From 8796a62a9cae649abf1e8a39a54fcf027795ce60 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 18 Nov 2022 20:00:47 -0500 Subject: [PATCH 001/206] Handle `LangError` from instantiate (fails for success case) This commit lets us grab what's in the output buffer after our call to `instantiate`, however we are unable to succesfully decode the `AccountId` from the success case. --- crates/env/src/api.rs | 8 +-- crates/env/src/backend.rs | 8 +-- crates/env/src/call/create_builder.rs | 49 +++++++++++++++---- crates/env/src/engine/off_chain/impls.rs | 6 ++- crates/env/src/engine/on_chain/impls.rs | 38 +++++++++++--- .../generator/as_dependency/contract_ref.rs | 6 ++- crates/ink/ir/src/ir/item_impl/constructor.rs | 15 ++++++ crates/ink/src/env_access.rs | 8 +-- .../call-builder/lib.rs | 43 ++++++++-------- 9 files changed, 131 insertions(+), 50 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index e4821480a67..9ef99b295b6 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -319,16 +319,18 @@ where /// - If the instantiation process runs out of gas. /// - If given insufficient endowment. /// - If the returned account ID failed to decode properly. -pub fn instantiate_contract( +pub fn instantiate_contract( params: &CreateParams, -) -> Result +) -> Result +// ) -> Result where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, + R: scale::Decode, { ::on_instance(|instance| { - TypedEnvBackend::instantiate_contract::(instance, params) + TypedEnvBackend::instantiate_contract::(instance, params) }) } diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index dc3a8832b0e..7988979acb1 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -439,14 +439,16 @@ pub trait TypedEnvBackend: EnvBackend { /// # Note /// /// For more details visit: [`instantiate_contract`][`crate::instantiate_contract`] - fn instantiate_contract( + fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result + ) -> Result + // ) -> Result where E: Environment, Args: scale::Encode, - Salt: AsRef<[u8]>; + Salt: AsRef<[u8]>, + R: scale::Decode; /// Terminates a smart contract. /// diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index c723dd9e1c0..603c9848fd3 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -116,12 +116,13 @@ where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: FromAccountId, + R: scale::Decode, + // R: FromAccountId, { /// Instantiates the contract and returns its account ID back to the caller. #[inline] pub fn instantiate(&self) -> Result { - crate::instantiate_contract(self).map(FromAccountId::from_account_id) + crate::instantiate_contract(self) //.map(FromAccountId::from_account_id) } } @@ -135,7 +136,7 @@ where endowment: Endowment, exec_input: Args, salt: Salt, - return_type: ReturnType, + return_type: R, _phantom: PhantomData E>, } @@ -195,11 +196,12 @@ pub fn build_create() -> CreateBuilder< Unset, Unset>, Unset, - R, + Unset>, > where E: Environment, - R: FromAccountId, + R: scale::Decode, + // R: FromAccountId, { CreateBuilder { code_hash: Default::default(), @@ -281,6 +283,34 @@ where } } +impl + CreateBuilder>> +where + E: Environment, +{ + /// Sets the type of the returned value upon the execution of the call. + /// + /// # 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`. + #[inline] + pub fn returns( + self, + ) -> CreateBuilder>> + { + CreateBuilder { + code_hash: self.code_hash, + gas_limit: self.gas_limit, + endowment: self.endowment, + exec_input: self.exec_input, + salt: self.salt, + return_type: Set(Default::default()), + _phantom: Default::default(), + } + } +} + impl CreateBuilder< E, @@ -347,7 +377,7 @@ impl Set, Set>, Set, - R, + Set>, > where E: Environment, @@ -362,7 +392,7 @@ where endowment: self.endowment.value(), exec_input: self.exec_input.value(), salt_bytes: self.salt.value(), - _return_type: self.return_type, + _return_type: Default::default(), } } } @@ -375,14 +405,15 @@ impl Set, Set>, Set, - R, + Set>, > where E: Environment, GasLimit: Unwrap, Args: scale::Encode, Salt: AsRef<[u8]>, - R: FromAccountId, + R: scale::Decode, + // R: FromAccountId, { /// Instantiates the contract using the given instantiation parameters. #[inline] diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 6954942e69c..e662578dd04 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -469,14 +469,16 @@ impl TypedEnvBackend for EnvInstance { ) } - fn instantiate_contract( + fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result + ) -> Result + // ) -> Result where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, + R: scale::Decode, { let _code_hash = params.code_hash(); let _gas_limit = params.gas_limit(); diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 036bb16d877..977409ded21 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -479,14 +479,16 @@ impl TypedEnvBackend for EnvInstance { } } - fn instantiate_contract( + fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result + ) -> Result + // ) -> Result where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, + R: scale::Decode, { let mut scoped = self.scoped_buffer(); let gas_limit = params.gas_limit(); @@ -503,7 +505,9 @@ impl TypedEnvBackend for EnvInstance { // This should change in the future but for that we need to add support // for constructors that may return values. // This is useful to support fallible constructors for example. - ext::instantiate( + // + // TODO: Support this output buffer? + let instantiate_result = ext::instantiate( enc_code_hash, gas_limit, enc_endowment, @@ -511,9 +515,31 @@ impl TypedEnvBackend for EnvInstance { out_address, out_return_value, salt, - )?; - let account_id = scale::Decode::decode(&mut &out_address[..])?; - Ok(account_id) + ); + + match instantiate_result { + Ok(()) => { + // The Ok case always needs to decode into an address + // + // This decodes to an `E::AccountId` + // + // But here I want an `Ok(E::AccountId)` + let account_id = scale::Decode::decode(&mut &out_address[..])?; + Ok(account_id) + + // let out = scale::Decode::decode(&mut &out_return_value[..])?; + // Ok(out) + } + Err(ext::Error::CalleeReverted) => { + // This decodes to an `Err(CouldNotReadInput)` + let out = scale::Decode::decode(&mut &out_return_value[..])?; + Ok(out) + } + Err(actual_error) => Err(actual_error.into()), + } + + // let account_id = scale::Decode::decode(&mut &out_address[..])?; + // Ok(account_id) } fn terminate_contract(&mut self, beneficiary: E::AccountId) -> ! 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..6e176b58c6d 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -403,6 +403,7 @@ impl ContractRef<'_> { let input_bindings = generator::input_bindings(constructor.inputs()); let input_types = generator::input_types(constructor.inputs()); let arg_list = generator::generate_argument_list(input_types.iter().cloned()); + let return_type = constructor.wrapped_output(); quote_spanned!(span => #( #attrs )* #[inline] @@ -416,9 +417,10 @@ impl ContractRef<'_> { ::ink::env::call::utils::Unset, ::ink::env::call::utils::Set<::ink::env::call::ExecutionInput<#arg_list>>, ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, - Self, + ::ink::env::call::utils::Unset<::ink::env::call::utils::ReturnType<#return_type>>, + // Self, > { - ::ink::env::call::build_create::() + ::ink::env::call::build_create::() .exec_input( ::ink::env::call::ExecutionInput::new( ::ink::env::call::Selector::new([ #( #selector_bytes ),* ]) diff --git a/crates/ink/ir/src/ir/item_impl/constructor.rs b/crates/ink/ir/src/ir/item_impl/constructor.rs index 276c26ce067..d1d326ad5ea 100644 --- a/crates/ink/ir/src/ir/item_impl/constructor.rs +++ b/crates/ink/ir/src/ir/item_impl/constructor.rs @@ -227,6 +227,21 @@ impl Constructor { syn::ReturnType::Type(_, return_type) => Some(return_type), } } + + /// Returns the return type of the constructor, but wrapped within a `Result`. + /// + /// This is used to to allow callers to handle certain types of errors which are not exposed + /// by constructors. + pub fn wrapped_output(&self) -> syn::Type { + let return_type = self + .output() + .map(quote::ToTokens::to_token_stream) + .unwrap_or_else(|| quote::quote! { Self }); + + syn::parse_quote! { + ::ink::ConstructorResult<#return_type> + } + } } #[cfg(test)] diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 1afdfbe8392..7218cf6cddf 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -469,15 +469,17 @@ where /// # Note /// /// For more details visit: [`ink_env::instantiate_contract`] - pub fn instantiate_contract( + pub fn instantiate_contract( self, params: &CreateParams, - ) -> Result + ) -> Result + // ) -> Result where Args: scale::Encode, Salt: AsRef<[u8]>, + R: scale::Decode, { - ink_env::instantiate_contract::(params) + ink_env::instantiate_contract::(params) } /// Invokes a contract message and returns its result. diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index f0f132b735a..4ca1cd83ba7 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -62,24 +62,35 @@ mod call_builder { code_hash: Hash, selector: [u8; 4], init_value: bool, - ) -> Option { + ) -> Option<::ink::LangError> { use ink::env::call::build_create; let result = build_create::< DefaultEnvironment, - constructors_return_value::ConstructorsReturnValueRef, + _, + // constructors_return_value::ConstructorsReturnValueRef, >() .code_hash(code_hash) .gas_limit(0) .endowment(0) .exec_input(ExecutionInput::new(Selector::new(selector)).push_arg(init_value)) .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) + .returns::>() .params() - .instantiate(); + .instantiate() + .expect("Error from the Contracts pallet."); + ::ink::env::debug_println!("Result from `instantiate` {:?}", &result); - // 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). - result.ok().map(|id| ink::ToAccountId::to_account_id(&id)) + match result { + Ok(_) => None, + Err(e @ ink::LangError::CouldNotReadInput) => Some(e), + Err(_) => { + unimplemented!("No other `LangError` variants exist at the moment.") + } + } } } @@ -205,14 +216,8 @@ mod call_builder { None, ) .await - .expect("Client failed to call `call_builder::call_instantiate`.") - .value - .expect("Dispatching `call_builder::call_instantiate` failed."); - - assert!( - call_result.is_some(), - "Call using valid selector failed, when it should've succeeded." - ); + .expect("Calling `call_builder::call_instantiate` failed"); + dbg!(&call_result.value); Ok(()) } @@ -254,14 +259,8 @@ mod call_builder { None, ) .await - .expect("Client failed to call `call_builder::call_instantiate`.") - .value - .expect("Dispatching `call_builder::call_instantiate` failed."); - - assert!( - call_result.is_none(), - "Call using invalid selector succeeded, when it should've failed." - ); + .expect("Client failed to call `call_builder::call_instantiate`."); + dbg!(&call_result.value); Ok(()) } From 95b80c475578b944e8911e2b55a1f1ccca61a6fb Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 25 Nov 2022 11:19:13 -0500 Subject: [PATCH 002/206] Change generic in `CreateBuilder` to be more consistent --- crates/env/src/call/create_builder.rs | 120 ++++++++++++++------------ 1 file changed, 63 insertions(+), 57 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 603c9848fd3..460718f9cba 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -127,7 +127,7 @@ where } /// Builds up contract instantiations. -pub struct CreateBuilder +pub struct CreateBuilder where E: Environment, { @@ -136,7 +136,7 @@ where endowment: Endowment, exec_input: Args, salt: Salt, - return_type: R, + return_type: RetType, _phantom: PhantomData E>, } @@ -189,18 +189,17 @@ where /// support in the off-chain testing environment. However, this code /// should work fine in on-chain environments. #[allow(clippy::type_complexity)] -pub fn build_create() -> CreateBuilder< +pub fn build_create() -> CreateBuilder< E, Unset, Unset, Unset, Unset>, Unset, - Unset>, + Unset>, > where E: Environment, - R: scale::Decode, // R: FromAccountId, { CreateBuilder { @@ -214,8 +213,8 @@ where } } -impl - CreateBuilder, GasLimit, Endowment, Args, Salt, R> +impl + CreateBuilder, GasLimit, Endowment, Args, Salt, RetType> where E: Environment, { @@ -224,7 +223,7 @@ where pub fn code_hash( self, code_hash: E::Hash, - ) -> CreateBuilder, GasLimit, Endowment, Args, Salt, R> { + ) -> CreateBuilder, GasLimit, Endowment, Args, Salt, RetType> { CreateBuilder { code_hash: Set(code_hash), gas_limit: self.gas_limit, @@ -237,8 +236,8 @@ where } } -impl - CreateBuilder, Endowment, Args, Salt, R> +impl + CreateBuilder, Endowment, Args, Salt, RetType> where E: Environment, { @@ -247,7 +246,7 @@ where pub fn gas_limit( self, gas_limit: u64, - ) -> CreateBuilder, Endowment, Args, Salt, R> { + ) -> CreateBuilder, Endowment, Args, Salt, RetType> { CreateBuilder { code_hash: self.code_hash, gas_limit: Set(gas_limit), @@ -260,8 +259,8 @@ where } } -impl - CreateBuilder, Args, Salt, R> +impl + CreateBuilder, Args, Salt, RetType> where E: Environment, { @@ -270,7 +269,7 @@ where pub fn endowment( self, endowment: E::Balance, - ) -> CreateBuilder, Args, Salt, R> { + ) -> CreateBuilder, Args, Salt, RetType> { CreateBuilder { code_hash: self.code_hash, gas_limit: self.gas_limit, @@ -283,35 +282,7 @@ where } } -impl - CreateBuilder>> -where - E: Environment, -{ - /// Sets the type of the returned value upon the execution of the call. - /// - /// # 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`. - #[inline] - pub fn returns( - self, - ) -> CreateBuilder>> - { - CreateBuilder { - code_hash: self.code_hash, - gas_limit: self.gas_limit, - endowment: self.endowment, - exec_input: self.exec_input, - salt: self.salt, - return_type: Set(Default::default()), - _phantom: Default::default(), - } - } -} - -impl +impl CreateBuilder< E, CodeHash, @@ -319,7 +290,7 @@ impl Endowment, Unset>, Salt, - R, + RetType, > where E: Environment, @@ -329,8 +300,15 @@ where pub fn exec_input( self, exec_input: ExecutionInput, - ) -> CreateBuilder>, Salt, R> - { + ) -> CreateBuilder< + E, + CodeHash, + GasLimit, + Endowment, + Set>, + Salt, + RetType, + > { CreateBuilder { code_hash: self.code_hash, gas_limit: self.gas_limit, @@ -343,8 +321,8 @@ where } } -impl - CreateBuilder, R> +impl + CreateBuilder, RetType> where E: Environment, { @@ -353,7 +331,7 @@ where pub fn salt_bytes( self, salt: Salt, - ) -> CreateBuilder, R> + ) -> CreateBuilder, RetType> where Salt: AsRef<[u8]>, { @@ -369,7 +347,35 @@ where } } -impl +impl + CreateBuilder>> +where + E: Environment, +{ + /// Sets the type of the returned value upon the execution of the call. + /// + /// # 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`. + #[inline] + pub fn returns( + self, + ) -> CreateBuilder>> + { + CreateBuilder { + code_hash: self.code_hash, + gas_limit: self.gas_limit, + endowment: self.endowment, + exec_input: self.exec_input, + salt: self.salt, + return_type: Set(Default::default()), + _phantom: Default::default(), + } + } +} + +impl CreateBuilder< E, Set, @@ -377,15 +383,15 @@ impl Set, Set>, Set, - Set>, + Set>, > where E: Environment, GasLimit: Unwrap, { - /// Sets the value transferred upon the execution of the call. + /// Finalizes the create builder, allowing it to instantiate a contract. #[inline] - pub fn params(self) -> CreateParams { + pub fn params(self) -> CreateParams { CreateParams { code_hash: self.code_hash.value(), gas_limit: self.gas_limit.unwrap_or_else(|| 0), @@ -397,7 +403,7 @@ where } } -impl +impl CreateBuilder< E, Set, @@ -405,19 +411,19 @@ impl Set, Set>, Set, - Set>, + Set>, > where E: Environment, GasLimit: Unwrap, Args: scale::Encode, Salt: AsRef<[u8]>, - R: scale::Decode, + RetType: scale::Decode, // R: FromAccountId, { /// Instantiates the contract using the given instantiation parameters. #[inline] - pub fn instantiate(self) -> Result { + pub fn instantiate(self) -> Result { self.params().instantiate() } } From a49fcb739d842d9b5ecdbc559f9e8a3591699b81 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 25 Nov 2022 13:00:21 -0500 Subject: [PATCH 003/206] Remove extra generic parameter I accidently introduced this not knowing that the generic `C` was for the return type --- crates/env/src/api.rs | 6 +++--- crates/env/src/backend.rs | 4 ++-- crates/env/src/engine/off_chain/impls.rs | 4 ++-- crates/env/src/engine/on_chain/impls.rs | 4 ++-- crates/ink/src/env_access.rs | 10 +++++----- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 9ef99b295b6..0eacbd9a084 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -319,8 +319,8 @@ where /// - If the instantiation process runs out of gas. /// - If given insufficient endowment. /// - If the returned account ID failed to decode properly. -pub fn instantiate_contract( - params: &CreateParams, +pub fn instantiate_contract( + params: &CreateParams, ) -> Result // ) -> Result where @@ -330,7 +330,7 @@ where R: scale::Decode, { ::on_instance(|instance| { - TypedEnvBackend::instantiate_contract::(instance, params) + TypedEnvBackend::instantiate_contract::(instance, params) }) } diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 7988979acb1..0589fd5e258 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -439,9 +439,9 @@ pub trait TypedEnvBackend: EnvBackend { /// # Note /// /// For more details visit: [`instantiate_contract`][`crate::instantiate_contract`] - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result // ) -> Result where diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index e662578dd04..ea093adfa97 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -469,9 +469,9 @@ impl TypedEnvBackend for EnvInstance { ) } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result // ) -> Result where diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 977409ded21..824d3691d7f 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -479,9 +479,9 @@ impl TypedEnvBackend for EnvInstance { } } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result // ) -> Result where diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 7218cf6cddf..c8fc1130e14 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -264,7 +264,7 @@ where /// # Example /// /// ``` - /// + /// /// #[ink::contract] /// pub mod only_owner { /// #[ink(storage)] @@ -342,7 +342,7 @@ where /// # Example /// /// ``` - /// + /// /// #[ink::contract] /// pub mod my_contract { /// #[ink(storage)] @@ -469,9 +469,9 @@ where /// # Note /// /// For more details visit: [`ink_env::instantiate_contract`] - pub fn instantiate_contract( + pub fn instantiate_contract( self, - params: &CreateParams, + params: &CreateParams, ) -> Result // ) -> Result where @@ -479,7 +479,7 @@ where Salt: AsRef<[u8]>, R: scale::Decode, { - ink_env::instantiate_contract::(params) + ink_env::instantiate_contract::(params) } /// Invokes a contract message and returns its result. From 8312fa87be7e3e173a483e69d61f49fda31c38d9 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 25 Nov 2022 13:42:21 -0500 Subject: [PATCH 004/206] Remove generic return type parameter from `CreateBuidler` codegen --- .../ink/codegen/src/generator/as_dependency/contract_ref.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 6e176b58c6d..4d8f970757a 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -417,10 +417,9 @@ impl ContractRef<'_> { ::ink::env::call::utils::Unset, ::ink::env::call::utils::Set<::ink::env::call::ExecutionInput<#arg_list>>, ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, - ::ink::env::call::utils::Unset<::ink::env::call::utils::ReturnType<#return_type>>, - // Self, + ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#return_type>>, > { - ::ink::env::call::build_create::() + ::ink::env::call::build_create::() .exec_input( ::ink::env::call::ExecutionInput::new( ::ink::env::call::Selector::new([ #( #selector_bytes ),* ]) @@ -429,6 +428,7 @@ impl ContractRef<'_> { .push_arg(#input_bindings) )* ) + .returns::<#return_type>() } ) } From 6e70be00a258fa19d32a0c76d81610afedb8ee38 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 25 Nov 2022 13:48:48 -0500 Subject: [PATCH 005/206] Hardcode assumption that `instantiate` returns a `ConstructorResult` --- crates/env/src/api.rs | 2 +- crates/env/src/backend.rs | 2 +- crates/env/src/call/create_builder.rs | 8 ++++++-- crates/env/src/engine/off_chain/impls.rs | 2 +- crates/env/src/engine/on_chain/impls.rs | 11 +++-------- .../src/generator/as_dependency/contract_ref.rs | 1 + crates/ink/src/env_access.rs | 6 +++--- .../lang-err-integration-tests/call-builder/lib.rs | 11 ++--------- 8 files changed, 18 insertions(+), 25 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 0eacbd9a084..8e2c2a097e1 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -321,7 +321,7 @@ where /// - If the returned account ID failed to decode properly. pub fn instantiate_contract( params: &CreateParams, -) -> Result +) -> Result<::ink_primitives::ConstructorResult> // ) -> Result where E: Environment, diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 0589fd5e258..ce4faabcd9d 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -442,7 +442,7 @@ pub trait TypedEnvBackend: EnvBackend { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result + ) -> Result<::ink_primitives::ConstructorResult> // ) -> Result where E: Environment, diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 460718f9cba..5150fd0fa06 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -121,7 +121,9 @@ where { /// Instantiates the contract and returns its account ID back to the caller. #[inline] - pub fn instantiate(&self) -> Result { + pub fn instantiate( + &self, + ) -> Result<::ink_primitives::ConstructorResult, crate::Error> { crate::instantiate_contract(self) //.map(FromAccountId::from_account_id) } } @@ -423,7 +425,9 @@ where { /// Instantiates the contract using the given instantiation parameters. #[inline] - pub fn instantiate(self) -> Result { + pub fn instantiate( + self, + ) -> Result<::ink_primitives::ConstructorResult, Error> { self.params().instantiate() } } diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index ea093adfa97..a7232e2ea32 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -472,7 +472,7 @@ impl TypedEnvBackend for EnvInstance { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result + ) -> Result<::ink_primitives::ConstructorResult> // ) -> Result where E: Environment, diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 824d3691d7f..bc9b504eec6 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -482,7 +482,7 @@ impl TypedEnvBackend for EnvInstance { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result + ) -> Result<::ink_primitives::ConstructorResult> // ) -> Result where E: Environment, @@ -501,12 +501,7 @@ impl TypedEnvBackend for EnvInstance { let out_address = &mut scoped.take(1024); let salt = params.salt_bytes().as_ref(); let out_return_value = &mut scoped.take_rest(); - // We currently do nothing with the `out_return_value` buffer. - // This should change in the future but for that we need to add support - // for constructors that may return values. - // This is useful to support fallible constructors for example. - // - // TODO: Support this output buffer? + let instantiate_result = ext::instantiate( enc_code_hash, gas_limit, @@ -525,7 +520,7 @@ impl TypedEnvBackend for EnvInstance { // // But here I want an `Ok(E::AccountId)` let account_id = scale::Decode::decode(&mut &out_address[..])?; - Ok(account_id) + Ok(Ok(account_id)) // let out = scale::Decode::decode(&mut &out_return_value[..])?; // Ok(out) 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 4d8f970757a..0bce63f10cc 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -417,6 +417,7 @@ impl ContractRef<'_> { ::ink::env::call::utils::Unset, ::ink::env::call::utils::Set<::ink::env::call::ExecutionInput<#arg_list>>, ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, + // TODO: May need to change this back to `Self` where `Self: ToAccountId` ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#return_type>>, > { ::ink::env::call::build_create::() diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index c8fc1130e14..adfd96821f3 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -264,7 +264,7 @@ where /// # Example /// /// ``` - /// + /// /// #[ink::contract] /// pub mod only_owner { /// #[ink(storage)] @@ -342,7 +342,7 @@ where /// # Example /// /// ``` - /// + /// /// #[ink::contract] /// pub mod my_contract { /// #[ink(storage)] @@ -472,7 +472,7 @@ where pub fn instantiate_contract( self, params: &CreateParams, - ) -> Result + ) -> Result<::ink_primitives::ConstructorResult> // ) -> Result where Args: scale::Encode, diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 4ca1cd83ba7..f7e1b7fcece 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -67,7 +67,6 @@ mod call_builder { let result = build_create::< DefaultEnvironment, - _, // constructors_return_value::ConstructorsReturnValueRef, >() .code_hash(code_hash) @@ -75,10 +74,7 @@ mod call_builder { .endowment(0) .exec_input(ExecutionInput::new(Selector::new(selector)).push_arg(init_value)) .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) - .returns::>() + .returns::() .params() .instantiate() .expect("Error from the Contracts pallet."); @@ -104,10 +100,7 @@ mod call_builder { async fn e2e_invalid_message_selector_can_be_handled( mut client: ink_e2e::Client, ) -> E2EResult<()> { - use call_builder::contract_types::ink_primitives::{ - types::AccountId as E2EAccountId, - LangError as E2ELangError, - }; + use call_builder::contract_types::ink_primitives::LangError as E2ELangError; let constructor = call_builder::constructors::new(); let contract_acc_id = client From 2fd4a822d6c6f47297ec41fdc5af342ba1a08099 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 25 Nov 2022 13:55:10 -0500 Subject: [PATCH 006/206] Update `CreateBuilder` codegen to just return `Self` --- .../ink/codegen/src/generator/as_dependency/contract_ref.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) 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 0bce63f10cc..adc4acfb04d 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -403,7 +403,6 @@ impl ContractRef<'_> { let input_bindings = generator::input_bindings(constructor.inputs()); let input_types = generator::input_types(constructor.inputs()); let arg_list = generator::generate_argument_list(input_types.iter().cloned()); - let return_type = constructor.wrapped_output(); quote_spanned!(span => #( #attrs )* #[inline] @@ -417,8 +416,7 @@ impl ContractRef<'_> { ::ink::env::call::utils::Unset, ::ink::env::call::utils::Set<::ink::env::call::ExecutionInput<#arg_list>>, ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, - // TODO: May need to change this back to `Self` where `Self: ToAccountId` - ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#return_type>>, + ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType>, > { ::ink::env::call::build_create::() .exec_input( @@ -429,7 +427,7 @@ impl ContractRef<'_> { .push_arg(#input_bindings) )* ) - .returns::<#return_type>() + .returns::() } ) } From 4d1f2bfa541e699a5af710c4bf2849d8e738a602 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 28 Nov 2022 16:36:19 -0500 Subject: [PATCH 007/206] Remove generic usage to fix formatting --- .../call-builder/lib.rs | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index f7e1b7fcece..40725095e58 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -65,19 +65,18 @@ mod call_builder { ) -> Option<::ink::LangError> { use ink::env::call::build_create; - let result = build_create::< - DefaultEnvironment, - // constructors_return_value::ConstructorsReturnValueRef, - >() - .code_hash(code_hash) - .gas_limit(0) - .endowment(0) - .exec_input(ExecutionInput::new(Selector::new(selector)).push_arg(init_value)) - .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) - .returns::() - .params() - .instantiate() - .expect("Error from the Contracts pallet."); + let result = build_create::() + .code_hash(code_hash) + .gas_limit(0) + .endowment(0) + .exec_input( + ExecutionInput::new(Selector::new(selector)).push_arg(init_value), + ) + .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) + .returns::() + .params() + .instantiate() + .expect("Error from the Contracts pallet."); ::ink::env::debug_println!("Result from `instantiate` {:?}", &result); match result { From f107cb1dd474b03dc2cba60a5e8be584234438cb Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 28 Nov 2022 16:39:10 -0500 Subject: [PATCH 008/206] Unwrap `ConstructorResult` in `contract-ref` E2E test --- examples/lang-err-integration-tests/contract-ref/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/lang-err-integration-tests/contract-ref/lib.rs b/examples/lang-err-integration-tests/contract-ref/lib.rs index 5bd914278a0..6e6fd34a90a 100755 --- a/examples/lang-err-integration-tests/contract-ref/lib.rs +++ b/examples/lang-err-integration-tests/contract-ref/lib.rs @@ -19,7 +19,10 @@ mod contract_ref { .salt_bytes(salt) .instantiate() .unwrap_or_else(|error| { - panic!("failed at instantiating the Flipper contract: {:?}", error) + panic!("Received an error from the Contracts pallet while instantiating Flipper {:?}", error) + }) + .unwrap_or_else(|error| { + panic!("Received a `LangError` while instatiating Flipper: {:?}", error) }); Self { flipper } From b6de9fc968fce60e077f3195ff1b045ac62fc424 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 28 Nov 2022 17:08:29 -0500 Subject: [PATCH 009/206] Clean up some comments --- crates/env/src/engine/on_chain/impls.rs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index bc9b504eec6..e677006d27a 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -514,27 +514,17 @@ impl TypedEnvBackend for EnvInstance { match instantiate_result { Ok(()) => { - // The Ok case always needs to decode into an address - // - // This decodes to an `E::AccountId` - // - // But here I want an `Ok(E::AccountId)` let account_id = scale::Decode::decode(&mut &out_address[..])?; Ok(Ok(account_id)) - - // let out = scale::Decode::decode(&mut &out_return_value[..])?; - // Ok(out) } Err(ext::Error::CalleeReverted) => { - // This decodes to an `Err(CouldNotReadInput)` + // We don't wrap manually with an extra `Err` like we do in the `Ok` case since the + // buffer already comes back in the form of `Err(LangError)` let out = scale::Decode::decode(&mut &out_return_value[..])?; Ok(out) } Err(actual_error) => Err(actual_error.into()), } - - // let account_id = scale::Decode::decode(&mut &out_address[..])?; - // Ok(account_id) } fn terminate_contract(&mut self, beneficiary: E::AccountId) -> ! From 5d221c3e0572d761bc505d6b7a8e3391a3c58d2b Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 28 Nov 2022 17:35:47 -0500 Subject: [PATCH 010/206] Bring back the assumption that we expect an `AccountId` Is supposed to help give better error messages if somebody uses a wrong type with the builder --- crates/env/src/api.rs | 4 ++-- crates/env/src/backend.rs | 6 +++--- crates/env/src/call/create_builder.rs | 10 ++++++---- crates/env/src/engine/off_chain/impls.rs | 4 ++-- crates/env/src/engine/on_chain/impls.rs | 4 ++-- crates/ink/src/env_access.rs | 4 ++-- .../lang-err-integration-tests/call-builder/lib.rs | 1 + 7 files changed, 18 insertions(+), 15 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 8e2c2a097e1..e1c18fd2208 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -321,13 +321,13 @@ where /// - If the returned account ID failed to decode properly. pub fn instantiate_contract( params: &CreateParams, -) -> Result<::ink_primitives::ConstructorResult> +) -> Result<::ink_primitives::ConstructorResult> // ) -> Result where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: scale::Decode, + // R: scale::Decode, { ::on_instance(|instance| { TypedEnvBackend::instantiate_contract::(instance, params) diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index ce4faabcd9d..1ec5ddffe47 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -442,13 +442,13 @@ pub trait TypedEnvBackend: EnvBackend { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result<::ink_primitives::ConstructorResult> + ) -> Result<::ink_primitives::ConstructorResult> // ) -> Result where E: Environment, Args: scale::Encode, - Salt: AsRef<[u8]>, - R: scale::Decode; + Salt: AsRef<[u8]>; + // R: scale::Decode; /// Terminates a smart contract. /// diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 5150fd0fa06..9a432f60465 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -116,15 +116,16 @@ where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: scale::Decode, - // R: FromAccountId, + // R: scale::Decode, + R: FromAccountId, { /// Instantiates the contract and returns its account ID back to the caller. #[inline] pub fn instantiate( &self, ) -> Result<::ink_primitives::ConstructorResult, crate::Error> { - crate::instantiate_contract(self) //.map(FromAccountId::from_account_id) + crate::instantiate_contract(self) + .and_then(|inner| Ok(inner.map(FromAccountId::from_account_id))) } } @@ -420,7 +421,8 @@ where GasLimit: Unwrap, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType: scale::Decode, + // RetType: scale::Decode, + RetType: FromAccountId, // R: FromAccountId, { /// Instantiates the contract using the given instantiation parameters. diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index a7232e2ea32..d1b34680c69 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -472,13 +472,13 @@ impl TypedEnvBackend for EnvInstance { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result<::ink_primitives::ConstructorResult> + ) -> Result<::ink_primitives::ConstructorResult> // ) -> Result where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: scale::Decode, + // R: scale::Decode, { let _code_hash = params.code_hash(); let _gas_limit = params.gas_limit(); diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index e677006d27a..a5f5c2405e4 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -482,13 +482,13 @@ impl TypedEnvBackend for EnvInstance { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result<::ink_primitives::ConstructorResult> + ) -> Result<::ink_primitives::ConstructorResult> // ) -> Result where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: scale::Decode, + // R: scale::Decode, { let mut scoped = self.scoped_buffer(); let gas_limit = params.gas_limit(); diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index adfd96821f3..22b58eb8dc6 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -472,12 +472,12 @@ where pub fn instantiate_contract( self, params: &CreateParams, - ) -> Result<::ink_primitives::ConstructorResult> + ) -> Result<::ink_primitives::ConstructorResult> // ) -> Result where Args: scale::Encode, Salt: AsRef<[u8]>, - R: scale::Decode, + // R: scale::Decode, { ink_env::instantiate_contract::(params) } diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 40725095e58..9d7423356b4 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -74,6 +74,7 @@ mod call_builder { ) .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) .returns::() + // .returns::<()>() .params() .instantiate() .expect("Error from the Contracts pallet."); From 7d94f75323c6fc95ee6ede87bd8d2c37575b08cc Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 28 Nov 2022 17:44:09 -0500 Subject: [PATCH 011/206] Remove unused method --- crates/ink/ir/src/ir/item_impl/constructor.rs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/crates/ink/ir/src/ir/item_impl/constructor.rs b/crates/ink/ir/src/ir/item_impl/constructor.rs index d1d326ad5ea..276c26ce067 100644 --- a/crates/ink/ir/src/ir/item_impl/constructor.rs +++ b/crates/ink/ir/src/ir/item_impl/constructor.rs @@ -227,21 +227,6 @@ impl Constructor { syn::ReturnType::Type(_, return_type) => Some(return_type), } } - - /// Returns the return type of the constructor, but wrapped within a `Result`. - /// - /// This is used to to allow callers to handle certain types of errors which are not exposed - /// by constructors. - pub fn wrapped_output(&self) -> syn::Type { - let return_type = self - .output() - .map(quote::ToTokens::to_token_stream) - .unwrap_or_else(|| quote::quote! { Self }); - - syn::parse_quote! { - ::ink::ConstructorResult<#return_type> - } - } } #[cfg(test)] From 798f9468f8f36eab7267e6e3c43f560e5a08e7aa Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 28 Nov 2022 17:54:02 -0500 Subject: [PATCH 012/206] Update doc tests for new builder pattern --- crates/ink/src/env_access.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 22b58eb8dc6..57d418c1386 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -444,7 +444,7 @@ where /// /// Instantiates another contract. /// #[ink(message)] /// pub fn instantiate_contract(&self) -> AccountId { - /// let create_params = build_create::() + /// let create_params = build_create::() /// .code_hash(Hash::from([0x42; 32])) /// .gas_limit(4000) /// .endowment(25) @@ -452,11 +452,20 @@ where /// ExecutionInput::new(Selector::new([0xCA, 0xFE, 0xBA, 0xBE])) /// .push_arg(42) /// .push_arg(true) - /// .push_arg(&[0x10u8; 32]) - /// ) + /// .push_arg(&[0x10u8; 32]), + /// ) /// .salt_bytes(&[0xCA, 0xFE, 0xBA, 0xBE]) + /// .returns::() /// .params(); - /// self.env().instantiate_contract(&create_params).unwrap_or_else(|err| panic!("instantiation must succeed: {:?}", err)) + /// self.env() + /// .instantiate_contract(&create_params) + /// .unwrap_or_else(|error| { + /// panic!( + /// "Received an error from the Contracts pallet while instantiating: {:?}", + /// error + /// ) + /// }) + /// .unwrap_or_else(|error| panic!("Received a `LangError` while instatiating: {:?}", error)) /// } /// # /// # } From 18d09227473543ddc67ae2b7bdb54bd3fd838bde Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 28 Nov 2022 18:04:59 -0500 Subject: [PATCH 013/206] Clean up some comments --- crates/env/src/api.rs | 2 -- crates/env/src/backend.rs | 2 -- crates/env/src/call/create_builder.rs | 11 +++++------ crates/env/src/engine/off_chain/impls.rs | 2 -- crates/env/src/engine/on_chain/impls.rs | 2 -- crates/ink/src/env_access.rs | 2 -- .../lang-err-integration-tests/call-builder/lib.rs | 1 - 7 files changed, 5 insertions(+), 17 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index e1c18fd2208..01f0a3d3d8b 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -322,12 +322,10 @@ where pub fn instantiate_contract( params: &CreateParams, ) -> Result<::ink_primitives::ConstructorResult> -// ) -> Result where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - // R: scale::Decode, { ::on_instance(|instance| { TypedEnvBackend::instantiate_contract::(instance, params) diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 1ec5ddffe47..041ab950fa6 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -443,12 +443,10 @@ pub trait TypedEnvBackend: EnvBackend { &mut self, params: &CreateParams, ) -> Result<::ink_primitives::ConstructorResult> - // ) -> Result where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>; - // R: scale::Decode; /// Terminates a smart contract. /// diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 9a432f60465..9e0af1dab74 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -116,7 +116,6 @@ where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - // R: scale::Decode, R: FromAccountId, { /// Instantiates the contract and returns its account ID back to the caller. @@ -203,7 +202,6 @@ pub fn build_create() -> CreateBuilder< > where E: Environment, - // R: FromAccountId, { CreateBuilder { code_hash: Default::default(), @@ -359,8 +357,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`. + /// Constructors are not able to return arbitrary values. Instead a succesful call to a + /// constructor returns the address at which the contract was instantiated. + /// + /// Therefore this must always be a reference (i.e `ContractRef`) to the contract you're trying + /// to instantiate. #[inline] pub fn returns( self, @@ -421,9 +422,7 @@ where GasLimit: Unwrap, Args: scale::Encode, Salt: AsRef<[u8]>, - // RetType: scale::Decode, RetType: FromAccountId, - // R: FromAccountId, { /// Instantiates the contract using the given instantiation parameters. #[inline] diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index d1b34680c69..ae8ab0056a9 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -473,12 +473,10 @@ impl TypedEnvBackend for EnvInstance { &mut self, params: &CreateParams, ) -> Result<::ink_primitives::ConstructorResult> - // ) -> Result where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - // R: scale::Decode, { let _code_hash = params.code_hash(); let _gas_limit = params.gas_limit(); diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index a5f5c2405e4..c9eaf3ba79f 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -483,12 +483,10 @@ impl TypedEnvBackend for EnvInstance { &mut self, params: &CreateParams, ) -> Result<::ink_primitives::ConstructorResult> - // ) -> Result where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - // R: scale::Decode, { let mut scoped = self.scoped_buffer(); let gas_limit = params.gas_limit(); diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 57d418c1386..dcd49f9dec5 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -482,11 +482,9 @@ where self, params: &CreateParams, ) -> Result<::ink_primitives::ConstructorResult> - // ) -> Result where Args: scale::Encode, Salt: AsRef<[u8]>, - // R: scale::Decode, { ink_env::instantiate_contract::(params) } diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 9d7423356b4..40725095e58 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -74,7 +74,6 @@ mod call_builder { ) .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) .returns::() - // .returns::<()>() .params() .instantiate() .expect("Error from the Contracts pallet."); From 06bba812b12c3fd5ba98ac6412783a0d2217ed38 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 28 Nov 2022 18:13:11 -0500 Subject: [PATCH 014/206] Fix Clippy warning --- crates/env/src/call/create_builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 9e0af1dab74..2949630058b 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -124,7 +124,7 @@ where &self, ) -> Result<::ink_primitives::ConstructorResult, crate::Error> { crate::instantiate_contract(self) - .and_then(|inner| Ok(inner.map(FromAccountId::from_account_id))) + .map(|inner| inner.map(FromAccountId::from_account_id)) } } From 612537e29f0d61cec42d5b93977817339236ae76 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 28 Nov 2022 18:14:26 -0500 Subject: [PATCH 015/206] Fix typo --- crates/env/src/call/create_builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 2949630058b..34c2df3930d 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -357,7 +357,7 @@ where /// /// # Note /// - /// Constructors are not able to return arbitrary values. Instead a succesful call to a + /// Constructors are not able to return arbitrary values. Instead a successful call to a /// constructor returns the address at which the contract was instantiated. /// /// Therefore this must always be a reference (i.e `ContractRef`) to the contract you're trying From 21751749d4d67e434d470706a8f8d8179a260ba9 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 28 Nov 2022 18:59:42 -0500 Subject: [PATCH 016/206] Add `try_instantiate` method to `CreateBuilder` --- crates/env/src/call/create_builder.rs | 32 +++++++++++++++++-- .../call-builder/lib.rs | 2 +- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 34c2df3930d..e7ccffa8566 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -120,7 +120,23 @@ where { /// Instantiates the contract and returns its account ID back to the caller. #[inline] - pub fn instantiate( + pub fn instantiate(&self) -> Result { + crate::instantiate_contract(self) + .map(|inner| { + inner.unwrap_or_else(|error| { + panic!("Received a `LangError` while instatiating: {:?}", error) + }) + }) + .map(FromAccountId::from_account_id) + } + + /// Instantiates the contract and returns its account ID back to the caller. + /// + /// # Note + /// + /// On failure this returns an [`ink_primitives::LangError`] which can be handled by the caller. + #[inline] + pub fn try_instantiate( &self, ) -> Result<::ink_primitives::ConstructorResult, crate::Error> { crate::instantiate_contract(self) @@ -426,9 +442,19 @@ where { /// Instantiates the contract using the given instantiation parameters. #[inline] - pub fn instantiate( + pub fn instantiate(self) -> Result { + self.params().instantiate() + } + + /// Instantiates the contract using the given instantiation parameters. + /// + /// # Note + /// + /// On failure this returns an [`ink_primitives::LangError`] which can be handled by the caller. + #[inline] + pub fn try_instantiate( self, ) -> Result<::ink_primitives::ConstructorResult, Error> { - self.params().instantiate() + self.params().try_instantiate() } } diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 40725095e58..04b803451cd 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -75,7 +75,7 @@ mod call_builder { .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) .returns::() .params() - .instantiate() + .try_instantiate() .expect("Error from the Contracts pallet."); ::ink::env::debug_println!("Result from `instantiate` {:?}", &result); From 44a83247f879c451fb2a5c5969661e23459a09b9 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 28 Nov 2022 19:04:36 -0500 Subject: [PATCH 017/206] Remove unneeded `unwrap` --- examples/lang-err-integration-tests/contract-ref/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/lang-err-integration-tests/contract-ref/lib.rs b/examples/lang-err-integration-tests/contract-ref/lib.rs index 6e6fd34a90a..44451188090 100755 --- a/examples/lang-err-integration-tests/contract-ref/lib.rs +++ b/examples/lang-err-integration-tests/contract-ref/lib.rs @@ -20,9 +20,6 @@ mod contract_ref { .instantiate() .unwrap_or_else(|error| { panic!("Received an error from the Contracts pallet while instantiating Flipper {:?}", error) - }) - .unwrap_or_else(|error| { - panic!("Received a `LangError` while instatiating Flipper: {:?}", error) }); Self { flipper } From 84d257dda0c246683c870150174c8b6c0758c451 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 28 Nov 2022 19:13:27 -0500 Subject: [PATCH 018/206] Remove debug logging --- examples/lang-err-integration-tests/call-builder/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 04b803451cd..aa169e99c4d 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -77,7 +77,6 @@ mod call_builder { .params() .try_instantiate() .expect("Error from the Contracts pallet."); - ::ink::env::debug_println!("Result from `instantiate` {:?}", &result); match result { Ok(_) => None, @@ -209,7 +208,6 @@ mod call_builder { ) .await .expect("Calling `call_builder::call_instantiate` failed"); - dbg!(&call_result.value); Ok(()) } @@ -252,7 +250,6 @@ mod call_builder { ) .await .expect("Client failed to call `call_builder::call_instantiate`."); - dbg!(&call_result.value); Ok(()) } From ffcca2c0725b65ac0442423a279d68b9ef4dd862 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 28 Nov 2022 19:19:56 -0500 Subject: [PATCH 019/206] Update doc test --- crates/env/src/call/create_builder.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index e7ccffa8566..d21b0d27fef 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -187,7 +187,7 @@ where /// # impl FromAccountId for MyContract { /// # fn from_account_id(account_id: AccountId) -> Self { Self } /// # } -/// let my_contract: MyContract = build_create::() +/// let my_contract: MyContract = build_create::() /// .code_hash(Hash::from([0x42; 32])) /// .gas_limit(4000) /// .endowment(25) @@ -198,6 +198,7 @@ where /// .push_arg(&[0x10u8; 32]) /// ) /// .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) +/// .returns::() /// .params() /// .instantiate() /// .unwrap(); From 91cd98f3a3f5996ddfc6bd4c248922e539b40e33 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 29 Nov 2022 15:13:03 -0500 Subject: [PATCH 020/206] Fix some typos Co-authored-by: Andrew Jones --- crates/env/src/call/create_builder.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index d21b0d27fef..026a137bcaa 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -124,7 +124,7 @@ where crate::instantiate_contract(self) .map(|inner| { inner.unwrap_or_else(|error| { - panic!("Received a `LangError` while instatiating: {:?}", error) + panic!("Received a `LangError` while instantiating: {:?}", error) }) }) .map(FromAccountId::from_account_id) @@ -370,7 +370,7 @@ impl where E: Environment, { - /// Sets the type of the returned value upon the execution of the call. + /// Sets the type of the returned value upon the execution of the constructor. /// /// # Note /// From e701230f3f76c7148e8ea6e624404bfa87f39ac0 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 29 Nov 2022 15:19:17 -0500 Subject: [PATCH 021/206] Mention panicking behaviour of `instantiate` methods --- crates/env/src/call/create_builder.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 026a137bcaa..445da795822 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -119,6 +119,11 @@ where R: FromAccountId, { /// Instantiates the contract and returns its account ID back to the caller. + /// + /// # Panics + /// + /// This method panics if it encounters an [`ink_primitives::LangError`]. If you want to handle + /// those use the [`try_instantiate`][`CreateParams::try_instantiate`] method instead. #[inline] pub fn instantiate(&self) -> Result { crate::instantiate_contract(self) @@ -442,6 +447,11 @@ where RetType: FromAccountId, { /// Instantiates the contract using the given instantiation parameters. + /// + /// # Panics + /// + /// This method panics if it encounters an [`ink_primitives::LangError`]. If you want to handle + /// those use the [`try_instantiate`][`CreateBuilder::try_instantiate`] method instead. #[inline] pub fn instantiate(self) -> Result { self.params().instantiate() From f2d85dddbd2e9a215ef8e9768813ed203c68b83c Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 29 Nov 2022 15:32:51 -0500 Subject: [PATCH 022/206] Improve error messages from wrong `returns()` type --- crates/env/src/call/create_builder.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 445da795822..120b758f42a 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -388,6 +388,8 @@ where pub fn returns( self, ) -> CreateBuilder>> + where + R: FromAccountId, { CreateBuilder { code_hash: self.code_hash, From addcda2a7b3dba59530f29443278d98517b00bf5 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 29 Nov 2022 15:48:27 -0500 Subject: [PATCH 023/206] Actually check return values from `call_instantiate` --- .../call-builder/lib.rs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index aa169e99c4d..f28d355a701 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -207,7 +207,14 @@ mod call_builder { None, ) .await - .expect("Calling `call_builder::call_instantiate` failed"); + .expect("Calling `call_builder::call_instantiate` failed") + .value + .expect("Dispatching `call_builder::call_instantiate` failed."); + + assert!( + call_result.is_none(), + "Call using valid selector failed, when it should've succeeded." + ); Ok(()) } @@ -216,6 +223,8 @@ mod call_builder { async fn e2e_create_builder_fails_with_invalid_selector( mut client: ink_e2e::Client, ) -> E2EResult<()> { + use call_builder::contract_types::ink_primitives::LangError as E2ELangError; + let constructor = call_builder::constructors::new(); let contract_acc_id = client .instantiate(&mut ink_e2e::eve(), constructor, 0, None) @@ -249,7 +258,14 @@ mod call_builder { None, ) .await - .expect("Client failed to call `call_builder::call_instantiate`."); + .expect("Client failed to call `call_builder::call_instantiate`.") + .value + .expect("Dispatching `call_builder::call_instantiate` failed."); + + assert!( + matches!(call_result, Some(E2ELangError::CouldNotReadInput)), + "Call using invalid selector succeeded, when it should've failed." + ); Ok(()) } From 4c99daf438360942e5949d866c379faabde07ab1 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 29 Nov 2022 16:59:44 -0500 Subject: [PATCH 024/206] Add test showing a reverting constructor with `Ok` in error buffer --- .../call-builder/lib.rs | 52 +++++++++++++++++++ .../constructors-return-value/lib.rs | 8 +++ 2 files changed, 60 insertions(+) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index f28d355a701..463875191ed 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -77,6 +77,7 @@ mod call_builder { .params() .try_instantiate() .expect("Error from the Contracts pallet."); + ::ink::env::debug_println!("Result from `instantiate` {:?}", &result); match result { Ok(_) => None, @@ -269,5 +270,56 @@ mod call_builder { Ok(()) } + + #[ink_e2e::test(additional_contracts = "../constructors-return-value/Cargo.toml")] + async fn e2e_create_builder_with_revert_constructor( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let constructor = call_builder::constructors::new(); + let contract_acc_id = client + .instantiate(&mut ink_e2e::ferdie(), constructor, 0, None) + .await + .expect("instantiate failed") + .account_id; + + let code_hash = client + .upload( + &mut ink_e2e::ferdie(), + constructors_return_value::CONTRACT_PATH, + None, + ) + .await + .expect("upload `constructors_return_value` failed") + .code_hash; + + let revert_new_selector = [0x90, 0xC9, 0xFE, 0x94]; + let call_result = dbg!( + client + .call( + &mut ink_e2e::ferdie(), + contract_acc_id.clone(), + call_builder::messages::call_instantiate( + ink_e2e::utils::runtime_hash_to_ink_hash::< + ink::env::DefaultEnvironment, + >(&code_hash), + revert_new_selector, + false, + ), + 0, + None, + ) + .await + .expect("Calling `call_builder::call_instantiate` failed") + .value + ) + .expect("Dispatching `call_builder::call_instantiate` failed."); + + assert!( + call_result.is_none(), + "Call using valid selector failed, when it should've succeeded." + ); + + Ok(()) + } } } 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 76fbae6e614..509feb2ecab 100644 --- a/examples/lang-err-integration-tests/constructors-return-value/lib.rs +++ b/examples/lang-err-integration-tests/constructors-return-value/lib.rs @@ -34,6 +34,14 @@ pub mod constructors_return_value { } } + #[ink(constructor)] + pub fn revert_new(_init_value: bool) -> Self { + ::ink::env::return_value::>( + ::ink::env::ReturnFlags::new_with_reverted(true), + &Ok(AccountId::from([0u8; 32])), + ) + } + /// Returns the current value of the contract storage. #[ink(message)] pub fn get_value(&self) -> bool { From 99c859bc8727eb0451ca0227c4003a59997bfdd7 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 29 Nov 2022 17:24:01 -0500 Subject: [PATCH 025/206] Check that we're only returning `LangError`s if the contract reverted --- crates/env/src/engine/on_chain/impls.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index c9eaf3ba79f..f9650eb33d6 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -518,7 +518,11 @@ impl TypedEnvBackend for EnvInstance { Err(ext::Error::CalleeReverted) => { // We don't wrap manually with an extra `Err` like we do in the `Ok` case since the // buffer already comes back in the form of `Err(LangError)` - let out = scale::Decode::decode(&mut &out_return_value[..])?; + let out: ::ink_primitives::ConstructorResult = + scale::Decode::decode(&mut &out_return_value[..])?; + + // Should only be handling `LangError` from this arm. + assert!(out.is_err(), "nice try haxx0r"); Ok(out) } Err(actual_error) => Err(actual_error.into()), From 323ed2dd1fe90e8a5b8fd04f4f014f2f60b60980 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 30 Nov 2022 15:52:44 -0500 Subject: [PATCH 026/206] Clean up the manual encoding test a bit --- crates/env/src/engine/on_chain/impls.rs | 12 ++--- .../call-builder/lib.rs | 50 +++++++++++-------- .../constructors-return-value/lib.rs | 1 + 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index f9650eb33d6..60f7594871a 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -517,12 +517,12 @@ impl TypedEnvBackend for EnvInstance { } Err(ext::Error::CalleeReverted) => { // We don't wrap manually with an extra `Err` like we do in the `Ok` case since the - // buffer already comes back in the form of `Err(LangError)` - let out: ::ink_primitives::ConstructorResult = - scale::Decode::decode(&mut &out_return_value[..])?; - - // Should only be handling `LangError` from this arm. - assert!(out.is_err(), "nice try haxx0r"); + // buffer already comes back in the form of `Err(LangError)` (assuming it's encoded + // by the ink! codegen and not the contract). + let out = ink_primitives::ConstructorResult::::decode( + &mut &out_return_value[..], + )?; + assert!(out.is_err(), "The callee reverted, but did not encode an error in the output buffer."); Ok(out) } Err(actual_error) => Err(actual_error.into()), diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 463875191ed..a8eb9996af1 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -293,30 +293,36 @@ mod call_builder { .code_hash; let revert_new_selector = [0x90, 0xC9, 0xFE, 0x94]; - let call_result = dbg!( - client - .call( - &mut ink_e2e::ferdie(), - contract_acc_id.clone(), - call_builder::messages::call_instantiate( - ink_e2e::utils::runtime_hash_to_ink_hash::< - ink::env::DefaultEnvironment, - >(&code_hash), - revert_new_selector, - false, - ), - 0, - None, - ) - .await - .expect("Calling `call_builder::call_instantiate` failed") - .value - ) - .expect("Dispatching `call_builder::call_instantiate` failed."); + let call_result = client + .call( + &mut ink_e2e::ferdie(), + contract_acc_id.clone(), + call_builder::messages::call_instantiate( + ink_e2e::utils::runtime_hash_to_ink_hash::< + ink::env::DefaultEnvironment, + >(&code_hash), + revert_new_selector, + false, + ), + 0, + None, + ) + .await; assert!( - call_result.is_none(), - "Call using valid selector failed, when it should've succeeded." + call_result.is_err(), + "Call execution should've failed, but didn't." + ); + let contains_err_msg = match call_result.unwrap_err() { + ink_e2e::Error::CallDryRun(dry_run) => { + String::from_utf8_lossy(&dry_run.debug_message) + .contains("The callee reverted, but did not encode an error in the output buffer.") + } + _ => false, + }; + assert!( + contains_err_msg, + "Call execution failed for an unexpected reason." ); Ok(()) 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 509feb2ecab..e06313aa80e 100644 --- a/examples/lang-err-integration-tests/constructors-return-value/lib.rs +++ b/examples/lang-err-integration-tests/constructors-return-value/lib.rs @@ -34,6 +34,7 @@ pub mod constructors_return_value { } } + /// A construcor which reverts and fills the output buffer with an arbitrary value. #[ink(constructor)] pub fn revert_new(_init_value: bool) -> Self { ::ink::env::return_value::>( From b6fc625e4a9052ddcf405c54ea7eca7aeeb081a3 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 1 Dec 2022 16:51:29 -0500 Subject: [PATCH 027/206] Add test for constructors which return a contract level error --- .../call-builder/lib.rs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index a8eb9996af1..34c4766e378 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -327,5 +327,53 @@ mod call_builder { Ok(()) } + + #[ink_e2e::test(additional_contracts = "../constructors-return-value/Cargo.toml")] + async fn e2e_create_builder_can_handle_contract_defined_constructor_error( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let constructor = call_builder::constructors::new(); + let contract_acc_id = client + .instantiate(&mut ink_e2e::ferdie(), constructor, 0, None) + .await + .expect("instantiate failed") + .account_id; + + let code_hash = client + .upload( + &mut ink_e2e::ferdie(), + constructors_return_value::CONTRACT_PATH, + None, + ) + .await + .expect("upload `constructors_return_value` failed") + .code_hash; + + let selector = ink::selector_bytes!("try_new"); + let call_result = dbg!( + client + .call( + &mut ink_e2e::ferdie(), + contract_acc_id.clone(), + call_builder::messages::call_instantiate( + ink_e2e::utils::runtime_hash_to_ink_hash::< + ink::env::DefaultEnvironment, + >(&code_hash), + selector, + false, + ), + 0, + None, + ) + .await + ) + .expect("Calling `call_builder::call_instantiate` failed") + .value + .expect("Dispatching `call_builder::call_instantiate` failed."); + + assert!(call_result.is_none(), "TODO"); + + Ok(()) + } } } From ac6b1978840547ba22d04ce162d3b6b670c54299 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sat, 3 Dec 2022 12:11:23 -0500 Subject: [PATCH 028/206] Add `CreateBuilder` message which calls a fallible constructor --- .../call-builder/lib.rs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 34c4766e378..b19e0623f60 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -87,6 +87,38 @@ mod call_builder { } } } + + #[ink(message)] + pub fn call_instantiate_with_result( + &mut self, + code_hash: Hash, + selector: [u8; 4], + init_value: bool, + ) -> Option<::ink::LangError> { + use ink::env::call::build_create; + + let result = build_create::() + .code_hash(code_hash) + .gas_limit(0) + .endowment(0) + .exec_input( + ExecutionInput::new(Selector::new(selector)).push_arg(init_value), + ) + .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) + .returns::>() + .params() + .try_instantiate() + .expect("Error from the Contracts pallet."); + ::ink::env::debug_println!("Result from `instantiate` {:?}", &result); + + match result { + Ok(_) => None, + Err(e @ ink::LangError::CouldNotReadInput) => Some(e), + Err(_) => { + unimplemented!("No other `LangError` variants exist at the moment.") + } + } + } } #[cfg(all(test, feature = "e2e-tests"))] From b06a9f8404942c304c55a08a54c62ef841482994 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 5 Dec 2022 11:49:19 -0500 Subject: [PATCH 029/206] Add test which calls falliable constructor for success case --- .../call-builder/lib.rs | 58 +++++++++++++++++-- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index b19e0623f60..e25cd74b7f1 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -360,6 +360,55 @@ mod call_builder { Ok(()) } + #[ink_e2e::test(additional_contracts = "../constructors-return-value/Cargo.toml")] + async fn e2e_create_builder_can_handle_contract_defined_constructor_success( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let constructor = call_builder::constructors::new(); + let contract_acc_id = client + .instantiate(&mut ink_e2e::ferdie(), constructor, 0, None) + .await + .expect("instantiate failed") + .account_id; + + let code_hash = client + .upload( + &mut ink_e2e::ferdie(), + constructors_return_value::CONTRACT_PATH, + None, + ) + .await + .expect("upload `constructors_return_value` failed") + .code_hash; + + let selector = ink::selector_bytes!("try_new"); + let success = true; + let call_result = dbg!( + client + .call( + &mut ink_e2e::ferdie(), + contract_acc_id.clone(), + call_builder::messages::call_instantiate_with_result( + ink_e2e::utils::runtime_hash_to_ink_hash::< + ink::env::DefaultEnvironment, + >(&code_hash), + selector, + success, + ), + 0, + None, + ) + .await + .expect("Calling `call_builder::call_instantiate` failed") + .value + ) + .expect("Dispatching `call_builder::call_instantiate` failed."); + + assert!(call_result.is_none(), "TODO"); + + Ok(()) + } + #[ink_e2e::test(additional_contracts = "../constructors-return-value/Cargo.toml")] async fn e2e_create_builder_can_handle_contract_defined_constructor_error( mut client: ink_e2e::Client, @@ -382,25 +431,26 @@ mod call_builder { .code_hash; let selector = ink::selector_bytes!("try_new"); + let success = false; let call_result = dbg!( client .call( &mut ink_e2e::ferdie(), contract_acc_id.clone(), - call_builder::messages::call_instantiate( + call_builder::messages::call_instantiate_with_result( ink_e2e::utils::runtime_hash_to_ink_hash::< ink::env::DefaultEnvironment, >(&code_hash), selector, - false, + success, ), 0, None, ) .await + .expect("Calling `call_builder::call_instantiate` failed") + .value ) - .expect("Calling `call_builder::call_instantiate` failed") - .value .expect("Dispatching `call_builder::call_instantiate` failed."); assert!(call_result.is_none(), "TODO"); From 7d664a0bdd5b3fe279dbd8d95b6de8d206c04311 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 5 Dec 2022 13:14:48 -0500 Subject: [PATCH 030/206] Get verbose `instantiate_contract_with_result` decoding past typechecker --- crates/env/src/engine/on_chain/impls.rs | 97 +++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 60f7594871a..9efec7beec7 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -529,6 +529,103 @@ impl TypedEnvBackend for EnvInstance { } } + fn instantiate_contract_with_result( + &mut self, + params: &CreateParams, + ) -> Result< + ::ink_primitives::ConstructorResult< + ::core::result::Result, + >, + > + where + E: Environment, + Args: scale::Encode, + Salt: AsRef<[u8]>, + ContractError: scale::Decode, + { + let mut scoped = self.scoped_buffer(); + let gas_limit = params.gas_limit(); + let enc_code_hash = scoped.take_encoded(params.code_hash()); + let enc_endowment = scoped.take_encoded(params.endowment()); + let enc_input = scoped.take_encoded(params.exec_input()); + // We support `AccountId` types with an encoding that requires up to + // 1024 bytes. Beyond that limit ink! contracts will trap for now. + // In the default configuration encoded `AccountId` require 32 bytes. + let out_address = &mut scoped.take(1024); + let salt = params.salt_bytes().as_ref(); + let out_return_value = &mut scoped.take_rest(); + + let instantiate_result = ext::instantiate( + enc_code_hash, + gas_limit, + enc_endowment, + enc_input, + out_address, + out_return_value, + salt, + ); + + use scale::Decode; + match instantiate_result { + Ok(()) => { + let account_id: E::AccountId = + scale::Decode::decode(&mut &out_address[..])?; + Ok(ink_primitives::ConstructorResult::Ok(Ok(account_id))) + } + Err(ext::Error::CalleeReverted) => { + // First, we check if dispatch even succeeded based off buffer decoding. + let out = + as scale::Decode>::decode( + &mut &out_return_value[..], + ); + + match out { + Ok(decoded_value) => { + // We were able to decode the buffer, which means dispatch probably failed. + match decoded_value { + ink_primitives::ConstructorResult::Ok(()) => + unreachable!("If dispatch failed, we shouldn't have an Ok encoded into the buffer."), + ink_primitives::ConstructorResult::Err(lang_err) => { + Ok(ink_primitives::ConstructorResult::Err(lang_err)) + } + } + } + Err(_) => { + // We were unable to decode the buffer which means dispatch probably + // succeeded. + // + // Try decoding the buffer differently for the success dispatch case. + let out = ink_primitives::ConstructorResult::< + ::core::result::Result<(), ContractError>, + >::decode( + &mut &out_return_value[..] + ); + + match out { + Ok(output_result) => { + match output_result { + ink_primitives::ConstructorResult::Ok(contract_error) => { + // This should only be an Err(ContractError), because if we + // had succeeded we'd be going down the decoding into an + // `AccountId` branch, not the revert branch + // + // Unwrapping the error is here to satisfy the type checker + let contract_error = contract_error.unwrap_err(); + Ok(ink_primitives::ConstructorResult::Ok(Err(contract_error))) + } + ink_primitives::ConstructorResult::Err(_) => + unreachable!("We only encode the Ok case, so somebody probably manually wrote to the buffer."), + } + } + Err(_) => unreachable!("Unable to decode this, so somebody probably manually wrote to the buffer."), + } + } + } + } + Err(actual_error) => Err(actual_error.into()), + } + } + fn terminate_contract(&mut self, beneficiary: E::AccountId) -> ! where E: Environment, From f874c97c6a9a14142e2675fca037f4f3fc729ed9 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 5 Dec 2022 17:36:44 -0500 Subject: [PATCH 031/206] Add `try_instantiate_with_result` to `CreateBuilder` --- crates/env/src/api.rs | 21 ++++++++ crates/env/src/backend.rs | 15 ++++++ crates/env/src/call/create_builder.rs | 65 +++++++++++++++++++++++- crates/env/src/engine/off_chain/impls.rs | 22 ++++++++ crates/ink/src/env_access.rs | 24 ++++++++- 5 files changed, 143 insertions(+), 4 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 01f0a3d3d8b..cad6e207622 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -332,6 +332,27 @@ where }) } +/// TODO +pub fn instantiate_contract_with_result( + params: &CreateParams, +) -> Result< + ::ink_primitives::ConstructorResult< + ::core::result::Result, + >, +> +where + E: Environment, + Args: scale::Encode, + Salt: AsRef<[u8]>, + ContractError: scale::Decode, +{ + ::on_instance(|instance| { + TypedEnvBackend::instantiate_contract_with_result::( + instance, params, + ) + }) +} + /// Terminates the existence of the currently executed smart contract. /// /// This removes the calling account and transfers all remaining balance diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 041ab950fa6..f107f3c0bb6 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -448,6 +448,21 @@ pub trait TypedEnvBackend: EnvBackend { Args: scale::Encode, Salt: AsRef<[u8]>; + /// TODO + fn instantiate_contract_with_result( + &mut self, + params: &CreateParams, + ) -> Result< + ::ink_primitives::ConstructorResult< + ::core::result::Result, + >, + > + where + E: Environment, + Args: scale::Encode, + Salt: AsRef<[u8]>, + ContractError: scale::Decode; + /// Terminates a smart contract. /// /// # Note diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 120b758f42a..5a251aabede 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -149,6 +149,31 @@ where } } +impl + CreateParams> +where + E: Environment, + Args: scale::Encode, + Salt: AsRef<[u8]>, + R: FromAccountId, + ContractError: scale::Decode, +{ + /// Instantiates the contract and returns its account ID back to the caller. + /// + /// # Note + /// + /// On failure this returns an [`ink_primitives::LangError`] which can be handled by the caller. + #[inline] + pub fn try_instantiate_with_result( + &self, + ) -> Result< + ::ink_primitives::ConstructorResult>, + crate::Error, + > { + crate::instantiate_contract_with_result(self) + } +} + /// Builds up contract instantiations. pub struct CreateBuilder where @@ -388,8 +413,8 @@ where pub fn returns( self, ) -> CreateBuilder>> - where - R: FromAccountId, +// where + // R: FromAccountId, { CreateBuilder { code_hash: self.code_hash, @@ -471,3 +496,39 @@ where self.params().try_instantiate() } } + +impl + CreateBuilder< + E, + Set, + GasLimit, + Set, + Set>, + Set, + Set>>, + > +where + E: Environment, + GasLimit: Unwrap, + Args: scale::Encode, + Salt: AsRef<[u8]>, + RetType: FromAccountId, + ContractError: scale::Decode, +{ + /// Instantiates the contract using the given instantiation parameters. + /// + /// # Note + /// + /// On failure this returns an [`ink_primitives::LangError`] which can be handled by the caller. + #[inline] + pub fn try_instantiate_with_result( + self, + ) -> Result< + ::ink_primitives::ConstructorResult< + ::core::result::Result, + >, + Error, + > { + self.params().try_instantiate_with_result() + } +} diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index ae8ab0056a9..6c74e428524 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -486,6 +486,28 @@ impl TypedEnvBackend for EnvInstance { unimplemented!("off-chain environment does not support contract instantiation") } + fn instantiate_contract_with_result( + &mut self, + params: &CreateParams, + ) -> Result< + ::ink_primitives::ConstructorResult< + ::core::result::Result, + >, + > + where + E: Environment, + Args: scale::Encode, + Salt: AsRef<[u8]>, + ContractError: scale::Decode, + { + let _code_hash = params.code_hash(); + let _gas_limit = params.gas_limit(); + let _endowment = params.endowment(); + let _input = params.exec_input(); + let _salt_bytes = params.salt_bytes(); + unimplemented!("off-chain environment does not support contract instantiation") + } + fn terminate_contract(&mut self, beneficiary: E::AccountId) -> ! where E: Environment, diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index dcd49f9dec5..917220d2269 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -264,7 +264,7 @@ where /// # Example /// /// ``` - /// + /// /// #[ink::contract] /// pub mod only_owner { /// #[ink(storage)] @@ -342,7 +342,7 @@ where /// # Example /// /// ``` - /// + /// /// #[ink::contract] /// pub mod my_contract { /// #[ink(storage)] @@ -489,6 +489,26 @@ where ink_env::instantiate_contract::(params) } + /// TODO + pub fn instantiate_contract_with_result( + self, + params: &CreateParams, + ) -> Result< + ::ink_primitives::ConstructorResult< + ::core::result::Result, + >, + > + where + E: Environment, + Args: scale::Encode, + Salt: AsRef<[u8]>, + ContractError: scale::Decode, + { + ink_env::instantiate_contract_with_result::( + params, + ) + } + /// Invokes a contract message and returns its result. /// /// # Example From c29895a9df42a153cff96e5c3456eb3a1500a429 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 5 Dec 2022 17:37:02 -0500 Subject: [PATCH 032/206] Clean up decoding logic for output from `seal_instatiate` --- crates/env/src/engine/on_chain/impls.rs | 59 ++++++++++--------------- 1 file changed, 23 insertions(+), 36 deletions(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 9efec7beec7..eb1f6945c71 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -522,6 +522,7 @@ impl TypedEnvBackend for EnvInstance { let out = ink_primitives::ConstructorResult::::decode( &mut &out_return_value[..], )?; + // TODO: Remove this assert!(out.is_err(), "The callee reverted, but did not encode an error in the output buffer."); Ok(out) } @@ -573,53 +574,39 @@ impl TypedEnvBackend for EnvInstance { Ok(ink_primitives::ConstructorResult::Ok(Ok(account_id))) } Err(ext::Error::CalleeReverted) => { - // First, we check if dispatch even succeeded based off buffer decoding. let out = as scale::Decode>::decode( &mut &out_return_value[..], - ); + ) + .expect("Failed to decode into `ConstructorResult<()>`"); match out { - Ok(decoded_value) => { - // We were able to decode the buffer, which means dispatch probably failed. - match decoded_value { - ink_primitives::ConstructorResult::Ok(()) => - unreachable!("If dispatch failed, we shouldn't have an Ok encoded into the buffer."), - ink_primitives::ConstructorResult::Err(lang_err) => { - Ok(ink_primitives::ConstructorResult::Err(lang_err)) - } - } - } - Err(_) => { - // We were unable to decode the buffer which means dispatch probably - // succeeded. - // - // Try decoding the buffer differently for the success dispatch case. - let out = ink_primitives::ConstructorResult::< - ::core::result::Result<(), ContractError>, - >::decode( + ink_primitives::ConstructorResult::Ok(()) => { + let out = , + > as scale::Decode>::decode( &mut &out_return_value[..] - ); + ) + .expect("Failed to decode into a `ContractError`"); match out { - Ok(output_result) => { - match output_result { - ink_primitives::ConstructorResult::Ok(contract_error) => { - // This should only be an Err(ContractError), because if we - // had succeeded we'd be going down the decoding into an - // `AccountId` branch, not the revert branch - // - // Unwrapping the error is here to satisfy the type checker - let contract_error = contract_error.unwrap_err(); - Ok(ink_primitives::ConstructorResult::Ok(Err(contract_error))) - } - ink_primitives::ConstructorResult::Err(_) => - unreachable!("We only encode the Ok case, so somebody probably manually wrote to the buffer."), - } + ink_primitives::ConstructorResult::Ok(contract_error) => { + // This should only be an Err(ContractError), because if the call + // to the constructor had succeeded we've be doing down the + // "decoding into an `AccountId`" branch. + // + // Unwrapping the error is here to satisfy the type checker + let contract_error = contract_error.unwrap_err(); + Ok(ink_primitives::ConstructorResult::Ok(Err( + contract_error, + ))) } - Err(_) => unreachable!("Unable to decode this, so somebody probably manually wrote to the buffer."), + _ => unreachable!("We already decoded into a `ConstructorResult::Ok` earlier."), } } + ink_primitives::ConstructorResult::Err(lang_err) => { + Ok(ink_primitives::ConstructorResult::Err(lang_err)) + } } } Err(actual_error) => Err(actual_error.into()), From dbb079e5ae1c2199ac300cce53bcf754ff9ca98c Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 5 Dec 2022 17:37:42 -0500 Subject: [PATCH 033/206] Small cleanups in `call-builder` E2E tests --- .../call-builder/lib.rs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index e25cd74b7f1..6f37152ccb6 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -105,9 +105,12 @@ mod call_builder { ExecutionInput::new(Selector::new(selector)).push_arg(init_value), ) .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) - .returns::>() + .returns::>() .params() - .try_instantiate() + .try_instantiate_with_result() .expect("Error from the Contracts pallet."); ::ink::env::debug_println!("Result from `instantiate` {:?}", &result); @@ -303,6 +306,7 @@ mod call_builder { Ok(()) } + // TODO: Also add something similar for fallible constructors #[ink_e2e::test(additional_contracts = "../constructors-return-value/Cargo.toml")] async fn e2e_create_builder_with_revert_constructor( mut client: ink_e2e::Client, @@ -366,14 +370,14 @@ mod call_builder { ) -> E2EResult<()> { let constructor = call_builder::constructors::new(); let contract_acc_id = client - .instantiate(&mut ink_e2e::ferdie(), constructor, 0, None) + .instantiate(&mut ink_e2e::alice(), constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client .upload( - &mut ink_e2e::ferdie(), + &mut ink_e2e::alice(), constructors_return_value::CONTRACT_PATH, None, ) @@ -386,7 +390,7 @@ mod call_builder { let call_result = dbg!( client .call( - &mut ink_e2e::ferdie(), + &mut ink_e2e::alice(), contract_acc_id.clone(), call_builder::messages::call_instantiate_with_result( ink_e2e::utils::runtime_hash_to_ink_hash::< @@ -415,14 +419,14 @@ mod call_builder { ) -> E2EResult<()> { let constructor = call_builder::constructors::new(); let contract_acc_id = client - .instantiate(&mut ink_e2e::ferdie(), constructor, 0, None) + .instantiate(&mut ink_e2e::bob(), constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client .upload( - &mut ink_e2e::ferdie(), + &mut ink_e2e::bob(), constructors_return_value::CONTRACT_PATH, None, ) @@ -435,7 +439,7 @@ mod call_builder { let call_result = dbg!( client .call( - &mut ink_e2e::ferdie(), + &mut ink_e2e::bob(), contract_acc_id.clone(), call_builder::messages::call_instantiate_with_result( ink_e2e::utils::runtime_hash_to_ink_hash::< From 6125690dff4bf6263811fcbe5de1de3ae8df6b02 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 5 Dec 2022 17:39:04 -0500 Subject: [PATCH 034/206] RustFmt `env_access` --- crates/ink/src/env_access.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 917220d2269..56b0cd80b1c 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -264,7 +264,7 @@ where /// # Example /// /// ``` - /// + /// /// #[ink::contract] /// pub mod only_owner { /// #[ink(storage)] @@ -342,7 +342,7 @@ where /// # Example /// /// ``` - /// + /// /// #[ink::contract] /// pub mod my_contract { /// #[ink(storage)] From aa4f897b3ab3bbda9da8e3583083406eec704aaa Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 5 Dec 2022 17:42:45 -0500 Subject: [PATCH 035/206] Remove unused import --- crates/env/src/engine/on_chain/impls.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index eb1f6945c71..2e77e2209b7 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -566,7 +566,6 @@ impl TypedEnvBackend for EnvInstance { salt, ); - use scale::Decode; match instantiate_result { Ok(()) => { let account_id: E::AccountId = From 053218fe68d39c2fbb5cdfa42a143bece5a1a6cf Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 6 Dec 2022 14:14:53 -0500 Subject: [PATCH 036/206] Flip decoding logic so that it's more strict initially Otherwise we may end up decoding a `Result` too eagerly and end up in a wrong branch. --- crates/env/src/engine/on_chain/impls.rs | 63 +++++++++++++------------ 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 2e77e2209b7..bc136351b5b 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -573,38 +573,39 @@ impl TypedEnvBackend for EnvInstance { Ok(ink_primitives::ConstructorResult::Ok(Ok(account_id))) } Err(ext::Error::CalleeReverted) => { - let out = - as scale::Decode>::decode( - &mut &out_return_value[..], - ) - .expect("Failed to decode into `ConstructorResult<()>`"); - - match out { - ink_primitives::ConstructorResult::Ok(()) => { - let out = , - > as scale::Decode>::decode( - &mut &out_return_value[..] - ) - .expect("Failed to decode into a `ContractError`"); - - match out { - ink_primitives::ConstructorResult::Ok(contract_error) => { - // This should only be an Err(ContractError), because if the call - // to the constructor had succeeded we've be doing down the - // "decoding into an `AccountId`" branch. - // - // Unwrapping the error is here to satisfy the type checker - let contract_error = contract_error.unwrap_err(); - Ok(ink_primitives::ConstructorResult::Ok(Err( - contract_error, - ))) - } - _ => unreachable!("We already decoded into a `ConstructorResult::Ok` earlier."), - } + let decoding_result = , + > as scale::Decode>::decode( + &mut &out_return_value[..] + ); + + match decoding_result { + Ok(constructor_result) => { + let contract_result = constructor_result.expect( + "If dispatch had failed, we shouldn't have been able to decode \ + the nested `Result`." + ); + + let contract_error = contract_result.expect_err( + "Since the contract reverted, we only expect an `Error` from the constructor. \ + Otherwise we would be in the `AccountId` branch."); + + Ok(ink_primitives::ConstructorResult::Ok(Err(contract_error))) } - ink_primitives::ConstructorResult::Err(lang_err) => { - Ok(ink_primitives::ConstructorResult::Err(lang_err)) + Err(_) => { + // If we hit this branch it likely means dispatch failed, but we need to + // check the buffer again to confirm. + let out = + as scale::Decode>::decode( + &mut &out_return_value[..], + )?; + + let lang_error = out.expect_err( + "If dispatch had succeeded, we would either be in the `AccountId` branch \ + or we would've been able to decode into a nested `Result` earlier." + ); + + Ok(ink_primitives::ConstructorResult::Err(lang_error)) } } } From 77c790f333c1a00540df7155671c096ad29df6e8 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 6 Dec 2022 14:16:16 -0500 Subject: [PATCH 037/206] Add test which revert a fallible constructor --- .../call-builder/lib.rs | 123 ++++++++++++++++++ .../constructors-return-value/lib.rs | 18 ++- 2 files changed, 140 insertions(+), 1 deletion(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 6f37152ccb6..36a6e96f2ff 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -461,5 +461,128 @@ mod call_builder { Ok(()) } + + #[ink_e2e::test(additional_contracts = "../constructors-return-value/Cargo.toml")] + async fn e2e_create_builder_with_fallible_revert_constructor_encodes_ok( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let constructor = call_builder::constructors::new(); + let contract_acc_id = client + .instantiate(&mut ink_e2e::charlie(), constructor, 0, None) + .await + .expect("instantiate failed") + .account_id; + + let code_hash = client + .upload( + &mut ink_e2e::charlie(), + constructors_return_value::CONTRACT_PATH, + None, + ) + .await + .expect("upload `constructors_return_value` failed") + .code_hash; + + let selector = ink::selector_bytes!("try_revert_new"); + let init_value = true; + let call_result = client + .call( + &mut ink_e2e::charlie(), + contract_acc_id.clone(), + call_builder::messages::call_instantiate_with_result( + ink_e2e::utils::runtime_hash_to_ink_hash::< + ink::env::DefaultEnvironment, + >(&code_hash), + selector, + init_value, + ), + 0, + None, + ) + .await; + + assert!( + call_result.is_err(), + "Call execution should've failed, but didn't." + ); + + let contains_err_msg = match call_result.unwrap_err() { + ink_e2e::Error::CallDryRun(dry_run) => { + String::from_utf8_lossy(&dry_run.debug_message) + .contains( + "Since the contract reverted, we only expect an `Error` from the constructor. \ + Otherwise we would be in the `AccountId` branch." + ) + } + _ => false, + }; + assert!( + contains_err_msg, + "Call execution failed for an unexpected reason." + ); + + Ok(()) + } + + #[ink_e2e::test(additional_contracts = "../constructors-return-value/Cargo.toml")] + async fn e2e_create_builder_with_fallible_revert_constructor_encodes_err( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let constructor = call_builder::constructors::new(); + let contract_acc_id = client + .instantiate(&mut ink_e2e::dave(), constructor, 0, None) + .await + .expect("instantiate failed") + .account_id; + + let code_hash = client + .upload( + &mut ink_e2e::dave(), + constructors_return_value::CONTRACT_PATH, + None, + ) + .await + .expect("upload `constructors_return_value` failed") + .code_hash; + + let selector = ink::selector_bytes!("try_revert_new"); + let init_value = false; + let call_result = client + .call( + &mut ink_e2e::dave(), + contract_acc_id.clone(), + call_builder::messages::call_instantiate_with_result( + ink_e2e::utils::runtime_hash_to_ink_hash::< + ink::env::DefaultEnvironment, + >(&code_hash), + selector, + init_value, + ), + 0, + None, + ) + .await; + + assert!( + call_result.is_err(), + "Call execution should've failed, but didn't." + ); + + let contains_err_msg = match call_result.unwrap_err() { + ink_e2e::Error::CallDryRun(dry_run) => { + String::from_utf8_lossy(&dry_run.debug_message).contains( + "If dispatch had failed, we shouldn't have been able to decode \ + the nested `Result`.", + ) + } + _ => false, + }; + assert!( + contains_err_msg, + "Call execution failed for an unexpected reason." + ); + + Ok(()) + } } } 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 e06313aa80e..d4277641798 100644 --- a/examples/lang-err-integration-tests/constructors-return-value/lib.rs +++ b/examples/lang-err-integration-tests/constructors-return-value/lib.rs @@ -34,7 +34,8 @@ pub mod constructors_return_value { } } - /// A construcor which reverts and fills the output buffer with an arbitrary value. + /// A constructor which reverts and fills the output buffer with an erronenously encoded + /// return value. #[ink(constructor)] pub fn revert_new(_init_value: bool) -> Self { ::ink::env::return_value::>( @@ -43,6 +44,21 @@ pub mod constructors_return_value { ) } + /// A constructor which reverts and fills the output buffer with an erronenously encoded + /// return value. + #[ink(constructor)] + pub fn try_revert_new(init_value: bool) -> Result { + let value = if init_value { + Ok(Ok(AccountId::from([0u8; 32]))) + } else { + Err(ink::LangError::CouldNotReadInput) + }; + + ::ink::env::return_value::< + ink::ConstructorResult>, + >(::ink::env::ReturnFlags::new_with_reverted(true), &value) + } + /// Returns the current value of the contract storage. #[ink(message)] pub fn get_value(&self) -> bool { From 713ad1eb827a4b349fab8346c053de261770bd53 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 6 Dec 2022 14:24:15 -0500 Subject: [PATCH 038/206] Remove note about removing `assert` statement We still need this to prevent someone from manually encoding an `Ok` value into the return buffer. --- crates/env/src/engine/on_chain/impls.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index bc136351b5b..c616e464414 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -522,7 +522,6 @@ impl TypedEnvBackend for EnvInstance { let out = ink_primitives::ConstructorResult::::decode( &mut &out_return_value[..], )?; - // TODO: Remove this assert!(out.is_err(), "The callee reverted, but did not encode an error in the output buffer."); Ok(out) } From 64a711c207eed88f2dd3f19a9128f922efc0239f Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 6 Dec 2022 14:46:13 -0500 Subject: [PATCH 039/206] Check return value from fallible constructor tests --- .../call-builder/lib.rs | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 36a6e96f2ff..8aa3381c13f 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -94,7 +94,8 @@ mod call_builder { code_hash: Hash, selector: [u8; 4], init_value: bool, - ) -> Option<::ink::LangError> { + ) -> Option> + { use ink::env::call::build_create; let result = build_create::() @@ -111,16 +112,11 @@ mod call_builder { >>() .params() .try_instantiate_with_result() - .expect("Error from the Contracts pallet."); + .expect("Error from the Contracts pallet.") + .expect("Dispatch should have succeeded."); ::ink::env::debug_println!("Result from `instantiate` {:?}", &result); - match result { - Ok(_) => None, - Err(e @ ink::LangError::CouldNotReadInput) => Some(e), - Err(_) => { - unimplemented!("No other `LangError` variants exist at the moment.") - } - } + Some(result) } } @@ -306,9 +302,8 @@ mod call_builder { Ok(()) } - // TODO: Also add something similar for fallible constructors #[ink_e2e::test(additional_contracts = "../constructors-return-value/Cargo.toml")] - async fn e2e_create_builder_with_revert_constructor( + async fn e2e_create_builder_with_infallible_revert_constructor_encodes_ok( mut client: ink_e2e::Client, ) -> E2EResult<()> { let constructor = call_builder::constructors::new(); @@ -365,7 +360,7 @@ mod call_builder { } #[ink_e2e::test(additional_contracts = "../constructors-return-value/Cargo.toml")] - async fn e2e_create_builder_can_handle_contract_defined_constructor_success( + async fn e2e_create_builder_can_handle_fallible_constructor_success( mut client: ink_e2e::Client, ) -> E2EResult<()> { let constructor = call_builder::constructors::new(); @@ -408,13 +403,16 @@ mod call_builder { ) .expect("Dispatching `call_builder::call_instantiate` failed."); - assert!(call_result.is_none(), "TODO"); + assert!( + call_result.unwrap().is_ok(), + "Call to falliable constructor failed, when it should have succeeded." + ); Ok(()) } #[ink_e2e::test(additional_contracts = "../constructors-return-value/Cargo.toml")] - async fn e2e_create_builder_can_handle_contract_defined_constructor_error( + async fn e2e_create_builder_can_handle_fallible_constructor_error( mut client: ink_e2e::Client, ) -> E2EResult<()> { let constructor = call_builder::constructors::new(); @@ -457,7 +455,10 @@ mod call_builder { ) .expect("Dispatching `call_builder::call_instantiate` failed."); - assert!(call_result.is_none(), "TODO"); + assert!( + call_result.unwrap().is_err(), + "Call to falliable constructor succeeded, when it should have failed." + ); Ok(()) } From c17fc3b46b918b67fba75ac1a18a222b9dc26d0e Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 6 Dec 2022 16:22:47 -0500 Subject: [PATCH 040/206] Update E2E Builder typedef to match changes --- crates/e2e/src/builders.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/e2e/src/builders.rs b/crates/e2e/src/builders.rs index f29af243639..7c2a6b44607 100644 --- a/crates/e2e/src/builders.rs +++ b/crates/e2e/src/builders.rs @@ -39,7 +39,7 @@ pub type CreateBuilderPartial = CreateBuilder< Unset<::Balance>, Set>, Unset, - R, + Set>, >; /// Get the encoded constructor arguments from the partially initialized `CreateBuilder` From 32f4a750c1041a495b18dca985d50843b62474cf Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 6 Dec 2022 16:23:10 -0500 Subject: [PATCH 041/206] Update E2E test for new call syntax --- .../call-builder/lib.rs | 173 ++++++------------ 1 file changed, 52 insertions(+), 121 deletions(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 61358fa81ac..40421a651f3 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -262,7 +262,7 @@ mod call_builder { .expect("Dispatching `call_builder::call_instantiate` failed."); assert!( - matches!(call_result, Some(E2ELangError::CouldNotReadInput)), + matches!(call_result, Some(ink::LangError::CouldNotReadInput)), "Call using invalid selector succeeded, when it should've failed." ); @@ -273,39 +273,26 @@ mod call_builder { async fn e2e_create_builder_with_infallible_revert_constructor_encodes_ok( mut client: ink_e2e::Client, ) -> E2EResult<()> { - let constructor = call_builder::constructors::new(); + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate(&mut ink_e2e::ferdie(), constructor, 0, None) + .instantiate("call_builder", &ink_e2e::ferdie(), constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload( - &mut ink_e2e::ferdie(), - constructors_return_value::CONTRACT_PATH, - None, - ) + .upload("constructors_return_value", &ink_e2e::ferdie(), None) .await .expect("upload `constructors_return_value` failed") .code_hash; let revert_new_selector = [0x90, 0xC9, 0xFE, 0x94]; - let call_result = client - .call( - &mut ink_e2e::ferdie(), - contract_acc_id.clone(), - call_builder::messages::call_instantiate( - ink_e2e::utils::runtime_hash_to_ink_hash::< - ink::env::DefaultEnvironment, - >(&code_hash), - revert_new_selector, - false, - ), - 0, - None, - ) - .await; + let init_value = false; + let call = + build_message::(contract_acc_id).call(|contract| { + contract.call_instantiate(code_hash, revert_new_selector, init_value) + }); + let call_result = client.call(&mut ink_e2e::ferdie(), call, 0, None).await; assert!( call_result.is_err(), @@ -330,45 +317,31 @@ mod call_builder { async fn e2e_create_builder_can_handle_fallible_constructor_success( mut client: ink_e2e::Client, ) -> E2EResult<()> { - let constructor = call_builder::constructors::new(); + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate(&mut ink_e2e::alice(), constructor, 0, None) + .instantiate("call_builder", &ink_e2e::alice(), constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload( - &mut ink_e2e::alice(), - constructors_return_value::CONTRACT_PATH, - None, - ) + .upload("constructors_return_value", &ink_e2e::alice(), None) .await .expect("upload `constructors_return_value` failed") .code_hash; let selector = ink::selector_bytes!("try_new"); let success = true; - let call_result = dbg!( - client - .call( - &mut ink_e2e::alice(), - contract_acc_id.clone(), - call_builder::messages::call_instantiate_with_result( - ink_e2e::utils::runtime_hash_to_ink_hash::< - ink::env::DefaultEnvironment, - >(&code_hash), - selector, - success, - ), - 0, - None, - ) - .await - .expect("Calling `call_builder::call_instantiate` failed") - .value - ) - .expect("Dispatching `call_builder::call_instantiate` failed."); + let call = + build_message::(contract_acc_id).call(|contract| { + contract.call_instantiate_with_result(code_hash, selector, success) + }); + let call_result = client + .call(&mut ink_e2e::alice(), call, 0, None) + .await + .expect("Calling `call_builder::call_instantiate` failed") + .value + .expect("Dispatching `call_builder::call_instantiate` failed."); assert!( call_result.unwrap().is_ok(), @@ -382,45 +355,31 @@ mod call_builder { async fn e2e_create_builder_can_handle_fallible_constructor_error( mut client: ink_e2e::Client, ) -> E2EResult<()> { - let constructor = call_builder::constructors::new(); + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate(&mut ink_e2e::bob(), constructor, 0, None) + .instantiate("call_builder", &ink_e2e::bob(), constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload( - &mut ink_e2e::bob(), - constructors_return_value::CONTRACT_PATH, - None, - ) + .upload("constructors_return_value", &ink_e2e::bob(), None) .await .expect("upload `constructors_return_value` failed") .code_hash; let selector = ink::selector_bytes!("try_new"); let success = false; - let call_result = dbg!( - client - .call( - &mut ink_e2e::bob(), - contract_acc_id.clone(), - call_builder::messages::call_instantiate_with_result( - ink_e2e::utils::runtime_hash_to_ink_hash::< - ink::env::DefaultEnvironment, - >(&code_hash), - selector, - success, - ), - 0, - None, - ) - .await - .expect("Calling `call_builder::call_instantiate` failed") - .value - ) - .expect("Dispatching `call_builder::call_instantiate` failed."); + let call = + build_message::(contract_acc_id).call(|contract| { + contract.call_instantiate_with_result(code_hash, selector, success) + }); + let call_result = client + .call(&mut ink_e2e::alice(), call, 0, None) + .await + .expect("Calling `call_builder::call_instantiate` failed") + .value + .expect("Dispatching `call_builder::call_instantiate` failed."); assert!( call_result.unwrap().is_err(), @@ -434,40 +393,26 @@ mod call_builder { async fn e2e_create_builder_with_fallible_revert_constructor_encodes_ok( mut client: ink_e2e::Client, ) -> E2EResult<()> { - let constructor = call_builder::constructors::new(); + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate(&mut ink_e2e::charlie(), constructor, 0, None) + .instantiate("call_builder", &ink_e2e::charlie(), constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload( - &mut ink_e2e::charlie(), - constructors_return_value::CONTRACT_PATH, - None, - ) + .upload("constructors_return_value", &ink_e2e::charlie(), None) .await .expect("upload `constructors_return_value` failed") .code_hash; let selector = ink::selector_bytes!("try_revert_new"); let init_value = true; - let call_result = client - .call( - &mut ink_e2e::charlie(), - contract_acc_id.clone(), - call_builder::messages::call_instantiate_with_result( - ink_e2e::utils::runtime_hash_to_ink_hash::< - ink::env::DefaultEnvironment, - >(&code_hash), - selector, - init_value, - ), - 0, - None, - ) - .await; + let call = + build_message::(contract_acc_id).call(|contract| { + contract.call_instantiate_with_result(code_hash, selector, init_value) + }); + let call_result = client.call(&mut ink_e2e::charlie(), call, 0, None).await; assert!( call_result.is_err(), @@ -496,40 +441,26 @@ mod call_builder { async fn e2e_create_builder_with_fallible_revert_constructor_encodes_err( mut client: ink_e2e::Client, ) -> E2EResult<()> { - let constructor = call_builder::constructors::new(); + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate(&mut ink_e2e::dave(), constructor, 0, None) + .instantiate("call_builder", &ink_e2e::dave(), constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload( - &mut ink_e2e::dave(), - constructors_return_value::CONTRACT_PATH, - None, - ) + .upload("constructors_return_value", &ink_e2e::dave(), None) .await .expect("upload `constructors_return_value` failed") .code_hash; let selector = ink::selector_bytes!("try_revert_new"); let init_value = false; - let call_result = client - .call( - &mut ink_e2e::dave(), - contract_acc_id.clone(), - call_builder::messages::call_instantiate_with_result( - ink_e2e::utils::runtime_hash_to_ink_hash::< - ink::env::DefaultEnvironment, - >(&code_hash), - selector, - init_value, - ), - 0, - None, - ) - .await; + let call = + build_message::(contract_acc_id).call(|contract| { + contract.call_instantiate_with_result(code_hash, selector, init_value) + }); + let call_result = client.call(&mut ink_e2e::dave(), call, 0, None).await; assert!( call_result.is_err(), From a3cfbb8a26a0c19ad21c854069b501e8249af3bd Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 6 Dec 2022 16:30:02 -0500 Subject: [PATCH 042/206] Use `selector_bytes!` macro in more places --- .../call-builder/lib.rs | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 40421a651f3..0c99a60ac9e 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -164,9 +164,9 @@ mod call_builder { .value .expect("Input is valid, call must not fail."); - let invalid_selector = [0x00, 0x00, 0x00, 0x00]; + let selector = ink::selector_bytes!("invalid_selector"); let call = build_message::(contract_acc_id) - .call(|contract| contract.call(flipper_acc_id, invalid_selector)); + .call(|contract| contract.call(flipper_acc_id, selector)); let call_result = client .call(&ink_e2e::charlie(), call, 0, None) .await @@ -212,10 +212,11 @@ mod call_builder { .expect("upload `constructors_return_value` failed") .code_hash; - let new_selector = [0x9B, 0xAE, 0x9D, 0x5E]; + let selector = ink::selector_bytes!("new"); + let init_value = true; let call = build_message::(contract_acc_id).call(|contract| { - contract.call_instantiate(code_hash, new_selector, true) + contract.call_instantiate(code_hash, selector, init_value) }); let call_result = client .call(&ink_e2e::dave(), call, 0, None) @@ -249,10 +250,11 @@ mod call_builder { .expect("upload `constructors_return_value` failed") .code_hash; - let invalid_selector = [0x00, 0x00, 0x00, 0x00]; + let selector = ink::selector_bytes!("invalid_selector"); + let init_value = true; let call = build_message::(contract_acc_id).call(|contract| { - contract.call_instantiate(code_hash, invalid_selector, true) + contract.call_instantiate(code_hash, selector, init_value) }); let call_result = client .call(&ink_e2e::eve(), call, 0, None) @@ -286,11 +288,11 @@ mod call_builder { .expect("upload `constructors_return_value` failed") .code_hash; - let revert_new_selector = [0x90, 0xC9, 0xFE, 0x94]; + let selector = ink::selector_bytes!("revert_new"); let init_value = false; let call = build_message::(contract_acc_id).call(|contract| { - contract.call_instantiate(code_hash, revert_new_selector, init_value) + contract.call_instantiate(code_hash, selector, init_value) }); let call_result = client.call(&mut ink_e2e::ferdie(), call, 0, None).await; @@ -331,10 +333,10 @@ mod call_builder { .code_hash; let selector = ink::selector_bytes!("try_new"); - let success = true; + let init_value = true; let call = build_message::(contract_acc_id).call(|contract| { - contract.call_instantiate_with_result(code_hash, selector, success) + contract.call_instantiate_with_result(code_hash, selector, init_value) }); let call_result = client .call(&mut ink_e2e::alice(), call, 0, None) @@ -369,10 +371,10 @@ mod call_builder { .code_hash; let selector = ink::selector_bytes!("try_new"); - let success = false; + let init_value = false; let call = build_message::(contract_acc_id).call(|contract| { - contract.call_instantiate_with_result(code_hash, selector, success) + contract.call_instantiate_with_result(code_hash, selector, init_value) }); let call_result = client .call(&mut ink_e2e::alice(), call, 0, None) From 283e182f6803adfc66ffbc792ea3c577fe203e72 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 6 Dec 2022 16:33:15 -0500 Subject: [PATCH 043/206] Change order to accounts used in tests The tests started failing due to nonce issues, re-ordering the accounts seems to help with that. --- .../call-builder/lib.rs | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 0c99a60ac9e..ae3e9010453 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -136,7 +136,7 @@ mod call_builder { ) -> E2EResult<()> { let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::charlie(), constructor, 0, None) + .instantiate("call_builder", &ink_e2e::alice(), constructor, 0, None) .await .expect("instantiate failed") .account_id; @@ -145,7 +145,7 @@ mod call_builder { let flipper_acc_id = client .instantiate( "integration_flipper", - &ink_e2e::charlie(), + &ink_e2e::alice(), flipper_constructor, 0, None, @@ -157,7 +157,7 @@ mod call_builder { let flipper_get = build_message::(flipper_acc_id) .call(|contract| contract.get()); let get_call_result = client - .call(&ink_e2e::charlie(), flipper_get, 0, None) + .call(&ink_e2e::alice(), flipper_get, 0, None) .await .expect("Calling `flipper::get` failed"); let initial_value = get_call_result @@ -168,7 +168,7 @@ mod call_builder { let call = build_message::(contract_acc_id) .call(|contract| contract.call(flipper_acc_id, selector)); let call_result = client - .call(&ink_e2e::charlie(), call, 0, None) + .call(&ink_e2e::alice(), call, 0, None) .await .expect("Calling `call_builder::call` failed"); @@ -184,7 +184,7 @@ mod call_builder { let flipper_get = build_message::(flipper_acc_id) .call(|contract| contract.get()); let get_call_result = client - .call(&ink_e2e::charlie(), flipper_get, 0, None) + .call(&ink_e2e::alice(), flipper_get, 0, None) .await .expect("Calling `flipper::get` failed"); let flipped_value = get_call_result @@ -201,13 +201,13 @@ mod call_builder { ) -> E2EResult<()> { let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::dave(), constructor, 0, None) + .instantiate("call_builder", &ink_e2e::bob(), constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::dave(), None) + .upload("constructors_return_value", &ink_e2e::bob(), None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -219,7 +219,7 @@ mod call_builder { contract.call_instantiate(code_hash, selector, init_value) }); let call_result = client - .call(&ink_e2e::dave(), call, 0, None) + .call(&ink_e2e::bob(), call, 0, None) .await .expect("Calling `call_builder::call_instantiate` failed") .value @@ -239,13 +239,13 @@ mod call_builder { ) -> E2EResult<()> { let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::eve(), constructor, 0, None) + .instantiate("call_builder", &ink_e2e::charlie(), constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::eve(), None) + .upload("constructors_return_value", &ink_e2e::charlie(), None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -257,7 +257,7 @@ mod call_builder { contract.call_instantiate(code_hash, selector, init_value) }); let call_result = client - .call(&ink_e2e::eve(), call, 0, None) + .call(&ink_e2e::charlie(), call, 0, None) .await .expect("Client failed to call `call_builder::call_instantiate`.") .value @@ -277,13 +277,13 @@ mod call_builder { ) -> E2EResult<()> { let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::ferdie(), constructor, 0, None) + .instantiate("call_builder", &ink_e2e::dave(), constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::ferdie(), None) + .upload("constructors_return_value", &ink_e2e::dave(), None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -294,7 +294,7 @@ mod call_builder { build_message::(contract_acc_id).call(|contract| { contract.call_instantiate(code_hash, selector, init_value) }); - let call_result = client.call(&mut ink_e2e::ferdie(), call, 0, None).await; + let call_result = client.call(&mut ink_e2e::dave(), call, 0, None).await; assert!( call_result.is_err(), @@ -321,13 +321,13 @@ mod call_builder { ) -> E2EResult<()> { let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::alice(), constructor, 0, None) + .instantiate("call_builder", &ink_e2e::eve(), constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::alice(), None) + .upload("constructors_return_value", &ink_e2e::eve(), None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -339,7 +339,7 @@ mod call_builder { contract.call_instantiate_with_result(code_hash, selector, init_value) }); let call_result = client - .call(&mut ink_e2e::alice(), call, 0, None) + .call(&mut ink_e2e::eve(), call, 0, None) .await .expect("Calling `call_builder::call_instantiate` failed") .value @@ -359,13 +359,13 @@ mod call_builder { ) -> E2EResult<()> { let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::bob(), constructor, 0, None) + .instantiate("call_builder", &ink_e2e::ferdie(), constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::bob(), None) + .upload("constructors_return_value", &ink_e2e::ferdie(), None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -377,7 +377,7 @@ mod call_builder { contract.call_instantiate_with_result(code_hash, selector, init_value) }); let call_result = client - .call(&mut ink_e2e::alice(), call, 0, None) + .call(&mut ink_e2e::ferdie(), call, 0, None) .await .expect("Calling `call_builder::call_instantiate` failed") .value @@ -397,13 +397,13 @@ mod call_builder { ) -> E2EResult<()> { let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::charlie(), constructor, 0, None) + .instantiate("call_builder", &ink_e2e::alice(), constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::charlie(), None) + .upload("constructors_return_value", &ink_e2e::alice(), None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -414,7 +414,7 @@ mod call_builder { build_message::(contract_acc_id).call(|contract| { contract.call_instantiate_with_result(code_hash, selector, init_value) }); - let call_result = client.call(&mut ink_e2e::charlie(), call, 0, None).await; + let call_result = client.call(&mut ink_e2e::alice(), call, 0, None).await; assert!( call_result.is_err(), @@ -445,13 +445,13 @@ mod call_builder { ) -> E2EResult<()> { let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::dave(), constructor, 0, None) + .instantiate("call_builder", &ink_e2e::bob(), constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::dave(), None) + .upload("constructors_return_value", &ink_e2e::bob(), None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -462,7 +462,7 @@ mod call_builder { build_message::(contract_acc_id).call(|contract| { contract.call_instantiate_with_result(code_hash, selector, init_value) }); - let call_result = client.call(&mut ink_e2e::dave(), call, 0, None).await; + let call_result = client.call(&mut ink_e2e::bob(), call, 0, None).await; assert!( call_result.is_err(), From cc98baf8cb61ae2b4580d72e0cefa4505592c458 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 6 Dec 2022 16:57:08 -0500 Subject: [PATCH 044/206] Update function names to use `fallible` --- crates/env/src/api.rs | 4 ++-- crates/env/src/backend.rs | 2 +- crates/env/src/call/create_builder.rs | 8 ++++---- crates/env/src/engine/off_chain/impls.rs | 2 +- crates/env/src/engine/on_chain/impls.rs | 2 +- crates/ink/src/env_access.rs | 6 ++---- .../lang-err-integration-tests/call-builder/lib.rs | 12 ++++++------ 7 files changed, 17 insertions(+), 19 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index cad6e207622..cb2cbf9c314 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -333,7 +333,7 @@ where } /// TODO -pub fn instantiate_contract_with_result( +pub fn instantiate_fallible_contract( params: &CreateParams, ) -> Result< ::ink_primitives::ConstructorResult< @@ -347,7 +347,7 @@ where ContractError: scale::Decode, { ::on_instance(|instance| { - TypedEnvBackend::instantiate_contract_with_result::( + TypedEnvBackend::instantiate_fallible_contract::( instance, params, ) }) diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index f107f3c0bb6..642a4881460 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -449,7 +449,7 @@ pub trait TypedEnvBackend: EnvBackend { Salt: AsRef<[u8]>; /// TODO - fn instantiate_contract_with_result( + fn instantiate_fallible_contract( &mut self, params: &CreateParams, ) -> Result< diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 69da25874d3..b75e6868c86 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -164,13 +164,13 @@ where /// /// On failure this returns an [`ink_primitives::LangError`] which can be handled by the caller. #[inline] - pub fn try_instantiate_with_result( + pub fn try_instantiate_fallible( &self, ) -> Result< ::ink_primitives::ConstructorResult>, crate::Error, > { - crate::instantiate_contract_with_result(self) + crate::instantiate_fallible_contract(self) } } @@ -521,7 +521,7 @@ where /// /// On failure this returns an [`ink_primitives::LangError`] which can be handled by the caller. #[inline] - pub fn try_instantiate_with_result( + pub fn try_instantiate_fallible( self, ) -> Result< ::ink_primitives::ConstructorResult< @@ -529,6 +529,6 @@ where >, Error, > { - self.params().try_instantiate_with_result() + self.params().try_instantiate_fallible() } } diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 6c74e428524..a1159e8f506 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -486,7 +486,7 @@ impl TypedEnvBackend for EnvInstance { unimplemented!("off-chain environment does not support contract instantiation") } - fn instantiate_contract_with_result( + fn instantiate_fallible_contract( &mut self, params: &CreateParams, ) -> Result< diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index c616e464414..a2d38d2efd0 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -529,7 +529,7 @@ impl TypedEnvBackend for EnvInstance { } } - fn instantiate_contract_with_result( + fn instantiate_fallible_contract( &mut self, params: &CreateParams, ) -> Result< diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 56b0cd80b1c..0fcc5c9a145 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -490,7 +490,7 @@ where } /// TODO - pub fn instantiate_contract_with_result( + pub fn instantiate_fallible_contract( self, params: &CreateParams, ) -> Result< @@ -504,9 +504,7 @@ where Salt: AsRef<[u8]>, ContractError: scale::Decode, { - ink_env::instantiate_contract_with_result::( - params, - ) + ink_env::instantiate_fallible_contract::(params) } /// Invokes a contract message and returns its result. diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index ae3e9010453..24946258d5d 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -89,7 +89,7 @@ mod call_builder { } #[ink(message)] - pub fn call_instantiate_with_result( + pub fn call_instantiate_fallible( &mut self, code_hash: Hash, selector: [u8; 4], @@ -111,7 +111,7 @@ mod call_builder { constructors_return_value::ConstructorError, >>() .params() - .try_instantiate_with_result() + .try_instantiate_fallible() .expect("Error from the Contracts pallet.") .expect("Dispatch should have succeeded."); ::ink::env::debug_println!("Result from `instantiate` {:?}", &result); @@ -336,7 +336,7 @@ mod call_builder { let init_value = true; let call = build_message::(contract_acc_id).call(|contract| { - contract.call_instantiate_with_result(code_hash, selector, init_value) + contract.call_instantiate_fallible(code_hash, selector, init_value) }); let call_result = client .call(&mut ink_e2e::eve(), call, 0, None) @@ -374,7 +374,7 @@ mod call_builder { let init_value = false; let call = build_message::(contract_acc_id).call(|contract| { - contract.call_instantiate_with_result(code_hash, selector, init_value) + contract.call_instantiate_fallible(code_hash, selector, init_value) }); let call_result = client .call(&mut ink_e2e::ferdie(), call, 0, None) @@ -412,7 +412,7 @@ mod call_builder { let init_value = true; let call = build_message::(contract_acc_id).call(|contract| { - contract.call_instantiate_with_result(code_hash, selector, init_value) + contract.call_instantiate_fallible(code_hash, selector, init_value) }); let call_result = client.call(&mut ink_e2e::alice(), call, 0, None).await; @@ -460,7 +460,7 @@ mod call_builder { let init_value = false; let call = build_message::(contract_acc_id).call(|contract| { - contract.call_instantiate_with_result(code_hash, selector, init_value) + contract.call_instantiate_fallible(code_hash, selector, init_value) }); let call_result = client.call(&mut ink_e2e::bob(), call, 0, None).await; From f01b5caaca8647fc2685452da1dee8a4fbc0edcc Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 6 Dec 2022 16:59:24 -0500 Subject: [PATCH 045/206] Add note about docs --- crates/env/src/api.rs | 2 +- crates/env/src/backend.rs | 2 +- crates/ink/src/env_access.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index cb2cbf9c314..0a0415e5e47 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -332,7 +332,7 @@ where }) } -/// TODO +/// TODO: Docs pub fn instantiate_fallible_contract( params: &CreateParams, ) -> Result< diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 642a4881460..c5c151e1d92 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -448,7 +448,7 @@ pub trait TypedEnvBackend: EnvBackend { Args: scale::Encode, Salt: AsRef<[u8]>; - /// TODO + /// TODO: Docs fn instantiate_fallible_contract( &mut self, params: &CreateParams, diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 0fcc5c9a145..1c18ff9b2d4 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -489,7 +489,7 @@ where ink_env::instantiate_contract::(params) } - /// TODO + /// TODO: Docs pub fn instantiate_fallible_contract( self, params: &CreateParams, From b4290cb6191d5bb79c40e0db357e09a6154abcbf Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 7 Dec 2022 12:26:13 -0500 Subject: [PATCH 046/206] Update `ContractRef` codegen to use fallible constructor return types --- .../codegen/src/generator/as_dependency/contract_ref.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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 adc4acfb04d..756dae0ed71 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -403,6 +403,10 @@ impl ContractRef<'_> { let input_bindings = generator::input_bindings(constructor.inputs()); let input_types = generator::input_types(constructor.inputs()); let arg_list = generator::generate_argument_list(input_types.iter().cloned()); + let ret_type = constructor + .output() + .map(quote::ToTokens::to_token_stream) + .unwrap_or_else(|| quote::quote! { Self }); quote_spanned!(span => #( #attrs )* #[inline] @@ -416,7 +420,7 @@ impl ContractRef<'_> { ::ink::env::call::utils::Unset, ::ink::env::call::utils::Set<::ink::env::call::ExecutionInput<#arg_list>>, ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, - ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType>, + ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, > { ::ink::env::call::build_create::() .exec_input( @@ -427,7 +431,7 @@ impl ContractRef<'_> { .push_arg(#input_bindings) )* ) - .returns::() + .returns::<#ret_type>() } ) } From d47bf8f4f0b70fd4e0b0af145364221515e0dbe4 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 7 Dec 2022 12:44:22 -0500 Subject: [PATCH 047/206] Stop returning an `AccountId` directly from `CreateBuilder::try_instantiate_fallible` This matches the behaviour of the other intantiate methods --- crates/env/src/call/create_builder.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index b75e6868c86..15a5aa80da1 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -525,10 +525,16 @@ where self, ) -> Result< ::ink_primitives::ConstructorResult< - ::core::result::Result, + ::core::result::Result, >, Error, > { - self.params().try_instantiate_fallible() + self.params() + .try_instantiate_fallible() + .map(|constructor_result| { + constructor_result.map(|contract_result| { + contract_result.map(FromAccountId::from_account_id) + }) + }) } } From b720ede4c58cbff54af9c7908d4d3900f3c24036 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 7 Dec 2022 12:45:06 -0500 Subject: [PATCH 048/206] Add panicking version of `try_instantiate_fallible` --- crates/env/src/call/create_builder.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 15a5aa80da1..b6c847534ed 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -515,7 +515,28 @@ where RetType: FromAccountId, ContractError: scale::Decode, { - /// Instantiates the contract using the given instantiation parameters. + /// Attempts to instantiate the contract, returning the execution result back to the caller. + /// + /// # Panics + /// + /// This method panics if it encounters an [`ink_primitives::LangError`]. If you want to handle + /// those use the [`try_instantiate_fallible`][`CreateParams::try_instantiate_fallible`] method instead. + #[inline] + pub fn instantiate_fallible( + self, + ) -> Result<::core::result::Result, Error> { + self.params() + .try_instantiate_fallible() + .map(|constructor_result| { + constructor_result + .unwrap_or_else(|error| { + panic!("Received a `LangError` while instantiating: {:?}", error) + }) + .map(FromAccountId::from_account_id) + }) + } + + /// Attempts to instantiate the contract, returning the execution result back to the caller. /// /// # Note /// From 75cad9efb5083710ce9e616cdcc72e19a77fd2e8 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 7 Dec 2022 12:58:14 -0500 Subject: [PATCH 049/206] Add test for using fallible constructors through ContractRefs --- .../contract-ref/lib.rs | 49 +++++++++++++++++++ .../integration-flipper/lib.rs | 15 ++++++ 2 files changed, 64 insertions(+) diff --git a/examples/lang-err-integration-tests/contract-ref/lib.rs b/examples/lang-err-integration-tests/contract-ref/lib.rs index 319fd797c42..b7f88263820 100755 --- a/examples/lang-err-integration-tests/contract-ref/lib.rs +++ b/examples/lang-err-integration-tests/contract-ref/lib.rs @@ -25,6 +25,24 @@ mod contract_ref { Self { flipper } } + #[ink(constructor)] + pub fn try_new(version: u32, flipper_code_hash: Hash) -> Self { + let salt = version.to_le_bytes(); + let flipper = FlipperRef::try_new(true) + .endowment(0) + .code_hash(flipper_code_hash) + .salt_bytes(salt) + .instantiate_fallible() + .unwrap_or_else(|error| { + panic!("Received an error from the Contracts pallet while instantiating Flipper {:?}", error) + }) + .unwrap_or_else(|error| { + panic!("Received an error from the Flipper constructor while instantiating Flipper {:?}", error) + }); + + Self { flipper } + } + #[ink(message)] pub fn flip(&mut self) { self.flipper.flip(); @@ -108,5 +126,36 @@ mod contract_ref { Ok(()) } + + #[ink_e2e::test(additional_contracts = "../integration-flipper/Cargo.toml")] + async fn e2e_fallible_ref_can_be_instantiated( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let flipper_hash = client + .upload("integration_flipper", &ink_e2e::bob(), None) + .await + .expect("uploading `flipper` failed") + .code_hash; + + let constructor = ContractRefRef::try_new(0, flipper_hash); + let contract_acc_id = client + .instantiate("contract_ref", &ink_e2e::bob(), constructor, 0, None) + .await + .expect("instantiate failed") + .account_id; + + let get_check = build_message::(contract_acc_id.clone()) + .call(|contract| contract.get_check()); + let get_call_result = client + .call(&ink_e2e::bob(), get_check, 0, None) + .await + .expect("Calling `get_check` failed"); + let initial_value = get_call_result + .value + .expect("Input is valid, call must not fail."); + assert!(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 a9858ba9c3e..521fedffe87 100644 --- a/examples/lang-err-integration-tests/integration-flipper/lib.rs +++ b/examples/lang-err-integration-tests/integration-flipper/lib.rs @@ -12,6 +12,10 @@ pub mod integration_flipper { value: bool, } + #[derive(scale::Encode, scale::Decode, Debug)] + #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] + pub struct FlipperError; + impl Flipper { /// Creates a new integration_flipper smart contract initialized with the given value. #[ink(constructor)] @@ -25,6 +29,17 @@ pub mod integration_flipper { Self::new(Default::default()) } + /// Attemps to create a new integration_flipper smart contract initialized with the given + /// value. + #[ink(constructor)] + pub fn try_new(succeed: bool) -> Result { + if succeed { + Ok(Self::new(true)) + } else { + Err(FlipperError) + } + } + /// Flips the current value of the Flipper's boolean. #[ink(message)] pub fn flip(&mut self) { From cf2516fc161258d110f5e01d68f92f013323ca72 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 7 Dec 2022 13:03:57 -0500 Subject: [PATCH 050/206] Add test for instantiation failure too --- .../contract-ref/lib.rs | 46 +++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/examples/lang-err-integration-tests/contract-ref/lib.rs b/examples/lang-err-integration-tests/contract-ref/lib.rs index b7f88263820..4cbc035f1ba 100755 --- a/examples/lang-err-integration-tests/contract-ref/lib.rs +++ b/examples/lang-err-integration-tests/contract-ref/lib.rs @@ -26,9 +26,9 @@ mod contract_ref { } #[ink(constructor)] - pub fn try_new(version: u32, flipper_code_hash: Hash) -> Self { + pub fn try_new(version: u32, flipper_code_hash: Hash, succeed: bool) -> Self { let salt = version.to_le_bytes(); - let flipper = FlipperRef::try_new(true) + let flipper = FlipperRef::try_new(succeed) .endowment(0) .code_hash(flipper_code_hash) .salt_bytes(salt) @@ -137,7 +137,8 @@ mod contract_ref { .expect("uploading `flipper` failed") .code_hash; - let constructor = ContractRefRef::try_new(0, flipper_hash); + let succeed = true; + let constructor = ContractRefRef::try_new(0, flipper_hash, succeed); let contract_acc_id = client .instantiate("contract_ref", &ink_e2e::bob(), constructor, 0, None) .await @@ -157,5 +158,44 @@ mod contract_ref { Ok(()) } + + #[ink_e2e::test(additional_contracts = "../integration-flipper/Cargo.toml")] + async fn e2e_fallible_ref_fails_to_be_instantiated( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let flipper_hash = client + .upload("integration_flipper", &ink_e2e::charlie(), None) + .await + .expect("uploading `flipper` failed") + .code_hash; + + let succeed = false; + let constructor = ContractRefRef::try_new(0, flipper_hash, succeed); + let instantiate_result = client + .instantiate("contract_ref", &ink_e2e::charlie(), constructor, 0, None) + .await; + // .expect("instantiate failed") + // .account_id; + + assert!( + instantiate_result.is_err(), + "Call execution should've failed, but didn't." + ); + + let contains_err_msg = match instantiate_result.unwrap_err() { + ink_e2e::Error::InstantiateDryRun(dry_run) => { + String::from_utf8_lossy(&dry_run.debug_message).contains( + "Received an error from the Flipper constructor while instantiating Flipper FlipperError" + ) + } + _ => false, + }; + assert!( + contains_err_msg, + "Call execution failed for an unexpected reason." + ); + + Ok(()) + } } } From f9b300444a814d05e6fc55d80ded0f71c7c2ecee Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 7 Dec 2022 13:14:23 -0500 Subject: [PATCH 051/206] Add `instantiate_fallible` to `CreateParams` --- crates/env/src/call/create_builder.rs | 49 +++++++++++++++------------ 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index b6c847534ed..ba022bb780a 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -158,7 +158,24 @@ where R: FromAccountId, ContractError: scale::Decode, { - /// Instantiates the contract and returns its account ID back to the caller. + /// Attempts to instantiate the contract, returning the execution result back to the caller. + /// + /// # Panics + /// + /// This method panics if it encounters an [`ink_primitives::LangError`]. If you want to handle + /// those use the [`try_instantiate_fallible`][`CreateParams::try_instantiate_fallible`] method instead. + #[inline] + pub fn instantiate_fallible(&self) -> Result, crate::Error> { + crate::instantiate_fallible_contract(self).map(|constructor_result| { + constructor_result + .unwrap_or_else(|error| { + panic!("Received a `LangError` while instantiating: {:?}", error) + }) + .map(FromAccountId::from_account_id) + }) + } + + /// Attempts to instantiate the contract, returning the execution result back to the caller. /// /// # Note /// @@ -166,11 +183,13 @@ where #[inline] pub fn try_instantiate_fallible( &self, - ) -> Result< - ::ink_primitives::ConstructorResult>, - crate::Error, - > { - crate::instantiate_fallible_contract(self) + ) -> Result<::ink_primitives::ConstructorResult>, crate::Error> + { + crate::instantiate_fallible_contract(self).map(|constructor_result| { + constructor_result.map(|contract_result| { + contract_result.map(FromAccountId::from_account_id) + }) + }) } } @@ -525,15 +544,7 @@ where pub fn instantiate_fallible( self, ) -> Result<::core::result::Result, Error> { - self.params() - .try_instantiate_fallible() - .map(|constructor_result| { - constructor_result - .unwrap_or_else(|error| { - panic!("Received a `LangError` while instantiating: {:?}", error) - }) - .map(FromAccountId::from_account_id) - }) + self.params().instantiate_fallible() } /// Attempts to instantiate the contract, returning the execution result back to the caller. @@ -550,12 +561,6 @@ where >, Error, > { - self.params() - .try_instantiate_fallible() - .map(|constructor_result| { - constructor_result.map(|contract_result| { - contract_result.map(FromAccountId::from_account_id) - }) - }) + self.params().try_instantiate_fallible() } } From d511b3feeaf3b9a71371b7bb4c1ab364edd84c13 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 7 Dec 2022 13:17:56 -0500 Subject: [PATCH 052/206] Add a couple of missing docs --- crates/env/src/api.rs | 17 ++++++++++++++++- crates/env/src/backend.rs | 7 ++++++- .../contract-ref/lib.rs | 2 -- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 0a0415e5e47..dc28bcab1a3 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -332,7 +332,22 @@ where }) } -/// TODO: Docs +/// Attempts to instantiate another contract, returning the instantiation result back to the +/// caller. +/// +/// # Note +/// +/// This is a low level way to instantiate another smart contract. +/// Prefer to use the ink! guided and type safe approach to using this. +/// +/// # Errors +/// +/// - If the code hash is invalid. +/// - If the arguments passed to the instantiation process are invalid. +/// - If the instantiation process traps. +/// - If the instantiation process runs out of gas. +/// - If given insufficient endowment. +/// - If the returned account ID failed to decode properly. pub fn instantiate_fallible_contract( params: &CreateParams, ) -> Result< diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index c5c151e1d92..bfa7fd09438 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -448,7 +448,12 @@ pub trait TypedEnvBackend: EnvBackend { Args: scale::Encode, Salt: AsRef<[u8]>; - /// TODO: Docs + /// Attempts to instantiate another contract, returning the instantiation result back to the + /// caller. + /// + /// # Note + /// + /// For more details visit: [`instantiate_fallible_contract`][`crate::instantiate_fallible_contract`] fn instantiate_fallible_contract( &mut self, params: &CreateParams, diff --git a/examples/lang-err-integration-tests/contract-ref/lib.rs b/examples/lang-err-integration-tests/contract-ref/lib.rs index 4cbc035f1ba..e7c08d2363d 100755 --- a/examples/lang-err-integration-tests/contract-ref/lib.rs +++ b/examples/lang-err-integration-tests/contract-ref/lib.rs @@ -174,8 +174,6 @@ mod contract_ref { let instantiate_result = client .instantiate("contract_ref", &ink_e2e::charlie(), constructor, 0, None) .await; - // .expect("instantiate failed") - // .account_id; assert!( instantiate_result.is_err(), From 550b728e7a44127c4af78cf44093ef631a85a048 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 7 Dec 2022 13:25:42 -0500 Subject: [PATCH 053/206] Convert `call-builder` test return type to `AccountId` --- examples/lang-err-integration-tests/call-builder/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 24946258d5d..4dee6b06326 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -116,7 +116,7 @@ mod call_builder { .expect("Dispatch should have succeeded."); ::ink::env::debug_println!("Result from `instantiate` {:?}", &result); - Some(result) + Some(result.map(|inner| ink::ToAccountId::to_account_id(&inner))) } } From 1668ae01f09d8f180ac5512d279475fb95ec44a6 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 8 Dec 2022 17:56:51 +0000 Subject: [PATCH 054/206] Extract reverted fallible constructor fn for testing --- crates/env/src/engine/mod.rs | 68 +++++++++++++++++++++++++ crates/env/src/engine/on_chain/impls.rs | 40 ++------------- 2 files changed, 72 insertions(+), 36 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 2e74d582e12..7710e4a1ade 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -37,3 +37,71 @@ cfg_if! { } } } + +use ink_primitives::ConstructorResult; +use crate::{ + Environment, + Result as EnvResult, +}; + +pub(crate) fn decode_fallible_constructor_reverted_return_value( + out_return_value: &mut I, +) -> EnvResult< + ConstructorResult< + Result, + >, +> + where + I: scale::Input, + E: Environment, + ContractError: scale::Decode, +{ + let decoding_result = , + > as scale::Decode>::decode(out_return_value); + + match decoding_result { + Ok(constructor_result) => { + let contract_result = constructor_result.expect( + "If dispatch had failed, we shouldn't have been able to decode \ + the nested `Result`.", + ); + + let contract_error = contract_result.expect_err( + "Since the contract reverted, we only expect an `Error` from the constructor. \ + Otherwise we would be in the `AccountId` branch."); + + Ok(Ok(Err(contract_error))) + } + Err(_) => { + // If we hit this branch it likely means dispatch failed, but we need to + // check the buffer again to confirm. + let out = as scale::Decode>::decode( + out_return_value, + )?; + + let lang_error = out.expect_err( + "If dispatch had succeeded, we would either be in the `AccountId` branch \ + or we would've been able to decode into a nested `Result` earlier." + ); + + Ok(Err(lang_error)) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use scale::Encode; + + #[derive(scale::Encode, scale::Decode)] + struct ContractError(String); + + #[test] + fn fallible_constructor_reverted_contract_error() { + let encoded_return_value = ConstructorResult::Ok(Result::::Err(ContractError("Constructor error".to_owned()))).encode(); + let decoded_result = decode_fallible_constructor_reverted_return_value::<_, crate::DefaultEnvironment, ContractError>(&mut &encoded_return_value[..]); + assert!(matches!(decoded_result, Ok(Ok(Result::::Err(ContractError(_)))))) + } +} diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index a2d38d2efd0..99607d2fcc2 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -572,41 +572,9 @@ impl TypedEnvBackend for EnvInstance { Ok(ink_primitives::ConstructorResult::Ok(Ok(account_id))) } Err(ext::Error::CalleeReverted) => { - let decoding_result = , - > as scale::Decode>::decode( - &mut &out_return_value[..] - ); - - match decoding_result { - Ok(constructor_result) => { - let contract_result = constructor_result.expect( - "If dispatch had failed, we shouldn't have been able to decode \ - the nested `Result`." - ); - - let contract_error = contract_result.expect_err( - "Since the contract reverted, we only expect an `Error` from the constructor. \ - Otherwise we would be in the `AccountId` branch."); - - Ok(ink_primitives::ConstructorResult::Ok(Err(contract_error))) - } - Err(_) => { - // If we hit this branch it likely means dispatch failed, but we need to - // check the buffer again to confirm. - let out = - as scale::Decode>::decode( - &mut &out_return_value[..], - )?; - - let lang_error = out.expect_err( - "If dispatch had succeeded, we would either be in the `AccountId` branch \ - or we would've been able to decode into a nested `Result` earlier." - ); - - Ok(ink_primitives::ConstructorResult::Err(lang_error)) - } - } + decode_fallible_constructor_reverted_return_value::<_, E, ContractError>( + &mut &out_return_value[..], + ) } Err(actual_error) => Err(actual_error.into()), } @@ -675,4 +643,4 @@ impl TypedEnvBackend for EnvInstance { let hash = scale::Decode::decode(&mut &output[..])?; Ok(hash) } -} +} \ No newline at end of file From acf23b913fbe22914fe60d6fba7db63738eaecac Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 8 Dec 2022 17:58:14 +0000 Subject: [PATCH 055/206] Fmt --- crates/env/src/engine/mod.rs | 46 ++++++++++++++++--------- crates/env/src/engine/on_chain/impls.rs | 2 +- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 7710e4a1ade..c01d7f6c21c 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -38,27 +38,24 @@ cfg_if! { } } -use ink_primitives::ConstructorResult; use crate::{ Environment, Result as EnvResult, }; +use ink_primitives::ConstructorResult; pub(crate) fn decode_fallible_constructor_reverted_return_value( out_return_value: &mut I, -) -> EnvResult< - ConstructorResult< - Result, - >, -> - where - I: scale::Input, - E: Environment, - ContractError: scale::Decode, +) -> EnvResult>> +where + I: scale::Input, + E: Environment, + ContractError: scale::Decode, { - let decoding_result = , - > as scale::Decode>::decode(out_return_value); + let decoding_result = + > as scale::Decode>::decode( + out_return_value, + ); match decoding_result { Ok(constructor_result) => { @@ -100,8 +97,25 @@ mod tests { #[test] fn fallible_constructor_reverted_contract_error() { - let encoded_return_value = ConstructorResult::Ok(Result::::Err(ContractError("Constructor error".to_owned()))).encode(); - let decoded_result = decode_fallible_constructor_reverted_return_value::<_, crate::DefaultEnvironment, ContractError>(&mut &encoded_return_value[..]); - assert!(matches!(decoded_result, Ok(Ok(Result::::Err(ContractError(_)))))) + let encoded_return_value = ConstructorResult::Ok(Result::< + ink_primitives::AccountId, + ContractError, + >::Err(ContractError( + "Constructor error".to_owned(), + ))) + .encode(); + + let decoded_result = decode_fallible_constructor_reverted_return_value::< + _, + crate::DefaultEnvironment, + ContractError, + >(&mut &encoded_return_value[..]); + + assert!(matches!( + decoded_result, + Ok(Ok(Result::::Err( + ContractError(_) + ))) + )) } } diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 99607d2fcc2..9711ee03749 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -643,4 +643,4 @@ impl TypedEnvBackend for EnvInstance { let hash = scale::Decode::decode(&mut &output[..])?; Ok(hash) } -} \ No newline at end of file +} From e69e7ce465a2152a217d5995007a714f38b42ca8 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 8 Dec 2022 18:08:15 +0000 Subject: [PATCH 056/206] Add fallible_constructor_reverted_lang_error FAILs --- crates/env/src/engine/mod.rs | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index c01d7f6c21c..1ccbb206dd4 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -97,13 +97,33 @@ mod tests { #[test] fn fallible_constructor_reverted_contract_error() { - let encoded_return_value = ConstructorResult::Ok(Result::< - ink_primitives::AccountId, + let return_value = Ok(Err(ContractError("Constructor error".to_owned()))); + let encoded_return_value = + > as Encode>::encode( + &return_value, + ); + + let decoded_result = decode_fallible_constructor_reverted_return_value::< + _, + crate::DefaultEnvironment, ContractError, - >::Err(ContractError( - "Constructor error".to_owned(), - ))) - .encode(); + >(&mut &encoded_return_value[..]); + + assert!(matches!( + decoded_result, + Ok(Ok(Err(ContractError( + _ + )))) + )) + } + + #[test] + fn fallible_constructor_reverted_lang_error() { + let return_value = Err(ink_primitives::LangError::CouldNotReadInput); + let encoded_return_value = + > as Encode>::encode( + &return_value, + ); let decoded_result = decode_fallible_constructor_reverted_return_value::< _, @@ -113,9 +133,7 @@ mod tests { assert!(matches!( decoded_result, - Ok(Ok(Result::::Err( - ContractError(_) - ))) + Ok(Err(ink_primitives::LangError::CouldNotReadInput)) )) } } From f08476334f81bb5294a4e9873d1a1863ea64f1c3 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 8 Dec 2022 18:09:34 +0000 Subject: [PATCH 057/206] Rename tests --- crates/env/src/engine/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 1ccbb206dd4..d60e380a380 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -96,7 +96,7 @@ mod tests { struct ContractError(String); #[test] - fn fallible_constructor_reverted_contract_error() { + fn fallible_constructor_reverted_inner_contract_error() { let return_value = Ok(Err(ContractError("Constructor error".to_owned()))); let encoded_return_value = > as Encode>::encode( @@ -118,7 +118,7 @@ mod tests { } #[test] - fn fallible_constructor_reverted_lang_error() { + fn fallible_constructor_reverted_outer_lang_error() { let return_value = Err(ink_primitives::LangError::CouldNotReadInput); let encoded_return_value = > as Encode>::encode( From 74f239262ef0e159072a568a323f272ff21924f1 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 8 Dec 2022 18:24:15 +0000 Subject: [PATCH 058/206] Add test for a decode error --- crates/env/src/engine/mod.rs | 61 ++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index d60e380a380..a1e237db133 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -88,52 +88,59 @@ where } #[cfg(test)] -mod tests { +mod fallible_constructor_reverted_tests { use super::*; use scale::Encode; #[derive(scale::Encode, scale::Decode)] struct ContractError(String); - #[test] - fn fallible_constructor_reverted_inner_contract_error() { - let return_value = Ok(Err(ContractError("Constructor error".to_owned()))); - let encoded_return_value = - > as Encode>::encode( - &return_value, - ); + fn roundtrip_return_value( + return_value: ConstructorResult>, + ) -> EnvResult>> + { + let encoded_return_value = return_value.encode(); + decode_return_value(&mut &encoded_return_value[..]) + } - let decoded_result = decode_fallible_constructor_reverted_return_value::< - _, + fn decode_return_value( + input: &mut I, + ) -> EnvResult>> + { + decode_fallible_constructor_reverted_return_value::< + I, crate::DefaultEnvironment, ContractError, - >(&mut &encoded_return_value[..]); + >(input) + } - assert!(matches!( - decoded_result, - Ok(Ok(Err(ContractError( - _ - )))) - )) + #[test] + fn inner_contract_error() { + let return_value = Ok(Err(ContractError("Constructor error".to_owned()))); + + let decoded_result = roundtrip_return_value(return_value); + + assert!(matches!(decoded_result, Ok(Ok(Err(ContractError(_)))))) } #[test] - fn fallible_constructor_reverted_outer_lang_error() { + fn outer_lang_error() { let return_value = Err(ink_primitives::LangError::CouldNotReadInput); - let encoded_return_value = - > as Encode>::encode( - &return_value, - ); - let decoded_result = decode_fallible_constructor_reverted_return_value::< - _, - crate::DefaultEnvironment, - ContractError, - >(&mut &encoded_return_value[..]); + let decoded_result = roundtrip_return_value(return_value); assert!(matches!( decoded_result, Ok(Err(ink_primitives::LangError::CouldNotReadInput)) )) } + + #[test] + fn err_decoding_return_value() { + let invalid_encoded_return_value = vec![69]; + + let decoded_result = decode_return_value(&mut &invalid_encoded_return_value[..]); + + assert!(matches!(decoded_result, Err(crate::Error::Decode(_)))) + } } From e3a99f909034afbe265fcc392baca2fc492a98b0 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 8 Dec 2022 18:26:44 +0000 Subject: [PATCH 059/206] Rename some tests --- crates/env/src/engine/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index a1e237db133..924c724abf9 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -115,7 +115,7 @@ mod fallible_constructor_reverted_tests { } #[test] - fn inner_contract_error() { + fn err_inner_contract() { let return_value = Ok(Err(ContractError("Constructor error".to_owned()))); let decoded_result = roundtrip_return_value(return_value); @@ -123,8 +123,9 @@ mod fallible_constructor_reverted_tests { assert!(matches!(decoded_result, Ok(Ok(Err(ContractError(_)))))) } + // todo: FAILS! Is my test incorrect or is the impl incorrect? #[test] - fn outer_lang_error() { + fn err_outer_lang() { let return_value = Err(ink_primitives::LangError::CouldNotReadInput); let decoded_result = roundtrip_return_value(return_value); From 56e8d520d03f7c242402aa328e31bc73130a87bd Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 8 Dec 2022 14:24:01 -0500 Subject: [PATCH 060/206] Make `Result` types more explicit --- crates/env/src/engine/mod.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 924c724abf9..e87697bfe62 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -44,6 +44,8 @@ use crate::{ }; use ink_primitives::ConstructorResult; +type ContractResult = core::result::Result; + pub(crate) fn decode_fallible_constructor_reverted_return_value( out_return_value: &mut I, ) -> EnvResult>> @@ -116,23 +118,31 @@ mod fallible_constructor_reverted_tests { #[test] fn err_inner_contract() { - let return_value = Ok(Err(ContractError("Constructor error".to_owned()))); + let return_value = ConstructorResult::Ok(ContractResult::Err(ContractError( + "Constructor error".to_owned(), + ))); let decoded_result = roundtrip_return_value(return_value); - assert!(matches!(decoded_result, Ok(Ok(Err(ContractError(_)))))) + assert!(matches!( + decoded_result, + EnvResult::Ok(ConstructorResult::Ok(ContractResult::Err(ContractError(_)))) + )) } // todo: FAILS! Is my test incorrect or is the impl incorrect? #[test] fn err_outer_lang() { - let return_value = Err(ink_primitives::LangError::CouldNotReadInput); + let return_value = + ConstructorResult::Err(ink_primitives::LangError::CouldNotReadInput); let decoded_result = roundtrip_return_value(return_value); assert!(matches!( decoded_result, - Ok(Err(ink_primitives::LangError::CouldNotReadInput)) + EnvResult::Ok(ConstructorResult::Err( + ink_primitives::LangError::CouldNotReadInput + )) )) } From 50c227ba50b3f84715535a3f37a26b00a62ccc05 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 8 Dec 2022 14:37:19 -0500 Subject: [PATCH 061/206] Add another test --- crates/env/src/engine/mod.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index e87697bfe62..19bba23bccb 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -102,6 +102,7 @@ mod fallible_constructor_reverted_tests { ) -> EnvResult>> { let encoded_return_value = return_value.encode(); + dbg!(&encoded_return_value); decode_return_value(&mut &encoded_return_value[..]) } @@ -117,9 +118,18 @@ mod fallible_constructor_reverted_tests { } #[test] - fn err_inner_contract() { + fn revert_branch_rejects_valid_output_buffer_with_success_case() { + let return_value = ConstructorResult::Ok(ContractResult::Ok(())); + + let _decoded_result = roundtrip_return_value(return_value); + + todo!("This should fail.") + } + + #[test] + fn succesful_dispatch_with_error_from_contract_constructor() { let return_value = ConstructorResult::Ok(ContractResult::Err(ContractError( - "Constructor error".to_owned(), + "Contract's constructor failed.".to_owned(), ))); let decoded_result = roundtrip_return_value(return_value); @@ -132,7 +142,7 @@ mod fallible_constructor_reverted_tests { // todo: FAILS! Is my test incorrect or is the impl incorrect? #[test] - fn err_outer_lang() { + fn dispatch_error_gets_decoded_correctly() { let return_value = ConstructorResult::Err(ink_primitives::LangError::CouldNotReadInput); @@ -147,7 +157,7 @@ mod fallible_constructor_reverted_tests { } #[test] - fn err_decoding_return_value() { + fn invalid_bytes_in_output_buffer_fail_decoding() { let invalid_encoded_return_value = vec![69]; let decoded_result = decode_return_value(&mut &invalid_encoded_return_value[..]); From 8ce1d92218b275152f4cc51da89eb793a7f352da Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 8 Dec 2022 14:58:17 -0500 Subject: [PATCH 062/206] Clean up decoding match statement --- crates/env/src/engine/mod.rs | 48 ++++++++++++------------------------ 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 19bba23bccb..b92a74ae3bd 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -54,38 +54,22 @@ where E: Environment, ContractError: scale::Decode, { - let decoding_result = - > as scale::Decode>::decode( - out_return_value, - ); - - match decoding_result { - Ok(constructor_result) => { - let contract_result = constructor_result.expect( - "If dispatch had failed, we shouldn't have been able to decode \ - the nested `Result`.", - ); - - let contract_error = contract_result.expect_err( - "Since the contract reverted, we only expect an `Error` from the constructor. \ - Otherwise we would be in the `AccountId` branch."); - - Ok(Ok(Err(contract_error))) + let out = > as scale::Decode>::decode( + out_return_value, + )?; + + match out { + ConstructorResult::Ok(ContractResult::Ok(())) => { + // Since the contract reverted we don't expect an `Ok` return value from the + // constructor, otherwise we'd be in the `AccountId` decoding branch. + Err(crate::Error::Decode( + "TODO: probably shouldn't be a `Decode` error".into(), + )) } - Err(_) => { - // If we hit this branch it likely means dispatch failed, but we need to - // check the buffer again to confirm. - let out = as scale::Decode>::decode( - out_return_value, - )?; - - let lang_error = out.expect_err( - "If dispatch had succeeded, we would either be in the `AccountId` branch \ - or we would've been able to decode into a nested `Result` earlier." - ); - - Ok(Err(lang_error)) + ConstructorResult::Ok(ContractResult::Err(contract_error)) => { + Ok(ConstructorResult::Ok(ContractResult::Err(contract_error))) } + ConstructorResult::Err(lang_error) => Ok(ConstructorResult::Err(lang_error)), } } @@ -121,9 +105,9 @@ mod fallible_constructor_reverted_tests { fn revert_branch_rejects_valid_output_buffer_with_success_case() { let return_value = ConstructorResult::Ok(ContractResult::Ok(())); - let _decoded_result = roundtrip_return_value(return_value); + let decoded_result = roundtrip_return_value(return_value); - todo!("This should fail.") + assert!(matches!(decoded_result, Err(crate::Error::Decode(_)))) } #[test] From c291b3cac1ad2fb91006a712007e68613aebdeb0 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 9 Dec 2022 13:30:02 -0500 Subject: [PATCH 063/206] Andrew was right --- crates/env/src/engine/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index b92a74ae3bd..2978298517b 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -48,7 +48,7 @@ type ContractResult = core::result::Result; pub(crate) fn decode_fallible_constructor_reverted_return_value( out_return_value: &mut I, -) -> EnvResult>> +) -> EnvResult>> where I: scale::Input, E: Environment, @@ -124,7 +124,6 @@ mod fallible_constructor_reverted_tests { )) } - // todo: FAILS! Is my test incorrect or is the impl incorrect? #[test] fn dispatch_error_gets_decoded_correctly() { let return_value = From f0561e5d9464b2ce1db1b6efc3910ae17dbb93e1 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sun, 11 Dec 2022 11:47:30 -0500 Subject: [PATCH 064/206] Small cleanups to naming and imports --- crates/env/src/engine/mod.rs | 17 ++++++++--------- crates/env/src/engine/on_chain/impls.rs | 8 +++++--- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 2978298517b..6276b93af02 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -38,20 +38,19 @@ cfg_if! { } } -use crate::{ - Environment, - Result as EnvResult, -}; +use crate::Result as EnvResult; use ink_primitives::ConstructorResult; type ContractResult = core::result::Result; +// We only use this function when 1) compiling to Wasm 2) compiling for tests +#[cfg_attr(all(feature = "std", not(test)), allow(dead_code))] pub(crate) fn decode_fallible_constructor_reverted_return_value( out_return_value: &mut I, ) -> EnvResult>> where I: scale::Input, - E: Environment, + E: crate::Environment, ContractError: scale::Decode, { let out = > as scale::Decode>::decode( @@ -81,7 +80,7 @@ mod fallible_constructor_reverted_tests { #[derive(scale::Encode, scale::Decode)] struct ContractError(String); - fn roundtrip_return_value( + fn encode_and_decode_return_value( return_value: ConstructorResult>, ) -> EnvResult>> { @@ -105,7 +104,7 @@ mod fallible_constructor_reverted_tests { fn revert_branch_rejects_valid_output_buffer_with_success_case() { let return_value = ConstructorResult::Ok(ContractResult::Ok(())); - let decoded_result = roundtrip_return_value(return_value); + let decoded_result = encode_and_decode_return_value(return_value); assert!(matches!(decoded_result, Err(crate::Error::Decode(_)))) } @@ -116,7 +115,7 @@ mod fallible_constructor_reverted_tests { "Contract's constructor failed.".to_owned(), ))); - let decoded_result = roundtrip_return_value(return_value); + let decoded_result = encode_and_decode_return_value(return_value); assert!(matches!( decoded_result, @@ -129,7 +128,7 @@ mod fallible_constructor_reverted_tests { let return_value = ConstructorResult::Err(ink_primitives::LangError::CouldNotReadInput); - let decoded_result = roundtrip_return_value(return_value); + let decoded_result = encode_and_decode_return_value(return_value); assert!(matches!( decoded_result, diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 9711ee03749..b8248d3188e 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -572,9 +572,11 @@ impl TypedEnvBackend for EnvInstance { Ok(ink_primitives::ConstructorResult::Ok(Ok(account_id))) } Err(ext::Error::CalleeReverted) => { - decode_fallible_constructor_reverted_return_value::<_, E, ContractError>( - &mut &out_return_value[..], - ) + crate::engine::decode_fallible_constructor_reverted_return_value::< + _, + E, + ContractError, + >(&mut &out_return_value[..]) } Err(actual_error) => Err(actual_error.into()), } From 1742a01bf857f24c018df67836bcb1f10b980672 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sun, 11 Dec 2022 11:56:32 -0500 Subject: [PATCH 065/206] Couple more import and comment fixes --- crates/env/src/engine/mod.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 6276b93af02..90516380a2f 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -12,11 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::backend::{ - EnvBackend, - TypedEnvBackend, +use crate::{ + backend::{ + EnvBackend, + TypedEnvBackend, + }, + Result as EnvResult, }; use cfg_if::cfg_if; +use ink_primitives::ConstructorResult; pub trait OnInstance: EnvBackend + TypedEnvBackend { fn on_instance(f: F) -> R @@ -38,12 +42,10 @@ cfg_if! { } } -use crate::Result as EnvResult; -use ink_primitives::ConstructorResult; - +// The `Result` type used to represent the programmer defined contract output. type ContractResult = core::result::Result; -// We only use this function when 1) compiling to Wasm 2) compiling for tests +// We only use this function when 1) compiling to Wasm 2) compiling for tests. #[cfg_attr(all(feature = "std", not(test)), allow(dead_code))] pub(crate) fn decode_fallible_constructor_reverted_return_value( out_return_value: &mut I, @@ -85,7 +87,6 @@ mod fallible_constructor_reverted_tests { ) -> EnvResult>> { let encoded_return_value = return_value.encode(); - dbg!(&encoded_return_value); decode_return_value(&mut &encoded_return_value[..]) } From 25d8326d17ed7fb4e1dd7035fe30f6afa3c89060 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sun, 11 Dec 2022 11:58:56 -0500 Subject: [PATCH 066/206] Use decode trait method directly --- crates/env/src/engine/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 90516380a2f..656527e6423 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -55,9 +55,8 @@ where E: crate::Environment, ContractError: scale::Decode, { - let out = > as scale::Decode>::decode( - out_return_value, - )?; + let out: ConstructorResult> = + scale::Decode::decode(out_return_value)?; match out { ConstructorResult::Ok(ContractResult::Ok(())) => { From 24e9424d8b8ea9aa05820fdc3bb677af79724e18 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sun, 11 Dec 2022 12:57:54 -0500 Subject: [PATCH 067/206] Fix `call-builder` E2E tests This now accounts for the better error handling in the `CalleeReverted` case --- .../call-builder/lib.rs | 71 ++++++++++--------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 4dee6b06326..6126b069184 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -94,11 +94,15 @@ mod call_builder { code_hash: Hash, selector: [u8; 4], init_value: bool, - ) -> Option> - { + ) -> Option< + Result< + Result, + ink::LangError, + >, + > { use ink::env::call::build_create; - let result = build_create::() + let lang_result = build_create::() .code_hash(code_hash) .gas_limit(0) .endowment(0) @@ -112,11 +116,12 @@ mod call_builder { >>() .params() .try_instantiate_fallible() - .expect("Error from the Contracts pallet.") - .expect("Dispatch should have succeeded."); - ::ink::env::debug_println!("Result from `instantiate` {:?}", &result); + .expect("Error from the Contracts pallet."); + ::ink::env::debug_println!("Result from `instantiate` {:?}", &lang_result); - Some(result.map(|inner| ink::ToAccountId::to_account_id(&inner))) + Some(lang_result.map(|contract_result| { + contract_result.map(|inner| ink::ToAccountId::to_account_id(&inner)) + })) } } @@ -341,9 +346,9 @@ mod call_builder { let call_result = client .call(&mut ink_e2e::eve(), call, 0, None) .await - .expect("Calling `call_builder::call_instantiate` failed") + .expect("Calling `call_builder::call_instantiate_fallible` failed") .value - .expect("Dispatching `call_builder::call_instantiate` failed."); + .expect("Dispatching `call_builder::call_instantiate_fallible` failed."); assert!( call_result.unwrap().is_ok(), @@ -379,13 +384,20 @@ mod call_builder { let call_result = client .call(&mut ink_e2e::ferdie(), call, 0, None) .await - .expect("Calling `call_builder::call_instantiate` failed") + .expect("Calling `call_builder::call_instantiate_fallible` failed") .value - .expect("Dispatching `call_builder::call_instantiate` failed."); + .expect("Dispatching `call_builder::call_instantiate_fallible` failed."); + + let contract_result = call_result + .unwrap() + .expect("Dispatching `constructors_return_value::try_new` failed."); assert!( - call_result.unwrap().is_err(), - "Call to falliable constructor succeeded, when it should have failed." + matches!( + contract_result, + Err(constructors_return_value::ConstructorError) + ), + "Got an unexpected error from the contract." ); Ok(()) @@ -424,10 +436,7 @@ mod call_builder { let contains_err_msg = match call_result.unwrap_err() { ink_e2e::Error::CallDryRun(dry_run) => { String::from_utf8_lossy(&dry_run.debug_message) - .contains( - "Since the contract reverted, we only expect an `Error` from the constructor. \ - Otherwise we would be in the `AccountId` branch." - ) + .contains("Error from the Contracts pallet.: Decode(Error)") } _ => false, }; @@ -462,25 +471,19 @@ mod call_builder { build_message::(contract_acc_id).call(|contract| { contract.call_instantiate_fallible(code_hash, selector, init_value) }); - let call_result = client.call(&mut ink_e2e::bob(), call, 0, None).await; - - assert!( - call_result.is_err(), - "Call execution should've failed, but didn't." - ); + let call_result = client + .call(&mut ink_e2e::bob(), call, 0, None) + .await + .expect( + "Client failed to call `call_builder::call_instantiate_fallible`.", + ) + .value + .expect("Dispatching `call_builder::call_instantiate_fallible` failed."); - let contains_err_msg = match call_result.unwrap_err() { - ink_e2e::Error::CallDryRun(dry_run) => { - String::from_utf8_lossy(&dry_run.debug_message).contains( - "If dispatch had failed, we shouldn't have been able to decode \ - the nested `Result`.", - ) - } - _ => false, - }; assert!( - contains_err_msg, - "Call execution failed for an unexpected reason." + matches!(call_result, Some(Err(ink::LangError::CouldNotReadInput))), + "The callee manually encoded `CouldNotReadInput` to the output buffer, we should've + gotten that back." ); Ok(()) From e7bba67fd8ba92a3923095556bc2bbcbef297992 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sun, 11 Dec 2022 13:13:39 -0500 Subject: [PATCH 068/206] Remove leading colons from non-codegen contexts --- crates/env/src/api.rs | 6 ++---- crates/env/src/backend.rs | 6 +++--- crates/env/src/call/create_builder.rs | 20 +++++++------------ crates/env/src/engine/off_chain/impls.rs | 4 ++-- crates/env/src/engine/on_chain/impls.rs | 6 +++--- .../call-builder/lib.rs | 8 ++++---- 6 files changed, 21 insertions(+), 29 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index dc28bcab1a3..be16afe3679 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -321,7 +321,7 @@ where /// - If the returned account ID failed to decode properly. pub fn instantiate_contract( params: &CreateParams, -) -> Result<::ink_primitives::ConstructorResult> +) -> Result> where E: Environment, Args: scale::Encode, @@ -351,9 +351,7 @@ where pub fn instantiate_fallible_contract( params: &CreateParams, ) -> Result< - ::ink_primitives::ConstructorResult< - ::core::result::Result, - >, + ink_primitives::ConstructorResult>, > where E: Environment, diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index bfa7fd09438..b186f45b35e 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -442,7 +442,7 @@ pub trait TypedEnvBackend: EnvBackend { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result<::ink_primitives::ConstructorResult> + ) -> Result> where E: Environment, Args: scale::Encode, @@ -458,8 +458,8 @@ pub trait TypedEnvBackend: EnvBackend { &mut self, params: &CreateParams, ) -> Result< - ::ink_primitives::ConstructorResult< - ::core::result::Result, + ink_primitives::ConstructorResult< + core::result::Result, >, > where diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index ba022bb780a..4f0b771ca24 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -143,7 +143,7 @@ where #[inline] pub fn try_instantiate( &self, - ) -> Result<::ink_primitives::ConstructorResult, crate::Error> { + ) -> Result, crate::Error> { crate::instantiate_contract(self) .map(|inner| inner.map(FromAccountId::from_account_id)) } @@ -183,7 +183,7 @@ where #[inline] pub fn try_instantiate_fallible( &self, - ) -> Result<::ink_primitives::ConstructorResult>, crate::Error> + ) -> Result>, crate::Error> { crate::instantiate_fallible_contract(self).map(|constructor_result| { constructor_result.map(|contract_result| { @@ -511,7 +511,7 @@ where #[inline] pub fn try_instantiate( self, - ) -> Result<::ink_primitives::ConstructorResult, Error> { + ) -> Result, Error> { self.params().try_instantiate() } } @@ -524,7 +524,7 @@ impl Set, Set>, Set, - Set>>, + Set>>, > where E: Environment, @@ -541,9 +541,7 @@ where /// This method panics if it encounters an [`ink_primitives::LangError`]. If you want to handle /// those use the [`try_instantiate_fallible`][`CreateParams::try_instantiate_fallible`] method instead. #[inline] - pub fn instantiate_fallible( - self, - ) -> Result<::core::result::Result, Error> { + pub fn instantiate_fallible(self) -> Result, Error> { self.params().instantiate_fallible() } @@ -555,12 +553,8 @@ where #[inline] pub fn try_instantiate_fallible( self, - ) -> Result< - ::ink_primitives::ConstructorResult< - ::core::result::Result, - >, - Error, - > { + ) -> Result>, Error> + { self.params().try_instantiate_fallible() } } diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index a1159e8f506..e6703f8c8ff 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -490,8 +490,8 @@ impl TypedEnvBackend for EnvInstance { &mut self, params: &CreateParams, ) -> Result< - ::ink_primitives::ConstructorResult< - ::core::result::Result, + ink_primitives::ConstructorResult< + core::result::Result, >, > where diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index b8248d3188e..2ea3b65d434 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -482,7 +482,7 @@ impl TypedEnvBackend for EnvInstance { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result<::ink_primitives::ConstructorResult> + ) -> Result> where E: Environment, Args: scale::Encode, @@ -533,8 +533,8 @@ impl TypedEnvBackend for EnvInstance { &mut self, params: &CreateParams, ) -> Result< - ::ink_primitives::ConstructorResult< - ::core::result::Result, + ink_primitives::ConstructorResult< + core::result::Result, >, > where diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 6126b069184..9ad1c413668 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -37,13 +37,13 @@ mod call_builder { &mut self, address: AccountId, selector: [u8; 4], - ) -> Option<::ink::LangError> { + ) -> Option { use ink::env::call::build_call; let result = build_call::() .call_type(Call::new().callee(address)) .exec_input(ExecutionInput::new(Selector::new(selector))) - .returns::>() + .returns::>() .fire() .expect("Error from the Contracts pallet."); @@ -62,7 +62,7 @@ mod call_builder { code_hash: Hash, selector: [u8; 4], init_value: bool, - ) -> Option<::ink::LangError> { + ) -> Option { use ink::env::call::build_create; let result = build_create::() @@ -183,7 +183,7 @@ mod call_builder { assert!(matches!( flipper_result, - Some(::ink::LangError::CouldNotReadInput) + Some(ink::LangError::CouldNotReadInput) )); let flipper_get = build_message::(flipper_acc_id) From ebd42f3d40469f88c31b92df3b0cc5d618de6b67 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sun, 11 Dec 2022 13:41:09 -0500 Subject: [PATCH 069/206] Add doc test for `instantiate_fallible_contract` --- crates/ink/src/env_access.rs | 83 ++++++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 4 deletions(-) diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 1c18ff9b2d4..c312784bff8 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -449,7 +449,7 @@ where /// .gas_limit(4000) /// .endowment(25) /// .exec_input( - /// ExecutionInput::new(Selector::new([0xCA, 0xFE, 0xBA, 0xBE])) + /// ExecutionInput::new(Selector::new(ink::selector_bytes!("new"))) /// .push_arg(42) /// .push_arg(true) /// .push_arg(&[0x10u8; 32]), @@ -489,13 +489,88 @@ where ink_env::instantiate_contract::(params) } - /// TODO: Docs + /// Attempts to instantiate a contract, returning the execution result back to the caller. + /// + /// # Example + /// + /// ``` + /// # #[ink::contract] + /// # pub mod my_contract { + /// # // In order for this to actually work with another contract we'd need a way + /// # // to turn the `ink-as-dependency` crate feature on in doctests, which we + /// # // can't do. + /// # // + /// # // Instead we use our own contract's `Ref`, which is fine for this example + /// # // (just need something that implements the `ContractRef` trait). + /// # pub mod other_contract { + /// # pub use super::MyContractRef as OtherContractRef; + /// # pub use super::ConstructorError as OtherConstructorError; + /// # } + /// use ink::env::{ + /// DefaultEnvironment, + /// call::{build_create, Selector, ExecutionInput} + /// }; + /// use other_contract::{OtherContractRef, OtherConstructorError}; + /// + /// # #[derive(scale::Encode, scale::Decode, Debug)] + /// # #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] + /// # pub struct ConstructorError; + /// # + /// # #[ink(storage)] + /// # pub struct MyContract { } + /// # + /// # impl MyContract { + /// # #[ink(constructor)] + /// # pub fn try_new() -> Result { + /// # Ok(Self {}) + /// # } + /// # + /// /// Attempts to instantiate a contract, returning the `AccountId` back to the caller. + /// #[ink(message)] + /// pub fn instantiate_fallible_contract(&self) -> AccountId { + /// let create_params = build_create::() + /// .code_hash(Hash::from([0x42; 32])) + /// .gas_limit(4000) + /// .endowment(25) + /// .exec_input( + /// ExecutionInput::new(Selector::new(ink::selector_bytes!("try_new"))) + /// .push_arg(42) + /// .push_arg(true) + /// .push_arg(&[0x10u8; 32]), + /// ) + /// .salt_bytes(&[0xCA, 0xFE, 0xBA, 0xBE]) + /// .returns::>() + /// .params(); + /// self.env() + /// .instantiate_fallible_contract(&create_params) + /// .unwrap_or_else(|error| { + /// panic!( + /// "Received an error from the Contracts pallet while instantiating: {:?}", + /// error + /// ) + /// }) + /// .unwrap_or_else(|error| panic!("Received a `LangError` while instatiating: {:?}", error)) + /// .unwrap_or_else(|error: ConstructorError| { + /// panic!( + /// "Received a `ConstructorError` while instatiating: {:?}", + /// error + /// ) + /// }) + /// } + /// # + /// # } + /// # } + /// ``` + /// + /// # Note + /// + /// For more details visit: [`ink_env::instantiate_fallible_contract`] pub fn instantiate_fallible_contract( self, params: &CreateParams, ) -> Result< - ::ink_primitives::ConstructorResult< - ::core::result::Result, + ink_primitives::ConstructorResult< + core::result::Result, >, > where From 0a99f1670cfd34418bc9cf9534baa6aa267ba19d Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sun, 11 Dec 2022 13:52:52 -0500 Subject: [PATCH 070/206] Add doc test to `build_create` function --- crates/env/src/call/create_builder.rs | 46 +++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 4f0b771ca24..c8b48764d80 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -211,6 +211,12 @@ where /// /// # Example /// +/// **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 1: Returns Address of Instantiated Contract +/// /// The below example shows instantiation of contract of type `MyContract`. /// /// The used constructor: @@ -253,9 +259,43 @@ where /// .unwrap(); /// ``` /// -/// **Note:** The shown example panics 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 2: Handles Result from Fallible Constructor +/// +/// ```should_panic +/// # use ::ink_env::{ +/// # Environment, +/// # DefaultEnvironment, +/// # call::{build_create, Selector, ExecutionInput, FromAccountId} +/// # }; +/// # type Hash = ::Hash; +/// # type AccountId = ::AccountId; +/// # type Salt = &'static [u8]; +/// # struct MyContract; +/// # impl FromAccountId for MyContract { +/// # fn from_account_id(account_id: AccountId) -> Self { Self } +/// # } +/// # #[derive(scale::Encode, scale::Decode, Debug)] +/// # #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +/// # pub struct ConstructorError; +/// let my_contract: MyContract = build_create::() +/// .code_hash(Hash::from([0x42; 32])) +/// .gas_limit(4000) +/// .endowment(25) +/// .exec_input( +/// ExecutionInput::new(Selector::new([0xDE, 0xAD, 0xBE, 0xEF])) +/// .push_arg(42) +/// .push_arg(true) +/// .push_arg(&[0x10u8; 32]) +/// ) +/// .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) +/// .returns::>() +/// .params() +/// .instantiate_fallible() +/// .unwrap() +/// .unwrap(); +/// ``` +/// +/// Note the usage of the [`CreateBuilder::instantiate_fallible`] method. #[allow(clippy::type_complexity)] pub fn build_create() -> CreateBuilder< E, From 6cf60e695411db8bf8d6bbd6f1c6768d9d9bb4c3 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sun, 11 Dec 2022 13:53:46 -0500 Subject: [PATCH 071/206] Remove leftover trait bound We can't use this with fallible constructors --- crates/env/src/call/create_builder.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index c8b48764d80..3baee0a32ce 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -472,8 +472,6 @@ where pub fn returns( self, ) -> CreateBuilder>> -// where - // R: FromAccountId, { CreateBuilder { code_hash: self.code_hash, From 581291ba936bc7f817a7c5cb32ab9498ec0160d4 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sun, 11 Dec 2022 14:04:23 -0500 Subject: [PATCH 072/206] Remove a few more leading colons --- crates/env/src/engine/off_chain/impls.rs | 2 +- crates/ink/src/env_access.rs | 2 +- .../constructors-return-value/lib.rs | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index e6703f8c8ff..33cc97fc98b 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -472,7 +472,7 @@ impl TypedEnvBackend for EnvInstance { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result<::ink_primitives::ConstructorResult> + ) -> Result> where E: Environment, Args: scale::Encode, diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index c312784bff8..690e19d17f2 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -481,7 +481,7 @@ where pub fn instantiate_contract( self, params: &CreateParams, - ) -> Result<::ink_primitives::ConstructorResult> + ) -> Result> where Args: scale::Encode, Salt: AsRef<[u8]>, 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 76c8b8f9d72..3ac1fed2287 100644 --- a/examples/lang-err-integration-tests/constructors-return-value/lib.rs +++ b/examples/lang-err-integration-tests/constructors-return-value/lib.rs @@ -38,8 +38,8 @@ pub mod constructors_return_value { /// return value. #[ink(constructor)] pub fn revert_new(_init_value: bool) -> Self { - ::ink::env::return_value::>( - ::ink::env::ReturnFlags::new_with_reverted(true), + ink::env::return_value::>( + ink::env::ReturnFlags::new_with_reverted(true), &Ok(AccountId::from([0u8; 32])), ) } @@ -54,9 +54,9 @@ pub mod constructors_return_value { Err(ink::LangError::CouldNotReadInput) }; - ::ink::env::return_value::< + ink::env::return_value::< ink::ConstructorResult>, - >(::ink::env::ReturnFlags::new_with_reverted(true), &value) + >(ink::env::ReturnFlags::new_with_reverted(true), &value) } /// Returns the current value of the contract storage. @@ -139,7 +139,7 @@ pub mod constructors_return_value { .expect("Instantiate dry run should succeed"); let data = infallible_constructor_result.result.data; - let decoded_result = Result::<(), ::ink::LangError>::decode(&mut &data[..]) + let decoded_result = Result::<(), ink::LangError>::decode(&mut &data[..]) .expect("Failed to decode constructor Result"); assert!( decoded_result.is_ok(), From 95f9e6e8fcacaa272b5120993a84f73178c52430 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 12 Dec 2022 13:42:46 -0500 Subject: [PATCH 073/206] Panic in case where we get `Ok` encoded into error buffer --- crates/env/src/engine/mod.rs | 16 ++++++++++------ .../call-builder/lib.rs | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 656527e6423..440cc5b1032 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -62,9 +62,12 @@ where ConstructorResult::Ok(ContractResult::Ok(())) => { // Since the contract reverted we don't expect an `Ok` return value from the // constructor, otherwise we'd be in the `AccountId` decoding branch. - Err(crate::Error::Decode( - "TODO: probably shouldn't be a `Decode` error".into(), - )) + // + // While we could handle this more gracefully, e.g through a `LangError`, we're going to + // be defensive for now and trap. + panic!( + "The callee reverted, but did not encode an error in the output buffer." + ) } ConstructorResult::Ok(ContractResult::Err(contract_error)) => { Ok(ConstructorResult::Ok(ContractResult::Err(contract_error))) @@ -101,12 +104,13 @@ mod fallible_constructor_reverted_tests { } #[test] + #[should_panic( + expected = "The callee reverted, but did not encode an error in the output buffer." + )] fn revert_branch_rejects_valid_output_buffer_with_success_case() { let return_value = ConstructorResult::Ok(ContractResult::Ok(())); - let decoded_result = encode_and_decode_return_value(return_value); - - assert!(matches!(decoded_result, Err(crate::Error::Decode(_)))) + let _decoded_result = encode_and_decode_return_value(return_value); } #[test] diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 9ad1c413668..84de5f131aa 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -436,7 +436,7 @@ mod call_builder { let contains_err_msg = match call_result.unwrap_err() { ink_e2e::Error::CallDryRun(dry_run) => { String::from_utf8_lossy(&dry_run.debug_message) - .contains("Error from the Contracts pallet.: Decode(Error)") + .contains("The callee reverted, but did not encode an error in the output buffer.") } _ => false, }; From 0d408251e523f7565777f3a658e63622c98d0808 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 12 Dec 2022 13:53:10 -0500 Subject: [PATCH 074/206] Add some links to env docs --- crates/env/src/api.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index be16afe3679..65abb542446 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -309,7 +309,9 @@ where /// # Note /// /// This is a low level way to instantiate another smart contract. -/// Prefer to use the ink! guided and type safe approach to using this. +/// +/// Prefer to use methods on a `ContractRef` or the [`CreateBuilder`](`crate::call::CreateBuilder`) +/// through [`build_create`](`crate::call::build_create`) instead. /// /// # Errors /// @@ -338,7 +340,9 @@ where /// # Note /// /// This is a low level way to instantiate another smart contract. -/// Prefer to use the ink! guided and type safe approach to using this. +/// +/// Prefer to use methods on a `ContractRef` or the [`CreateBuilder`](`crate::call::CreateBuilder`) +/// through [`build_create`](`crate::call::build_create`) instead. /// /// # Errors /// From c8e5cfa751e02ba1f1d0bc6f0fd8ff981ad52cc5 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 12 Dec 2022 14:05:24 -0500 Subject: [PATCH 075/206] Add more docs to `call-builder` E2E tests --- .../call-builder/lib.rs | 39 ++++++++++++++----- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 84de5f131aa..c1ffcf60811 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -2,8 +2,16 @@ //! //! This contract is used to ensure that the behavior around `LangError`s works as expected. //! -//! It makes use of ink!'s end-to-end testing features, so ensure that you have a node which -//! includes the Contract's pallet running alongside your tests. +//! In particular, it exercises the codepaths that stem from the usage of the +//! [`CallBuilder`](`ink_env::call::CallBuilder`) and [`CreateBuilder`](`ink_env::call::CreateBuilder`) +//! structs. +//! +//! This differs from the codepath used by external tooling, such as `cargo-contract` or the +//! `Contracts-UI` which instead depend on methods from the Contracts pallet which are exposed via +//! RPC. +//! +//! Note that during testing we make use of ink!'s end-to-end testing features, so ensure that you +//! have a node which includes the Contracts pallet running alongside your tests. #![cfg_attr(not(feature = "std"), no_std)] @@ -11,6 +19,8 @@ mod call_builder { use ink::env::{ call::{ + build_call, + build_create, Call, ExecutionInput, Selector, @@ -32,14 +42,15 @@ mod call_builder { /// /// 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. + /// + /// We also wrap the output in an `Option` since we can't return a `Result` directly from a + /// contract message without erroring out ourselves. #[ink(message)] pub fn call( &mut self, address: AccountId, selector: [u8; 4], ) -> Option { - use ink::env::call::build_call; - let result = build_call::() .call_type(Call::new().callee(address)) .exec_input(ExecutionInput::new(Selector::new(selector))) @@ -56,6 +67,13 @@ mod call_builder { } } + /// Instantiate a contract using the `CreateBuilder`. + /// + /// Since we can't use the `CreateBuilder` in a test environment directly we need this + /// wrapper to test things like crafting calls with invalid selectors. + /// + /// We also wrap the output in an `Option` since we can't return a `Result` directly from a + /// contract message without erroring out ourselves. #[ink(message)] pub fn call_instantiate( &mut self, @@ -63,8 +81,6 @@ mod call_builder { selector: [u8; 4], init_value: bool, ) -> Option { - use ink::env::call::build_create; - let result = build_create::() .code_hash(code_hash) .gas_limit(0) @@ -77,7 +93,6 @@ mod call_builder { .params() .try_instantiate() .expect("Error from the Contracts pallet."); - ::ink::env::debug_println!("Result from `instantiate` {:?}", &result); match result { Ok(_) => None, @@ -88,6 +103,13 @@ mod call_builder { } } + /// Attempt to instantiate a contract using the `CreateBuilder`. + /// + /// Since we can't use the `CreateBuilder` in a test environment directly we need this + /// wrapper to test things like crafting calls with invalid selectors. + /// + /// We also wrap the output in an `Option` since we can't return a `Result` directly from a + /// contract message without erroring out ourselves. #[ink(message)] pub fn call_instantiate_fallible( &mut self, @@ -100,8 +122,6 @@ mod call_builder { ink::LangError, >, > { - use ink::env::call::build_create; - let lang_result = build_create::() .code_hash(code_hash) .gas_limit(0) @@ -117,7 +137,6 @@ mod call_builder { .params() .try_instantiate_fallible() .expect("Error from the Contracts pallet."); - ::ink::env::debug_println!("Result from `instantiate` {:?}", &lang_result); Some(lang_result.map(|contract_result| { contract_result.map(|inner| ink::ToAccountId::to_account_id(&inner)) From 1e323f4bd86582cc056ff1737561c190fa427db8 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 12 Dec 2022 15:07:03 -0500 Subject: [PATCH 076/206] Use correct path in `call-builder` docs --- examples/lang-err-integration-tests/call-builder/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index c1ffcf60811..5ef06bf6d52 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -3,7 +3,7 @@ //! This contract is used to ensure that the behavior around `LangError`s works as expected. //! //! In particular, it exercises the codepaths that stem from the usage of the -//! [`CallBuilder`](`ink_env::call::CallBuilder`) and [`CreateBuilder`](`ink_env::call::CreateBuilder`) +//! [`CallBuilder`](`ink::env::call::CallBuilder`) and [`CreateBuilder`](`ink::env::call::CreateBuilder`) //! structs. //! //! This differs from the codepath used by external tooling, such as `cargo-contract` or the From 57a7a6b857f163c26e52c9238037d263c92fc2a7 Mon Sep 17 00:00:00 2001 From: andrew Date: Fri, 13 Jan 2023 17:56:43 +0000 Subject: [PATCH 077/206] Remove fallible create_builder.rs methods --- crates/env/src/call/create_builder.rs | 45 +-------------------------- 1 file changed, 1 insertion(+), 44 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 3baee0a32ce..86589d36b99 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -552,47 +552,4 @@ where ) -> Result, Error> { self.params().try_instantiate() } -} - -impl - CreateBuilder< - E, - Set, - GasLimit, - Set, - Set>, - Set, - Set>>, - > -where - E: Environment, - GasLimit: Unwrap, - Args: scale::Encode, - Salt: AsRef<[u8]>, - RetType: FromAccountId, - ContractError: scale::Decode, -{ - /// Attempts to instantiate the contract, returning the execution result back to the caller. - /// - /// # Panics - /// - /// This method panics if it encounters an [`ink_primitives::LangError`]. If you want to handle - /// those use the [`try_instantiate_fallible`][`CreateParams::try_instantiate_fallible`] method instead. - #[inline] - pub fn instantiate_fallible(self) -> Result, Error> { - self.params().instantiate_fallible() - } - - /// Attempts to instantiate the contract, returning the execution result back to the caller. - /// - /// # Note - /// - /// On failure this returns an [`ink_primitives::LangError`] which can be handled by the caller. - #[inline] - pub fn try_instantiate_fallible( - self, - ) -> Result>, Error> - { - self.params().try_instantiate_fallible() - } -} +} \ No newline at end of file From 99a37b847ccc271130207dbc973edfe072840c2d Mon Sep 17 00:00:00 2001 From: andrew Date: Sat, 14 Jan 2023 11:18:15 +0000 Subject: [PATCH 078/206] WIP experiment --- crates/env/src/api.rs | 5 +- crates/env/src/backend.rs | 10 +- crates/env/src/call/common.rs | 96 +++++++++++++++++++ crates/env/src/call/create_builder.rs | 4 +- crates/env/src/call/mod.rs | 2 + crates/env/src/engine/off_chain/impls.rs | 8 +- crates/env/src/engine/on_chain/impls.rs | 21 ++-- .../generator/as_dependency/contract_ref.rs | 4 +- 8 files changed, 135 insertions(+), 15 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 65abb542446..eb5d4c0e1d9 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -25,6 +25,8 @@ use crate::{ CallParams, CreateParams, DelegateCall, + FromAccountId, + utils::ConstructorOutputValue, }, engine::{ EnvInstance, @@ -323,11 +325,12 @@ where /// - If the returned account ID failed to decode properly. pub fn instantiate_contract( params: &CreateParams, -) -> Result> +) -> Result>> where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, + R: FromAccountId, { ::on_instance(|instance| { TypedEnvBackend::instantiate_contract::(instance, params) diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index b186f45b35e..b8c567777db 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -17,7 +17,12 @@ use crate::{ Call, CallParams, CreateParams, + FromAccountId, DelegateCall, + utils::{ + ConstructorOutput, + ConstructorOutputValue, + } }, hash::{ CryptoHash, @@ -442,11 +447,12 @@ pub trait TypedEnvBackend: EnvBackend { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result> + ) -> Result>> where E: Environment, Args: scale::Encode, - Salt: AsRef<[u8]>; + Salt: AsRef<[u8]>, + R: FromAccountId,; /// Attempts to instantiate another contract, returning the instantiation result back to the /// caller. diff --git a/crates/env/src/call/common.rs b/crates/env/src/call/common.rs index e1cc4171a2d..a2bc4addd00 100644 --- a/crates/env/src/call/common.rs +++ b/crates/env/src/call/common.rs @@ -15,6 +15,8 @@ //! Utilities, types and abstractions common to call and instantiation routines. use core::marker::PhantomData; +use crate::call::FromAccountId; +use crate::Environment; /// Represents a return type. /// @@ -38,6 +40,100 @@ impl Default for ReturnType { } } +mod private { + /// Seals the implementation of `ConstructorReturnType`. + pub trait Sealed {} +} + +/// Guards against using invalid contract initializer types. +/// +/// # Note +/// +/// Currently the only allowed types are `()` and `Result<(), E>` +/// where `E` is some unspecified error type. +/// If the contract initializer returns `Result::Err` the utility +/// method that is used to initialize an ink! smart contract will +/// revert the state of the contract instantiation. +pub trait ConstructorOutput: private::Sealed { + /// Is `true` if `Self` is `Result`. + const IS_RESULT: bool = false; + + /// Reflects the output type of the dispatchable ink! constructor. + type Output; + + /// The error type of the constructor return type. + /// + /// # Note + /// + /// For infallible constructors this is `()` whereas for fallible + /// constructors this is the actual return error type. Since we only ever + /// return a value in case of `Result::Err` the `Result::Ok` value type + /// does not matter. + type Error; + + // todo: docs + fn from_account_id(account_id: Env::AccountId) -> Self::Output; + + /// Converts the return value into a `Result` instance. + /// + /// # Note + /// + /// For infallible constructor returns this always yields `Ok`. + fn as_result(&self) -> Result<&C, &Self::Error>; +} + +/// todo: comment +pub struct ConstructorOutputValue(T, PhantomData); + +impl ConstructorOutputValue +where + Env: Environment, +{ + pub fn new(val: T) -> Self { + Self(val, PhantomData) + } +} + +impl private::Sealed for ConstructorOutputValue {} + +impl ConstructorOutput for ConstructorOutputValue +where + C: FromAccountId, + Env: Environment, +{ + type Output = C; + type Error = &'static (); + + fn from_account_id(account_id: Env::AccountId) -> Self::Output { + C::from_account_id(account_id) + } + + #[inline(always)] + fn as_result(&self) -> Result<&C, &Self::Error> { + Ok(&self.0) + } +} + +impl ConstructorOutput for ConstructorOutputValue, Env> +where + C: FromAccountId, + Env: Environment, +{ + const IS_RESULT: bool = true; + + type Output = Result; + type Error = E; + + fn from_account_id(account_id: Env::AccountId) -> Self::Output { + Ok(C::from_account_id(account_id)) + } + + #[inline(always)] + fn as_result(&self) -> Result<&C, &Self::Error> { + self.0.as_ref() + } +} + /// A parameter that has been set to some value. #[derive(Debug, Copy, Clone)] pub struct Set(pub T); diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 86589d36b99..fb8715dc40a 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -15,6 +15,8 @@ use crate::{ call::{ utils::{ + ConstructorOutput, + ConstructorOutputValue, EmptyArgumentList, ReturnType, Set, @@ -132,7 +134,6 @@ where panic!("Received a `LangError` while instantiating: {:?}", error) }) }) - .map(FromAccountId::from_account_id) } /// Instantiates the contract and returns its account ID back to the caller. @@ -145,7 +146,6 @@ where &self, ) -> Result, crate::Error> { crate::instantiate_contract(self) - .map(|inner| inner.map(FromAccountId::from_account_id)) } } diff --git a/crates/env/src/call/mod.rs b/crates/env/src/call/mod.rs index ac4ba6cc4bb..b5b24066b5c 100644 --- a/crates/env/src/call/mod.rs +++ b/crates/env/src/call/mod.rs @@ -24,6 +24,8 @@ mod selector; pub mod utils { pub use super::{ common::{ + ConstructorOutput, + ConstructorOutputValue, ReturnType, Set, Unset, diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 33cc97fc98b..e3aa9159f1b 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -18,7 +18,12 @@ use crate::{ Call, CallParams, CreateParams, + FromAccountId, DelegateCall, + utils::{ + ConstructorOutput, + ConstructorOutputValue, + } }, hash::{ Blake2x128, @@ -472,11 +477,12 @@ impl TypedEnvBackend for EnvInstance { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result> + ) -> Result>> where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, + R: FromAccountId, { let _code_hash = params.code_hash(); let _gas_limit = params.gas_limit(); diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 2ea3b65d434..1a7cc8a5c61 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -24,6 +24,10 @@ use crate::{ CallParams, CreateParams, DelegateCall, + utils::{ + ConstructorOutput, + ConstructorOutputValue, + } }, hash::{ Blake2x128, @@ -41,6 +45,7 @@ use crate::{ EnvBackend, Environment, Error, + FromAccountId, FromLittleEndian, Result, ReturnFlags, @@ -482,11 +487,12 @@ impl TypedEnvBackend for EnvInstance { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result> + ) -> Result>> where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, + R: FromAccountId, { let mut scoped = self.scoped_buffer(); let gas_limit = params.gas_limit(); @@ -513,17 +519,18 @@ impl TypedEnvBackend for EnvInstance { match instantiate_result { Ok(()) => { let account_id = scale::Decode::decode(&mut &out_address[..])?; - Ok(Ok(account_id)) + Ok(Ok(>::from_account_id(account_id))) } Err(ext::Error::CalleeReverted) => { // We don't wrap manually with an extra `Err` like we do in the `Ok` case since the // buffer already comes back in the form of `Err(LangError)` (assuming it's encoded // by the ink! codegen and not the contract). - let out = ink_primitives::ConstructorResult::::decode( - &mut &out_return_value[..], - )?; - assert!(out.is_err(), "The callee reverted, but did not encode an error in the output buffer."); - Ok(out) + // let out = ink_primitives::ConstructorResult::::decode( + // &mut &out_return_value[..], + // )?; + // assert!(out.is_err(), "The callee reverted, but did not encode an error in the output buffer."); + // Ok(out) + todo!("custom decoding based on ConstructorOutputValue") } Err(actual_error) => Err(actual_error.into()), } 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 756dae0ed71..229970cb8e3 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -420,7 +420,8 @@ impl ContractRef<'_> { ::ink::env::call::utils::Unset, ::ink::env::call::utils::Set<::ink::env::call::ExecutionInput<#arg_list>>, ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, - ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, + ::ink::env::call::utils::Set<::ink::env::call::utils::ConstructorOutputValue<#ret_type>>, + Self, > { ::ink::env::call::build_create::() .exec_input( @@ -431,7 +432,6 @@ impl ContractRef<'_> { .push_arg(#input_bindings) )* ) - .returns::<#ret_type>() } ) } From 2bd176b7845fb1a890d81b3ea5e773b5bc67b55d Mon Sep 17 00:00:00 2001 From: andrew Date: Sat, 14 Jan 2023 21:22:43 +0000 Subject: [PATCH 079/206] InstantiateResult blanket impl for T and Result --- crates/env/src/api.rs | 43 +----------- crates/env/src/backend.rs | 30 +------- crates/env/src/call/common.rs | 68 +++++-------------- crates/env/src/call/create_builder.rs | 46 ------------- crates/env/src/call/mod.rs | 3 +- crates/env/src/engine/off_chain/impls.rs | 32 +-------- crates/env/src/engine/on_chain/impls.rs | 16 ++--- crates/env/src/lib.rs | 1 - .../generator/as_dependency/contract_ref.rs | 2 +- 9 files changed, 34 insertions(+), 207 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index eb5d4c0e1d9..b134cce7f8d 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -25,8 +25,6 @@ use crate::{ CallParams, CreateParams, DelegateCall, - FromAccountId, - utils::ConstructorOutputValue, }, engine::{ EnvInstance, @@ -42,6 +40,7 @@ use crate::{ Result, }; use ink_storage_traits::Storable; +use crate::call::utils::InstantiateResult; /// Returns the address of the caller of the executed contract. /// @@ -325,54 +324,18 @@ where /// - If the returned account ID failed to decode properly. pub fn instantiate_contract( params: &CreateParams, -) -> Result>> +) -> Result>::Output>> where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: FromAccountId, + R: InstantiateResult, { ::on_instance(|instance| { TypedEnvBackend::instantiate_contract::(instance, params) }) } -/// Attempts to instantiate another contract, returning the instantiation result back to the -/// caller. -/// -/// # Note -/// -/// This is a low level way to instantiate another smart contract. -/// -/// Prefer to use methods on a `ContractRef` or the [`CreateBuilder`](`crate::call::CreateBuilder`) -/// through [`build_create`](`crate::call::build_create`) instead. -/// -/// # Errors -/// -/// - If the code hash is invalid. -/// - If the arguments passed to the instantiation process are invalid. -/// - If the instantiation process traps. -/// - If the instantiation process runs out of gas. -/// - If given insufficient endowment. -/// - If the returned account ID failed to decode properly. -pub fn instantiate_fallible_contract( - params: &CreateParams, -) -> Result< - ink_primitives::ConstructorResult>, -> -where - E: Environment, - Args: scale::Encode, - Salt: AsRef<[u8]>, - ContractError: scale::Decode, -{ - ::on_instance(|instance| { - TypedEnvBackend::instantiate_fallible_contract::( - instance, params, - ) - }) -} - /// Terminates the existence of the currently executed smart contract. /// /// This removes the calling account and transfers all remaining balance diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index b8c567777db..0e5d9bf6b69 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -17,12 +17,8 @@ use crate::{ Call, CallParams, CreateParams, - FromAccountId, DelegateCall, - utils::{ - ConstructorOutput, - ConstructorOutputValue, - } + utils::InstantiateResult, }, hash::{ CryptoHash, @@ -447,32 +443,12 @@ pub trait TypedEnvBackend: EnvBackend { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result>> - where - E: Environment, - Args: scale::Encode, - Salt: AsRef<[u8]>, - R: FromAccountId,; - - /// Attempts to instantiate another contract, returning the instantiation result back to the - /// caller. - /// - /// # Note - /// - /// For more details visit: [`instantiate_fallible_contract`][`crate::instantiate_fallible_contract`] - fn instantiate_fallible_contract( - &mut self, - params: &CreateParams, - ) -> Result< - ink_primitives::ConstructorResult< - core::result::Result, - >, - > + ) -> Result>::Output>> where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - ContractError: scale::Decode; + R: InstantiateResult; /// Terminates a smart contract. /// diff --git a/crates/env/src/call/common.rs b/crates/env/src/call/common.rs index a2bc4addd00..e562c0e428b 100644 --- a/crates/env/src/call/common.rs +++ b/crates/env/src/call/common.rs @@ -15,8 +15,6 @@ //! Utilities, types and abstractions common to call and instantiation routines. use core::marker::PhantomData; -use crate::call::FromAccountId; -use crate::Environment; /// Represents a return type. /// @@ -54,12 +52,12 @@ mod private { /// If the contract initializer returns `Result::Err` the utility /// method that is used to initialize an ink! smart contract will /// revert the state of the contract instantiation. -pub trait ConstructorOutput: private::Sealed { +pub trait InstantiateResult: private::Sealed { /// Is `true` if `Self` is `Result`. const IS_RESULT: bool = false; /// Reflects the output type of the dispatchable ink! constructor. - type Output; + type Output; /// The error type of the constructor return type. /// @@ -69,68 +67,34 @@ pub trait ConstructorOutput: private::Sealed { /// constructors this is the actual return error type. Since we only ever /// return a value in case of `Result::Err` the `Result::Ok` value type /// does not matter. - type Error; - - // todo: docs - fn from_account_id(account_id: Env::AccountId) -> Self::Output; + type Error: scale::Decode; - /// Converts the return value into a `Result` instance. - /// - /// # Note - /// - /// For infallible constructor returns this always yields `Ok`. - fn as_result(&self) -> Result<&C, &Self::Error>; + /// todo: docs! + fn output(value: O) -> Self::Output; } -/// todo: comment -pub struct ConstructorOutputValue(T, PhantomData); +impl private::Sealed for T {} -impl ConstructorOutputValue -where - Env: Environment, -{ - pub fn new(val: T) -> Self { - Self(val, PhantomData) - } -} +impl InstantiateResult for C { + type Output = O; + type Error = (); -impl private::Sealed for ConstructorOutputValue {} - -impl ConstructorOutput for ConstructorOutputValue -where - C: FromAccountId, - Env: Environment, -{ - type Output = C; - type Error = &'static (); - - fn from_account_id(account_id: Env::AccountId) -> Self::Output { - C::from_account_id(account_id) - } - - #[inline(always)] - fn as_result(&self) -> Result<&C, &Self::Error> { - Ok(&self.0) + fn output(value: O) -> Self::Output { + value } } -impl ConstructorOutput for ConstructorOutputValue, Env> +impl InstantiateResult for Result where - C: FromAccountId, - Env: Environment, + E: scale::Decode, { const IS_RESULT: bool = true; - type Output = Result; + type Output = Result; type Error = E; - fn from_account_id(account_id: Env::AccountId) -> Self::Output { - Ok(C::from_account_id(account_id)) - } - - #[inline(always)] - fn as_result(&self) -> Result<&C, &Self::Error> { - self.0.as_ref() + fn output(value: O) -> Self::Output { + Ok(value) } } diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index fb8715dc40a..b013452c214 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -15,8 +15,6 @@ use crate::{ call::{ utils::{ - ConstructorOutput, - ConstructorOutputValue, EmptyArgumentList, ReturnType, Set, @@ -149,50 +147,6 @@ where } } -impl - CreateParams> -where - E: Environment, - Args: scale::Encode, - Salt: AsRef<[u8]>, - R: FromAccountId, - ContractError: scale::Decode, -{ - /// Attempts to instantiate the contract, returning the execution result back to the caller. - /// - /// # Panics - /// - /// This method panics if it encounters an [`ink_primitives::LangError`]. If you want to handle - /// those use the [`try_instantiate_fallible`][`CreateParams::try_instantiate_fallible`] method instead. - #[inline] - pub fn instantiate_fallible(&self) -> Result, crate::Error> { - crate::instantiate_fallible_contract(self).map(|constructor_result| { - constructor_result - .unwrap_or_else(|error| { - panic!("Received a `LangError` while instantiating: {:?}", error) - }) - .map(FromAccountId::from_account_id) - }) - } - - /// Attempts to instantiate the contract, returning the execution result back to the caller. - /// - /// # Note - /// - /// On failure this returns an [`ink_primitives::LangError`] which can be handled by the caller. - #[inline] - pub fn try_instantiate_fallible( - &self, - ) -> Result>, crate::Error> - { - crate::instantiate_fallible_contract(self).map(|constructor_result| { - constructor_result.map(|contract_result| { - contract_result.map(FromAccountId::from_account_id) - }) - }) - } -} - /// Builds up contract instantiations. pub struct CreateBuilder where diff --git a/crates/env/src/call/mod.rs b/crates/env/src/call/mod.rs index b5b24066b5c..971d0cc4d15 100644 --- a/crates/env/src/call/mod.rs +++ b/crates/env/src/call/mod.rs @@ -24,8 +24,7 @@ mod selector; pub mod utils { pub use super::{ common::{ - ConstructorOutput, - ConstructorOutputValue, + InstantiateResult, ReturnType, Set, Unset, diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index e3aa9159f1b..5e997a76eb7 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -18,12 +18,8 @@ use crate::{ Call, CallParams, CreateParams, - FromAccountId, DelegateCall, - utils::{ - ConstructorOutput, - ConstructorOutputValue, - } + utils::InstantiateResult, }, hash::{ Blake2x128, @@ -477,34 +473,12 @@ impl TypedEnvBackend for EnvInstance { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result>> - where - E: Environment, - Args: scale::Encode, - Salt: AsRef<[u8]>, - R: FromAccountId, - { - let _code_hash = params.code_hash(); - let _gas_limit = params.gas_limit(); - let _endowment = params.endowment(); - let _input = params.exec_input(); - let _salt_bytes = params.salt_bytes(); - unimplemented!("off-chain environment does not support contract instantiation") - } - - fn instantiate_fallible_contract( - &mut self, - params: &CreateParams, - ) -> Result< - ink_primitives::ConstructorResult< - core::result::Result, - >, - > + ) -> Result>::Output>> where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - ContractError: scale::Decode, + R: InstantiateResult, { let _code_hash = params.code_hash(); let _gas_limit = params.gas_limit(); diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 1a7cc8a5c61..f02776fea92 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -24,10 +24,7 @@ use crate::{ CallParams, CreateParams, DelegateCall, - utils::{ - ConstructorOutput, - ConstructorOutputValue, - } + utils::InstantiateResult, }, hash::{ Blake2x128, @@ -484,15 +481,15 @@ impl TypedEnvBackend for EnvInstance { } } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, - ) -> Result>> + params: &CreateParams, + ) -> Result> where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: FromAccountId, + RetType: { let mut scoped = self.scoped_buffer(); let gas_limit = params.gas_limit(); @@ -548,7 +545,6 @@ impl TypedEnvBackend for EnvInstance { E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - ContractError: scale::Decode, { let mut scoped = self.scoped_buffer(); let gas_limit = params.gas_limit(); @@ -572,6 +568,8 @@ impl TypedEnvBackend for EnvInstance { salt, ); + // todo: < + match instantiate_result { Ok(()) => { let account_id: E::AccountId = diff --git a/crates/env/src/lib.rs b/crates/env/src/lib.rs index f04a61306f9..e9d9be7dcf1 100644 --- a/crates/env/src/lib.rs +++ b/crates/env/src/lib.rs @@ -29,7 +29,6 @@ missing_docs, bad_style, bare_trait_objects, - const_err, improper_ctypes, non_shorthand_field_patterns, no_mangle_generic_items, 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 229970cb8e3..1b620d1e8b4 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -420,7 +420,7 @@ impl ContractRef<'_> { ::ink::env::call::utils::Unset, ::ink::env::call::utils::Set<::ink::env::call::ExecutionInput<#arg_list>>, ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, - ::ink::env::call::utils::Set<::ink::env::call::utils::ConstructorOutputValue<#ret_type>>, + ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, Self, > { ::ink::env::call::build_create::() From fa47e250ac741464322582c8a747903a1bb1685c Mon Sep 17 00:00:00 2001 From: andrew Date: Sat, 14 Jan 2023 21:52:16 +0000 Subject: [PATCH 080/206] Introduce ContractRef type parameter --- crates/env/src/api.rs | 16 +- crates/env/src/backend.rs | 16 +- crates/env/src/call/create_builder.rs | 186 ++++++++++++++++++----- crates/env/src/engine/off_chain/impls.rs | 14 +- crates/env/src/engine/on_chain/impls.rs | 4 +- 5 files changed, 179 insertions(+), 57 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index b134cce7f8d..7e8a4f5a5e8 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -21,10 +21,12 @@ use crate::{ TypedEnvBackend, }, call::{ + utils::InstantiateResult, Call, CallParams, CreateParams, DelegateCall, + FromAccountId, }, engine::{ EnvInstance, @@ -40,7 +42,6 @@ use crate::{ Result, }; use ink_storage_traits::Storable; -use crate::call::utils::InstantiateResult; /// Returns the address of the caller of the executed contract. /// @@ -322,17 +323,22 @@ where /// - If the instantiation process runs out of gas. /// - If given insufficient endowment. /// - If the returned account ID failed to decode properly. -pub fn instantiate_contract( - params: &CreateParams, -) -> Result>::Output>> +pub fn instantiate_contract( + params: &CreateParams, +) -> Result< + ink_primitives::ConstructorResult<>::Output>, +> where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, R: InstantiateResult, + ContractRef: FromAccountId, { ::on_instance(|instance| { - TypedEnvBackend::instantiate_contract::(instance, params) + TypedEnvBackend::instantiate_contract::( + instance, params, + ) }) } diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 0e5d9bf6b69..8b70bd1c0ac 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -14,11 +14,12 @@ use crate::{ call::{ + utils::InstantiateResult, Call, CallParams, CreateParams, DelegateCall, - utils::InstantiateResult, + FromAccountId, }, hash::{ CryptoHash, @@ -440,15 +441,20 @@ pub trait TypedEnvBackend: EnvBackend { /// # Note /// /// For more details visit: [`instantiate_contract`][`crate::instantiate_contract`] - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, - ) -> Result>::Output>> + params: &CreateParams, + ) -> Result< + ink_primitives::ConstructorResult< + >::Output, + >, + > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult; + R: InstantiateResult, + ContractRef: FromAccountId; /// Terminates a smart contract. /// diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index b013452c214..3df17ecc27b 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -16,6 +16,7 @@ use crate::{ call::{ utils::{ EmptyArgumentList, + InstantiateResult, ReturnType, Set, Unset, @@ -52,7 +53,7 @@ where /// Builds up contract instantiations. #[derive(Debug)] -pub struct CreateParams +pub struct CreateParams where E: Environment, { @@ -66,11 +67,13 @@ where exec_input: ExecutionInput, /// The salt for determining the hash for the contract account ID. salt_bytes: Salt, - /// The type of the instantiated contract. + /// The return type of the target contracts constructor method. _return_type: ReturnType, + /// Phantom for ContractRef: todo! + _contract_ref: PhantomData, } -impl CreateParams +impl CreateParams where E: Environment, { @@ -99,7 +102,7 @@ where } } -impl CreateParams +impl CreateParams where E: Environment, Salt: AsRef<[u8]>, @@ -111,12 +114,13 @@ where } } -impl CreateParams +impl CreateParams where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: FromAccountId, + R: InstantiateResult, + ContractRef: FromAccountId, { /// Instantiates the contract and returns its account ID back to the caller. /// @@ -125,13 +129,14 @@ where /// This method panics if it encounters an [`ink_primitives::LangError`]. If you want to handle /// those use the [`try_instantiate`][`CreateParams::try_instantiate`] method instead. #[inline] - pub fn instantiate(&self) -> Result { - crate::instantiate_contract(self) - .map(|inner| { - inner.unwrap_or_else(|error| { - panic!("Received a `LangError` while instantiating: {:?}", error) - }) + pub fn instantiate( + &self, + ) -> Result<>::Output, crate::Error> { + crate::instantiate_contract(self).map(|inner| { + inner.unwrap_or_else(|error| { + panic!("Received a `LangError` while instantiating: {:?}", error) }) + }) } /// Instantiates the contract and returns its account ID back to the caller. @@ -142,14 +147,27 @@ where #[inline] pub fn try_instantiate( &self, - ) -> Result, crate::Error> { + ) -> Result< + ink_primitives::ConstructorResult< + >::Output, + >, + crate::Error, + > { crate::instantiate_contract(self) } } /// Builds up contract instantiations. -pub struct CreateBuilder -where +pub struct CreateBuilder< + E, + CodeHash, + GasLimit, + Endowment, + Args, + Salt, + RetType, + ContractRef, +> where E: Environment, { code_hash: CodeHash, @@ -158,7 +176,7 @@ where exec_input: Args, salt: Salt, return_type: RetType, - _phantom: PhantomData E>, + _phantom: PhantomData (E, ContractRef)>, } /// Returns a new [`CreateBuilder`] to build up the parameters to a cross-contract instantiation. @@ -251,7 +269,7 @@ where /// /// Note the usage of the [`CreateBuilder::instantiate_fallible`] method. #[allow(clippy::type_complexity)] -pub fn build_create() -> CreateBuilder< +pub fn build_create() -> CreateBuilder< E, Unset, Unset, @@ -259,6 +277,7 @@ pub fn build_create() -> CreateBuilder< Unset>, Unset, Unset>, + ContractRef, > where E: Environment, @@ -274,8 +293,17 @@ where } } -impl - CreateBuilder, GasLimit, Endowment, Args, Salt, RetType> +impl + CreateBuilder< + E, + Unset, + GasLimit, + Endowment, + Args, + Salt, + RetType, + ContractRef, + > where E: Environment, { @@ -284,7 +312,16 @@ where pub fn code_hash( self, code_hash: E::Hash, - ) -> CreateBuilder, GasLimit, Endowment, Args, Salt, RetType> { + ) -> CreateBuilder< + E, + Set, + GasLimit, + Endowment, + Args, + Salt, + RetType, + ContractRef, + > { CreateBuilder { code_hash: Set(code_hash), gas_limit: self.gas_limit, @@ -297,8 +334,8 @@ where } } -impl - CreateBuilder, Endowment, Args, Salt, RetType> +impl + CreateBuilder, Endowment, Args, Salt, RetType, ContractRef> where E: Environment, { @@ -307,7 +344,8 @@ where pub fn gas_limit( self, gas_limit: u64, - ) -> CreateBuilder, Endowment, Args, Salt, RetType> { + ) -> CreateBuilder, Endowment, Args, Salt, RetType, ContractRef> + { CreateBuilder { code_hash: self.code_hash, gas_limit: Set(gas_limit), @@ -320,8 +358,17 @@ where } } -impl - CreateBuilder, Args, Salt, RetType> +impl + CreateBuilder< + E, + CodeHash, + GasLimit, + Unset, + Args, + Salt, + RetType, + ContractRef, + > where E: Environment, { @@ -330,7 +377,16 @@ where pub fn endowment( self, endowment: E::Balance, - ) -> CreateBuilder, Args, Salt, RetType> { + ) -> CreateBuilder< + E, + CodeHash, + GasLimit, + Set, + Args, + Salt, + RetType, + ContractRef, + > { CreateBuilder { code_hash: self.code_hash, gas_limit: self.gas_limit, @@ -343,7 +399,7 @@ where } } -impl +impl CreateBuilder< E, CodeHash, @@ -352,6 +408,7 @@ impl Unset>, Salt, RetType, + ContractRef, > where E: Environment, @@ -369,6 +426,7 @@ where Set>, Salt, RetType, + ContractRef, > { CreateBuilder { code_hash: self.code_hash, @@ -382,8 +440,17 @@ where } } -impl - CreateBuilder, RetType> +impl + CreateBuilder< + E, + CodeHash, + GasLimit, + Endowment, + Args, + Unset, + RetType, + ContractRef, + > where E: Environment, { @@ -392,7 +459,16 @@ where pub fn salt_bytes( self, salt: Salt, - ) -> CreateBuilder, RetType> + ) -> CreateBuilder< + E, + CodeHash, + GasLimit, + Endowment, + Args, + Set, + RetType, + ContractRef, + > where Salt: AsRef<[u8]>, { @@ -408,8 +484,17 @@ where } } -impl - CreateBuilder>> +impl + CreateBuilder< + E, + CodeHash, + GasLimit, + Endowment, + Args, + Salt, + Unset>, + ContractRef, + > where E: Environment, { @@ -425,8 +510,16 @@ where #[inline] pub fn returns( self, - ) -> CreateBuilder>> - { + ) -> CreateBuilder< + E, + CodeHash, + GasLimit, + Endowment, + Args, + Salt, + Set>, + ContractRef, + > { CreateBuilder { code_hash: self.code_hash, gas_limit: self.gas_limit, @@ -439,7 +532,7 @@ where } } -impl +impl CreateBuilder< E, Set, @@ -448,6 +541,7 @@ impl Set>, Set, Set>, + ContractRef, > where E: Environment, @@ -455,7 +549,7 @@ where { /// Finalizes the create builder, allowing it to instantiate a contract. #[inline] - pub fn params(self) -> CreateParams { + pub fn params(self) -> CreateParams { CreateParams { code_hash: self.code_hash.value(), gas_limit: self.gas_limit.unwrap_or_else(|| 0), @@ -463,11 +557,12 @@ where exec_input: self.exec_input.value(), salt_bytes: self.salt.value(), _return_type: Default::default(), + _contract_ref: Default::default(), } } } -impl +impl CreateBuilder< E, Set, @@ -476,13 +571,15 @@ impl Set>, Set, Set>, + ContractRef, > where E: Environment, GasLimit: Unwrap, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType: FromAccountId, + RetType: InstantiateResult, + ContractRef: FromAccountId, { /// Instantiates the contract using the given instantiation parameters. /// @@ -491,7 +588,9 @@ where /// This method panics if it encounters an [`ink_primitives::LangError`]. If you want to handle /// those use the [`try_instantiate`][`CreateBuilder::try_instantiate`] method instead. #[inline] - pub fn instantiate(self) -> Result { + pub fn instantiate( + self, + ) -> Result<>::Output, Error> { self.params().instantiate() } @@ -503,7 +602,12 @@ where #[inline] pub fn try_instantiate( self, - ) -> Result, Error> { + ) -> Result< + ink_primitives::ConstructorResult< + >::Output, + >, + Error, + > { self.params().try_instantiate() } -} \ No newline at end of file +} diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 5e997a76eb7..d37d300e003 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -15,11 +15,12 @@ use super::EnvInstance; use crate::{ call::{ + utils::InstantiateResult, Call, CallParams, CreateParams, DelegateCall, - utils::InstantiateResult, + FromAccountId, }, hash::{ Blake2x128, @@ -470,15 +471,20 @@ impl TypedEnvBackend for EnvInstance { ) } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, - ) -> Result>::Output>> + params: &CreateParams, + ) -> Result< + ink_primitives::ConstructorResult< + >::Output, + >, + > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, R: InstantiateResult, + ContractRef: FromAccountId, { let _code_hash = params.code_hash(); let _gas_limit = params.gas_limit(); diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index f02776fea92..856a5169338 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -20,11 +20,11 @@ use super::{ }; use crate::{ call::{ + utils::InstantiateResult, Call, CallParams, CreateParams, DelegateCall, - utils::InstantiateResult, }, hash::{ Blake2x128, @@ -489,7 +489,7 @@ impl TypedEnvBackend for EnvInstance { E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType: + RetType:, { let mut scoped = self.scoped_buffer(); let gas_limit = params.gas_limit(); From 9ac5f02c47bf7f95bed51e949fb7cb8f8c1f48e0 Mon Sep 17 00:00:00 2001 From: andrew Date: Sat, 14 Jan 2023 21:59:23 +0000 Subject: [PATCH 081/206] Fix up env access --- crates/env/src/engine/on_chain/impls.rs | 9 +- crates/ink/src/env_access.rs | 105 ++---------------------- crates/storage/src/lib.rs | 1 - 3 files changed, 13 insertions(+), 102 deletions(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 856a5169338..832cbaaf4a0 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -481,15 +481,16 @@ impl TypedEnvBackend for EnvInstance { } } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, - ) -> Result> + params: &CreateParams, + ) -> Result>::Output>> where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType:, + RetType: InstantiateResult, + ContractRef: FromAccountId, { let mut scoped = self.scoped_buffer(); let gas_limit = params.gas_limit(); diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 690e19d17f2..4a78a52faf1 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -20,6 +20,8 @@ use ink_env::{ CallParams, CreateParams, DelegateCall, + FromAccountId, + utils::InstantiateResult, }, hash::{ CryptoHash, @@ -478,108 +480,17 @@ where /// # Note /// /// For more details visit: [`ink_env::instantiate_contract`] - pub fn instantiate_contract( + pub fn instantiate_contract( self, - params: &CreateParams, - ) -> Result> + params: &CreateParams, + ) -> Result>::Output>> where Args: scale::Encode, Salt: AsRef<[u8]>, + R: InstantiateResult, + ContractRef: FromAccountId, { - ink_env::instantiate_contract::(params) - } - - /// Attempts to instantiate a contract, returning the execution result back to the caller. - /// - /// # Example - /// - /// ``` - /// # #[ink::contract] - /// # pub mod my_contract { - /// # // In order for this to actually work with another contract we'd need a way - /// # // to turn the `ink-as-dependency` crate feature on in doctests, which we - /// # // can't do. - /// # // - /// # // Instead we use our own contract's `Ref`, which is fine for this example - /// # // (just need something that implements the `ContractRef` trait). - /// # pub mod other_contract { - /// # pub use super::MyContractRef as OtherContractRef; - /// # pub use super::ConstructorError as OtherConstructorError; - /// # } - /// use ink::env::{ - /// DefaultEnvironment, - /// call::{build_create, Selector, ExecutionInput} - /// }; - /// use other_contract::{OtherContractRef, OtherConstructorError}; - /// - /// # #[derive(scale::Encode, scale::Decode, Debug)] - /// # #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] - /// # pub struct ConstructorError; - /// # - /// # #[ink(storage)] - /// # pub struct MyContract { } - /// # - /// # impl MyContract { - /// # #[ink(constructor)] - /// # pub fn try_new() -> Result { - /// # Ok(Self {}) - /// # } - /// # - /// /// Attempts to instantiate a contract, returning the `AccountId` back to the caller. - /// #[ink(message)] - /// pub fn instantiate_fallible_contract(&self) -> AccountId { - /// let create_params = build_create::() - /// .code_hash(Hash::from([0x42; 32])) - /// .gas_limit(4000) - /// .endowment(25) - /// .exec_input( - /// ExecutionInput::new(Selector::new(ink::selector_bytes!("try_new"))) - /// .push_arg(42) - /// .push_arg(true) - /// .push_arg(&[0x10u8; 32]), - /// ) - /// .salt_bytes(&[0xCA, 0xFE, 0xBA, 0xBE]) - /// .returns::>() - /// .params(); - /// self.env() - /// .instantiate_fallible_contract(&create_params) - /// .unwrap_or_else(|error| { - /// panic!( - /// "Received an error from the Contracts pallet while instantiating: {:?}", - /// error - /// ) - /// }) - /// .unwrap_or_else(|error| panic!("Received a `LangError` while instatiating: {:?}", error)) - /// .unwrap_or_else(|error: ConstructorError| { - /// panic!( - /// "Received a `ConstructorError` while instatiating: {:?}", - /// error - /// ) - /// }) - /// } - /// # - /// # } - /// # } - /// ``` - /// - /// # Note - /// - /// For more details visit: [`ink_env::instantiate_fallible_contract`] - pub fn instantiate_fallible_contract( - self, - params: &CreateParams, - ) -> Result< - ink_primitives::ConstructorResult< - core::result::Result, - >, - > - where - E: Environment, - Args: scale::Encode, - Salt: AsRef<[u8]>, - ContractError: scale::Decode, - { - ink_env::instantiate_fallible_contract::(params) + ink_env::instantiate_contract::(params) } /// Invokes a contract message and returns its result. diff --git a/crates/storage/src/lib.rs b/crates/storage/src/lib.rs index d9971535a3a..38a417cca5b 100644 --- a/crates/storage/src/lib.rs +++ b/crates/storage/src/lib.rs @@ -29,7 +29,6 @@ missing_docs, bad_style, bare_trait_objects, - const_err, improper_ctypes, non_shorthand_field_patterns, no_mangle_generic_items, From 361a0b6ed804e785616544699402a294f05b6e28 Mon Sep 17 00:00:00 2001 From: andrew Date: Sat, 14 Jan 2023 22:07:43 +0000 Subject: [PATCH 082/206] WIP... --- crates/env/src/engine/on_chain/impls.rs | 121 +++++++++--------- .../generator/as_dependency/contract_ref.rs | 2 +- 2 files changed, 59 insertions(+), 64 deletions(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 832cbaaf4a0..005ff11634e 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -517,76 +517,71 @@ impl TypedEnvBackend for EnvInstance { match instantiate_result { Ok(()) => { let account_id = scale::Decode::decode(&mut &out_address[..])?; - Ok(Ok(>::from_account_id(account_id))) + let contract_ref = >::from_account_id(account_id); + let output = >::output(contract_ref); + Ok(ink_primitives::ConstructorResult::Ok(output)) } Err(ext::Error::CalleeReverted) => { - // We don't wrap manually with an extra `Err` like we do in the `Ok` case since the - // buffer already comes back in the form of `Err(LangError)` (assuming it's encoded - // by the ink! codegen and not the contract). - // let out = ink_primitives::ConstructorResult::::decode( - // &mut &out_return_value[..], - // )?; - // assert!(out.is_err(), "The callee reverted, but did not encode an error in the output buffer."); - // Ok(out) - todo!("custom decoding based on ConstructorOutputValue") + todo!("custom decoding based on InstantiateResult") + // if InstantiateResult::IS_RESULT, attempt to decode Result manually by first byte } Err(actual_error) => Err(actual_error.into()), } } - fn instantiate_fallible_contract( - &mut self, - params: &CreateParams, - ) -> Result< - ink_primitives::ConstructorResult< - core::result::Result, - >, - > - where - E: Environment, - Args: scale::Encode, - Salt: AsRef<[u8]>, - { - let mut scoped = self.scoped_buffer(); - let gas_limit = params.gas_limit(); - let enc_code_hash = scoped.take_encoded(params.code_hash()); - let enc_endowment = scoped.take_encoded(params.endowment()); - let enc_input = scoped.take_encoded(params.exec_input()); - // We support `AccountId` types with an encoding that requires up to - // 1024 bytes. Beyond that limit ink! contracts will trap for now. - // In the default configuration encoded `AccountId` require 32 bytes. - let out_address = &mut scoped.take(1024); - let salt = params.salt_bytes().as_ref(); - let out_return_value = &mut scoped.take_rest(); - - let instantiate_result = ext::instantiate( - enc_code_hash, - gas_limit, - enc_endowment, - enc_input, - out_address, - out_return_value, - salt, - ); - - // todo: < - - match instantiate_result { - Ok(()) => { - let account_id: E::AccountId = - scale::Decode::decode(&mut &out_address[..])?; - Ok(ink_primitives::ConstructorResult::Ok(Ok(account_id))) - } - Err(ext::Error::CalleeReverted) => { - crate::engine::decode_fallible_constructor_reverted_return_value::< - _, - E, - ContractError, - >(&mut &out_return_value[..]) - } - Err(actual_error) => Err(actual_error.into()), - } - } + // fn instantiate_fallible_contract( + // &mut self, + // params: &CreateParams, + // ) -> Result< + // ink_primitives::ConstructorResult< + // core::result::Result, + // >, + // > + // where + // E: Environment, + // Args: scale::Encode, + // Salt: AsRef<[u8]>, + // { + // let mut scoped = self.scoped_buffer(); + // let gas_limit = params.gas_limit(); + // let enc_code_hash = scoped.take_encoded(params.code_hash()); + // let enc_endowment = scoped.take_encoded(params.endowment()); + // let enc_input = scoped.take_encoded(params.exec_input()); + // // We support `AccountId` types with an encoding that requires up to + // // 1024 bytes. Beyond that limit ink! contracts will trap for now. + // // In the default configuration encoded `AccountId` require 32 bytes. + // let out_address = &mut scoped.take(1024); + // let salt = params.salt_bytes().as_ref(); + // let out_return_value = &mut scoped.take_rest(); + // + // let instantiate_result = ext::instantiate( + // enc_code_hash, + // gas_limit, + // enc_endowment, + // enc_input, + // out_address, + // out_return_value, + // salt, + // ); + // + // // todo: < + // + // match instantiate_result { + // Ok(()) => { + // let account_id: E::AccountId = + // scale::Decode::decode(&mut &out_address[..])?; + // Ok(ink_primitives::ConstructorResult::Ok(Ok(account_id))) + // } + // Err(ext::Error::CalleeReverted) => { + // crate::engine::decode_fallible_constructor_reverted_return_value::< + // _, + // E, + // ContractError, + // >(&mut &out_return_value[..]) + // } + // Err(actual_error) => Err(actual_error.into()), + // } + // } fn terminate_contract(&mut self, beneficiary: E::AccountId) -> ! where 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 1b620d1e8b4..11369845a2c 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -423,7 +423,7 @@ impl ContractRef<'_> { ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, Self, > { - ::ink::env::call::build_create::() + ::ink::env::call::build_create::() .exec_input( ::ink::env::call::ExecutionInput::new( ::ink::env::call::Selector::new([ #( #selector_bytes ),* ]) From d1d11a73f86b8b300632462023d80425e7f03d32 Mon Sep 17 00:00:00 2001 From: andrew Date: Sun, 15 Jan 2023 14:08:54 +0000 Subject: [PATCH 083/206] Make it compile --- crates/e2e/src/builders.rs | 3 ++- crates/env/src/call/create_builder.rs | 6 +++--- .../ink/codegen/src/generator/as_dependency/contract_ref.rs | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/e2e/src/builders.rs b/crates/e2e/src/builders.rs index 7c2a6b44607..6851b0768e8 100644 --- a/crates/e2e/src/builders.rs +++ b/crates/e2e/src/builders.rs @@ -39,7 +39,8 @@ pub type CreateBuilderPartial = CreateBuilder< Unset<::Balance>, Set>, Unset, - Set>, + Set>, + R, >; /// Get the encoded constructor arguments from the partially initialized `CreateBuilder` diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 3df17ecc27b..8315fdaf55c 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -269,14 +269,14 @@ pub struct CreateBuilder< /// /// Note the usage of the [`CreateBuilder::instantiate_fallible`] method. #[allow(clippy::type_complexity)] -pub fn build_create() -> CreateBuilder< +pub fn build_create() -> CreateBuilder< E, Unset, Unset, Unset, Unset>, Unset, - Unset>, + Set>, ContractRef, > where @@ -288,7 +288,7 @@ where endowment: Default::default(), exec_input: Default::default(), salt: Default::default(), - return_type: Default::default(), + return_type: Set(Default::default()), _phantom: Default::default(), } } 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 11369845a2c..ab318ad6eb3 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -423,7 +423,7 @@ impl ContractRef<'_> { ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, Self, > { - ::ink::env::call::build_create::() + ::ink::env::call::build_create::() .exec_input( ::ink::env::call::ExecutionInput::new( ::ink::env::call::Selector::new([ #( #selector_bytes ),* ]) From f7b85716a69d93d4c72fe72839580bd6acf82d4f Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 16 Jan 2023 00:15:25 +0000 Subject: [PATCH 084/206] Add ContractStorage parameter --- crates/e2e/src/builders.rs | 1 + crates/env/src/api.rs | 21 ++- crates/env/src/backend.rs | 8 +- crates/env/src/call/common.rs | 40 ++++-- crates/env/src/call/create_builder.rs | 92 ++++++++---- crates/env/src/engine/mod.rs | 133 +++++++++++++----- crates/env/src/engine/off_chain/impls.rs | 8 +- crates/env/src/engine/on_chain/impls.rs | 26 ++-- .../generator/as_dependency/contract_ref.rs | 4 +- crates/ink/src/env_access.rs | 18 ++- 10 files changed, 244 insertions(+), 107 deletions(-) diff --git a/crates/e2e/src/builders.rs b/crates/e2e/src/builders.rs index 6851b0768e8..b08eaf8649f 100644 --- a/crates/e2e/src/builders.rs +++ b/crates/e2e/src/builders.rs @@ -40,6 +40,7 @@ pub type CreateBuilderPartial = CreateBuilder< Set>, Unset, Set>, + R, // todo ContractStorage param? R, >; diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 7e8a4f5a5e8..e77a18066ac 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -323,22 +323,29 @@ where /// - If the instantiation process runs out of gas. /// - If given insufficient endowment. /// - If the returned account ID failed to decode properly. -pub fn instantiate_contract( - params: &CreateParams, +pub fn instantiate_contract( + params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult< + >::Output, + >, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId, { ::on_instance(|instance| { - TypedEnvBackend::instantiate_contract::( - instance, params, - ) + TypedEnvBackend::instantiate_contract::< + E, + Args, + Salt, + R, + ContractStorage, + ContractRef, + >(instance, params) }) } diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 8b70bd1c0ac..801bf6c078c 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -441,19 +441,19 @@ pub trait TypedEnvBackend: EnvBackend { /// # Note /// /// For more details visit: [`instantiate_contract`][`crate::instantiate_contract`] - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId; /// Terminates a smart contract. diff --git a/crates/env/src/call/common.rs b/crates/env/src/call/common.rs index e562c0e428b..9b9ab2d2f02 100644 --- a/crates/env/src/call/common.rs +++ b/crates/env/src/call/common.rs @@ -60,17 +60,13 @@ pub trait InstantiateResult: private::Sealed { type Output; /// The error type of the constructor return type. - /// - /// # Note - /// - /// For infallible constructors this is `()` whereas for fallible - /// constructors this is the actual return error type. Since we only ever - /// return a value in case of `Result::Err` the `Result::Ok` value type - /// does not matter. type Error: scale::Decode; - /// todo: docs! - fn output(value: O) -> Self::Output; + /// Construct a success value of the `Output` type. + fn ok(value: O) -> Self::Output; + + /// Construct an error value of the `Output` type. + fn err(err: Self::Error) -> Self::Output; } impl private::Sealed for T {} @@ -79,9 +75,14 @@ impl InstantiateResult for C { type Output = O; type Error = (); - fn output(value: O) -> Self::Output { + fn ok(value: O) -> Self::Output { value } + + fn err(_err: Self::Error) -> Self::Output { + // todo! + unreachable!() + } } impl InstantiateResult for Result @@ -93,9 +94,13 @@ where type Output = Result; type Error = E; - fn output(value: O) -> Self::Output { + fn ok(value: O) -> Self::Output { Ok(value) } + + fn err(err: Self::Error) -> Self::Output { + Err(err) + } } /// A parameter that has been set to some value. @@ -167,3 +172,16 @@ impl Unwrap for Set { self.value() } } + +// #[cfg(test)] +// mod tests { +// use super::*; +// +// #[test] +// fn instantiate_result_types() { +// static_assertions::assert_type_eq_all!( +// Result<(), u8>, +// as InstantiateResult<()>> +// ); +// } +// } diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 8315fdaf55c..51c62a483b1 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -53,7 +53,7 @@ where /// Builds up contract instantiations. #[derive(Debug)] -pub struct CreateParams +pub struct CreateParams where E: Environment, { @@ -68,12 +68,13 @@ where /// The salt for determining the hash for the contract account ID. salt_bytes: Salt, /// The return type of the target contracts constructor method. - _return_type: ReturnType, + _return_type: ReturnType<(R, ContractStorage)>, /// Phantom for ContractRef: todo! _contract_ref: PhantomData, } -impl CreateParams +impl + CreateParams where E: Environment, { @@ -102,7 +103,8 @@ where } } -impl CreateParams +impl + CreateParams where E: Environment, Salt: AsRef<[u8]>, @@ -114,12 +116,13 @@ where } } -impl CreateParams +impl + CreateParams where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId, { /// Instantiates the contract and returns its account ID back to the caller. @@ -131,7 +134,10 @@ where #[inline] pub fn instantiate( &self, - ) -> Result<>::Output, crate::Error> { + ) -> Result< + >::Output, + crate::Error, + > { crate::instantiate_contract(self).map(|inner| { inner.unwrap_or_else(|error| { panic!("Received a `LangError` while instantiating: {:?}", error) @@ -149,7 +155,7 @@ where &self, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, crate::Error, > { @@ -166,6 +172,7 @@ pub struct CreateBuilder< Args, Salt, RetType, + ContractStorage, ContractRef, > where E: Environment, @@ -176,7 +183,7 @@ pub struct CreateBuilder< exec_input: Args, salt: Salt, return_type: RetType, - _phantom: PhantomData (E, ContractRef)>, + _phantom: PhantomData (E, ContractStorage, ContractRef)>, } /// Returns a new [`CreateBuilder`] to build up the parameters to a cross-contract instantiation. @@ -269,7 +276,7 @@ pub struct CreateBuilder< /// /// Note the usage of the [`CreateBuilder::instantiate_fallible`] method. #[allow(clippy::type_complexity)] -pub fn build_create() -> CreateBuilder< +pub fn build_create() -> CreateBuilder< E, Unset, Unset, @@ -277,6 +284,7 @@ pub fn build_create() -> CreateBuilder< Unset>, Unset, Set>, + ContractStorage, ContractRef, > where @@ -293,7 +301,7 @@ where } } -impl +impl CreateBuilder< E, Unset, @@ -302,6 +310,7 @@ impl Args, Salt, RetType, + ContractStorage, ContractRef, > where @@ -320,6 +329,7 @@ where Args, Salt, RetType, + ContractStorage, ContractRef, > { CreateBuilder { @@ -334,8 +344,18 @@ where } } -impl - CreateBuilder, Endowment, Args, Salt, RetType, ContractRef> +impl + CreateBuilder< + E, + CodeHash, + Unset, + Endowment, + Args, + Salt, + RetType, + ContractStorage, + ContractRef, + > where E: Environment, { @@ -344,8 +364,17 @@ where pub fn gas_limit( self, gas_limit: u64, - ) -> CreateBuilder, Endowment, Args, Salt, RetType, ContractRef> - { + ) -> CreateBuilder< + E, + CodeHash, + Set, + Endowment, + Args, + Salt, + RetType, + ContractStorage, + ContractRef, + > { CreateBuilder { code_hash: self.code_hash, gas_limit: Set(gas_limit), @@ -358,7 +387,7 @@ where } } -impl +impl CreateBuilder< E, CodeHash, @@ -367,6 +396,7 @@ impl Args, Salt, RetType, + ContractStorage, ContractRef, > where @@ -385,6 +415,7 @@ where Args, Salt, RetType, + ContractStorage, ContractRef, > { CreateBuilder { @@ -399,7 +430,7 @@ where } } -impl +impl CreateBuilder< E, CodeHash, @@ -408,6 +439,7 @@ impl Unset>, Salt, RetType, + ContractStorage, ContractRef, > where @@ -426,6 +458,7 @@ where Set>, Salt, RetType, + ContractStorage, ContractRef, > { CreateBuilder { @@ -440,7 +473,7 @@ where } } -impl +impl CreateBuilder< E, CodeHash, @@ -449,6 +482,7 @@ impl Args, Unset, RetType, + ContractStorage, ContractRef, > where @@ -467,6 +501,7 @@ where Args, Set, RetType, + ContractStorage, ContractRef, > where @@ -484,7 +519,7 @@ where } } -impl +impl CreateBuilder< E, CodeHash, @@ -493,6 +528,7 @@ impl Args, Salt, Unset>, + ContractStorage, ContractRef, > where @@ -518,6 +554,7 @@ where Args, Salt, Set>, + ContractStorage, ContractRef, > { CreateBuilder { @@ -532,7 +569,7 @@ where } } -impl +impl CreateBuilder< E, Set, @@ -541,6 +578,7 @@ impl Set>, Set, Set>, + ContractStorage, ContractRef, > where @@ -549,7 +587,9 @@ where { /// Finalizes the create builder, allowing it to instantiate a contract. #[inline] - pub fn params(self) -> CreateParams { + pub fn params( + self, + ) -> CreateParams { CreateParams { code_hash: self.code_hash.value(), gas_limit: self.gas_limit.unwrap_or_else(|| 0), @@ -562,7 +602,7 @@ where } } -impl +impl CreateBuilder< E, Set, @@ -571,6 +611,7 @@ impl Set>, Set, Set>, + ContractStorage, ContractRef, > where @@ -578,7 +619,7 @@ where GasLimit: Unwrap, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType: InstantiateResult, + RetType: InstantiateResult, ContractRef: FromAccountId, { /// Instantiates the contract using the given instantiation parameters. @@ -590,7 +631,8 @@ where #[inline] pub fn instantiate( self, - ) -> Result<>::Output, Error> { + ) -> Result<>::Output, Error> + { self.params().instantiate() } @@ -604,7 +646,7 @@ where self, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, Error, > { diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 440cc5b1032..158f0fa88e0 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -17,10 +17,18 @@ use crate::{ EnvBackend, TypedEnvBackend, }, + call::{ + utils::InstantiateResult, + FromAccountId, + }, Result as EnvResult, }; use cfg_if::cfg_if; -use ink_primitives::ConstructorResult; +use ink_engine::ext; +use ink_primitives::{ + ConstructorResult, + LangError, +}; pub trait OnInstance: EnvBackend + TypedEnvBackend { fn on_instance(f: F) -> R @@ -42,65 +50,118 @@ cfg_if! { } } -// The `Result` type used to represent the programmer defined contract output. -type ContractResult = core::result::Result; - // We only use this function when 1) compiling to Wasm 2) compiling for tests. #[cfg_attr(all(feature = "std", not(test)), allow(dead_code))] -pub(crate) fn decode_fallible_constructor_reverted_return_value( +pub(crate) fn decode_instantiate_result( + instantiate_result: Result<(), ext::Error>, + out_address: &mut I, out_return_value: &mut I, -) -> EnvResult>> +) -> EnvResult< + ConstructorResult<>::Output>, +> where I: scale::Input, E: crate::Environment, - ContractError: scale::Decode, + R: InstantiateResult, + ContractRef: FromAccountId, { - let out: ConstructorResult> = - scale::Decode::decode(out_return_value)?; - - match out { - ConstructorResult::Ok(ContractResult::Ok(())) => { - // Since the contract reverted we don't expect an `Ok` return value from the - // constructor, otherwise we'd be in the `AccountId` decoding branch. - // - // While we could handle this more gracefully, e.g through a `LangError`, we're going to - // be defensive for now and trap. - panic!( - "The callee reverted, but did not encode an error in the output buffer." - ) + match instantiate_result { + Ok(()) => { + let account_id = scale::Decode::decode(out_address)?; + let contract_ref = + >::from_account_id(account_id); + let output = >::ok(contract_ref); + Ok(Ok(output)) } - ConstructorResult::Ok(ContractResult::Err(contract_error)) => { - Ok(ConstructorResult::Ok(ContractResult::Err(contract_error))) + Err(ext::Error::CalleeReverted) => { + let constructor_result_variant = out_return_value.read_byte()?; + match constructor_result_variant { + // 0 == `ConstructorResult::Ok` variant + 0 => { + if >::IS_RESULT { + let result_variant = out_return_value.read_byte()?; + match result_variant { + // 0 == `Ok` variant + 0 => panic!("The callee reverted, but did not encode an error in the output buffer."), + // 1 == `Err` variant + 1 => { + let contract_err = <>::Error + as scale::Decode>::decode(out_return_value)?; + let err = >::err(contract_err); + Ok(Ok(err)) + } + _ => panic!("Invalid inner constructor Result encoding, expected 0 or 1 as the first byte") + } + } else { + panic!("The callee reverted, but did not encode an error in the output buffer.") + } + } + // 1 == `ConstructorResult::Err` variant + 1 => { + let lang_err = ::decode(out_return_value)?; + Ok(Err(lang_err)) + } + _ => panic!("Invalid outer constructor Result encoding, expected 0 or 1 as the first byte") + } } - ConstructorResult::Err(lang_error) => Ok(ConstructorResult::Err(lang_error)), + Err(actual_error) => Err(actual_error.into()), } } #[cfg(test)] mod fallible_constructor_reverted_tests { use super::*; + use crate::Environment; use scale::Encode; + // The `Result` type used to represent the programmer defined contract output. + type ContractResult = Result; + #[derive(scale::Encode, scale::Decode)] struct ContractError(String); + struct TestContractRef(::AccountId); + + impl FromAccountId for TestContractRef { + fn from_account_id(account_id: ::AccountId) -> Self { + Self(account_id) + } + } + fn encode_and_decode_return_value( return_value: ConstructorResult>, - ) -> EnvResult>> - { + ) -> EnvResult< + ConstructorResult< + Result, ContractError>, + >, + > { + let out_address = Vec::new(); let encoded_return_value = return_value.encode(); - decode_return_value(&mut &encoded_return_value[..]) + decode_return_value_fallible( + &mut &out_address[..], + &mut &encoded_return_value[..], + ) } - fn decode_return_value( - input: &mut I, - ) -> EnvResult>> - { - decode_fallible_constructor_reverted_return_value::< + fn decode_return_value_fallible( + out_address: &mut I, + out_return_value: &mut I, + ) -> EnvResult< + ConstructorResult< + Result, ContractError>, + >, + > { + decode_instantiate_result::< I, crate::DefaultEnvironment, - ContractError, - >(input) + Result<(), ContractError>, + (), + TestContractRef, + >( + Err(ext::Error::CalleeReverted), + out_address, + out_return_value, + ) } #[test] @@ -144,9 +205,13 @@ mod fallible_constructor_reverted_tests { #[test] fn invalid_bytes_in_output_buffer_fail_decoding() { + let out_address = Vec::new(); let invalid_encoded_return_value = vec![69]; - let decoded_result = decode_return_value(&mut &invalid_encoded_return_value[..]); + let decoded_result = decode_return_value_fallible( + &mut &out_address[..], + &mut &invalid_encoded_return_value[..], + ); assert!(matches!(decoded_result, Err(crate::Error::Decode(_)))) } diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index d37d300e003..7949ea70ee3 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -471,19 +471,19 @@ impl TypedEnvBackend for EnvInstance { ) } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId, { let _code_hash = params.code_hash(); diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 005ff11634e..9c7ce2eb439 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -484,7 +484,11 @@ impl TypedEnvBackend for EnvInstance { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result>::Output>> + ) -> Result< + ink_primitives::ConstructorResult< + ::Output, + >, + > where E: Environment, Args: scale::Encode, @@ -504,7 +508,7 @@ impl TypedEnvBackend for EnvInstance { let salt = params.salt_bytes().as_ref(); let out_return_value = &mut scoped.take_rest(); - let instantiate_result = ext::instantiate( + let instantiate_result = out_addressext::instantiate( enc_code_hash, gas_limit, enc_endowment, @@ -514,19 +518,11 @@ impl TypedEnvBackend for EnvInstance { salt, ); - match instantiate_result { - Ok(()) => { - let account_id = scale::Decode::decode(&mut &out_address[..])?; - let contract_ref = >::from_account_id(account_id); - let output = >::output(contract_ref); - Ok(ink_primitives::ConstructorResult::Ok(output)) - } - Err(ext::Error::CalleeReverted) => { - todo!("custom decoding based on InstantiateResult") - // if InstantiateResult::IS_RESULT, attempt to decode Result manually by first byte - } - Err(actual_error) => Err(actual_error.into()), - } + crate::engine::decode_instantiate_result::<_, E, RetType, ContractError>( + instantiate_result, + &mut &out_address[..], + &mut &out_return_value[..], + ) } // fn instantiate_fallible_contract( 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 ab318ad6eb3..f3d1a057958 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -407,6 +407,7 @@ impl ContractRef<'_> { .output() .map(quote::ToTokens::to_token_stream) .unwrap_or_else(|| quote::quote! { Self }); + let storage_ident = self.contract.module().storage().ident(); quote_spanned!(span => #( #attrs )* #[inline] @@ -421,9 +422,10 @@ impl ContractRef<'_> { ::ink::env::call::utils::Set<::ink::env::call::ExecutionInput<#arg_list>>, ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, + #storage_ident, Self, > { - ::ink::env::call::build_create::() + ::ink::env::call::build_create::() .exec_input( ::ink::env::call::ExecutionInput::new( ::ink::env::call::Selector::new([ #( #selector_bytes ),* ]) diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 4a78a52faf1..e61312e2efc 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -16,12 +16,12 @@ use crate::ChainExtensionInstance; use core::marker::PhantomData; use ink_env::{ call::{ + utils::InstantiateResult, Call, CallParams, CreateParams, DelegateCall, FromAccountId, - utils::InstantiateResult, }, hash::{ CryptoHash, @@ -480,17 +480,23 @@ where /// # Note /// /// For more details visit: [`ink_env::instantiate_contract`] - pub fn instantiate_contract( + pub fn instantiate_contract( self, - params: &CreateParams, - ) -> Result>::Output>> + params: &CreateParams, + ) -> Result< + ink_primitives::ConstructorResult< + >::Output, + >, + > where Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId, { - ink_env::instantiate_contract::(params) + ink_env::instantiate_contract::( + params, + ) } /// Invokes a contract message and returns its result. From 448b3809e844b5b5e5b15a3d409b589124b90066 Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 16 Jan 2023 00:18:07 +0000 Subject: [PATCH 085/206] Remove commented out instantiate_fallible_contract --- crates/env/src/engine/on_chain/impls.rs | 54 ------------------------- 1 file changed, 54 deletions(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 9c7ce2eb439..d56b5039d4f 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -525,60 +525,6 @@ impl TypedEnvBackend for EnvInstance { ) } - // fn instantiate_fallible_contract( - // &mut self, - // params: &CreateParams, - // ) -> Result< - // ink_primitives::ConstructorResult< - // core::result::Result, - // >, - // > - // where - // E: Environment, - // Args: scale::Encode, - // Salt: AsRef<[u8]>, - // { - // let mut scoped = self.scoped_buffer(); - // let gas_limit = params.gas_limit(); - // let enc_code_hash = scoped.take_encoded(params.code_hash()); - // let enc_endowment = scoped.take_encoded(params.endowment()); - // let enc_input = scoped.take_encoded(params.exec_input()); - // // We support `AccountId` types with an encoding that requires up to - // // 1024 bytes. Beyond that limit ink! contracts will trap for now. - // // In the default configuration encoded `AccountId` require 32 bytes. - // let out_address = &mut scoped.take(1024); - // let salt = params.salt_bytes().as_ref(); - // let out_return_value = &mut scoped.take_rest(); - // - // let instantiate_result = ext::instantiate( - // enc_code_hash, - // gas_limit, - // enc_endowment, - // enc_input, - // out_address, - // out_return_value, - // salt, - // ); - // - // // todo: < - // - // match instantiate_result { - // Ok(()) => { - // let account_id: E::AccountId = - // scale::Decode::decode(&mut &out_address[..])?; - // Ok(ink_primitives::ConstructorResult::Ok(Ok(account_id))) - // } - // Err(ext::Error::CalleeReverted) => { - // crate::engine::decode_fallible_constructor_reverted_return_value::< - // _, - // E, - // ContractError, - // >(&mut &out_return_value[..]) - // } - // Err(actual_error) => Err(actual_error.into()), - // } - // } - fn terminate_contract(&mut self, beneficiary: E::AccountId) -> ! where E: Environment, From a0799d0d2bea4a1873541d60b1a5fae392991e66 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 16 Jan 2023 13:43:00 +0000 Subject: [PATCH 086/206] Convert to env Error in helper --- crates/env/src/engine/mod.rs | 13 ++++++++----- crates/env/src/engine/on_chain/impls.rs | 6 +++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 158f0fa88e0..7fbd11fb1ae 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -21,10 +21,10 @@ use crate::{ utils::InstantiateResult, FromAccountId, }, + Error as EnvError, Result as EnvResult, }; use cfg_if::cfg_if; -use ink_engine::ext; use ink_primitives::{ ConstructorResult, LangError, @@ -53,7 +53,7 @@ cfg_if! { // We only use this function when 1) compiling to Wasm 2) compiling for tests. #[cfg_attr(all(feature = "std", not(test)), allow(dead_code))] pub(crate) fn decode_instantiate_result( - instantiate_result: Result<(), ext::Error>, + instantiate_result: EnvResult<()>, out_address: &mut I, out_return_value: &mut I, ) -> EnvResult< @@ -73,7 +73,7 @@ where let output = >::ok(contract_ref); Ok(Ok(output)) } - Err(ext::Error::CalleeReverted) => { + Err(EnvError::CalleeReverted) => { let constructor_result_variant = out_return_value.read_byte()?; match constructor_result_variant { // 0 == `ConstructorResult::Ok` variant @@ -111,7 +111,10 @@ where #[cfg(test)] mod fallible_constructor_reverted_tests { use super::*; - use crate::Environment; + use crate::{ + Error, + Environment, + }; use scale::Encode; // The `Result` type used to represent the programmer defined contract output. @@ -158,7 +161,7 @@ mod fallible_constructor_reverted_tests { (), TestContractRef, >( - Err(ext::Error::CalleeReverted), + Err(Error::CalleeReverted), out_address, out_return_value, ) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index d56b5039d4f..42a393cbaa5 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -25,6 +25,7 @@ use crate::{ CallParams, CreateParams, DelegateCall, + FromAccountId, }, hash::{ Blake2x128, @@ -42,7 +43,6 @@ use crate::{ EnvBackend, Environment, Error, - FromAccountId, FromLittleEndian, Result, ReturnFlags, @@ -508,7 +508,7 @@ impl TypedEnvBackend for EnvInstance { let salt = params.salt_bytes().as_ref(); let out_return_value = &mut scoped.take_rest(); - let instantiate_result = out_addressext::instantiate( + let instantiate_result = ext::instantiate( enc_code_hash, gas_limit, enc_endowment, @@ -519,7 +519,7 @@ impl TypedEnvBackend for EnvInstance { ); crate::engine::decode_instantiate_result::<_, E, RetType, ContractError>( - instantiate_result, + instantiate_result.map_err(Into::into), &mut &out_address[..], &mut &out_return_value[..], ) From 83c9ea2c253f2a2eb012601ae0f3ce0a8cef8638 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 16 Jan 2023 16:32:27 +0000 Subject: [PATCH 087/206] Return Decode errors in case of invalid Result first byte --- crates/env/src/engine/mod.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 7fbd11fb1ae..0627ce5e041 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -22,6 +22,7 @@ use crate::{ FromAccountId, }, Error as EnvError, + Error, Result as EnvResult, }; use cfg_if::cfg_if; @@ -90,7 +91,7 @@ where let err = >::err(contract_err); Ok(Ok(err)) } - _ => panic!("Invalid inner constructor Result encoding, expected 0 or 1 as the first byte") + _ => Err(Error::Decode("Invalid inner constructor Result encoding, expected 0 or 1 as the first byte".into())) } } else { panic!("The callee reverted, but did not encode an error in the output buffer.") @@ -101,7 +102,7 @@ where let lang_err = ::decode(out_return_value)?; Ok(Err(lang_err)) } - _ => panic!("Invalid outer constructor Result encoding, expected 0 or 1 as the first byte") + _ => Err(Error::Decode("Invalid outer constructor Result encoding, expected 0 or 1 as the first byte".into())) } } Err(actual_error) => Err(actual_error.into()), @@ -109,11 +110,11 @@ where } #[cfg(test)] -mod fallible_constructor_reverted_tests { +mod decode_instantiate_result_tests { use super::*; use crate::{ - Error, Environment, + Error, }; use scale::Encode; @@ -160,11 +161,7 @@ mod fallible_constructor_reverted_tests { Result<(), ContractError>, (), TestContractRef, - >( - Err(Error::CalleeReverted), - out_address, - out_return_value, - ) + >(Err(Error::CalleeReverted), out_address, out_return_value) } #[test] From 89c77403c8f34ca521ebae084106ed4a4f63c066 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 16 Jan 2023 16:40:04 +0000 Subject: [PATCH 088/206] Fix impls::instantiate_contract --- crates/env/src/engine/on_chain/impls.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 42a393cbaa5..8afeef27e43 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -481,19 +481,19 @@ impl TypedEnvBackend for EnvInstance { } } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult< - ::Output, + >::Output, >, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType: InstantiateResult, + RetType: InstantiateResult, ContractRef: FromAccountId, { let mut scoped = self.scoped_buffer(); @@ -518,7 +518,7 @@ impl TypedEnvBackend for EnvInstance { salt, ); - crate::engine::decode_instantiate_result::<_, E, RetType, ContractError>( + crate::engine::decode_instantiate_result::<_, E, RetType, ContractStorage, ContractRef>( instantiate_result.map_err(Into::into), &mut &out_address[..], &mut &out_return_value[..], From 7e7979a9961ae2039ff38e7a836d7041184f73f8 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 17 Jan 2023 18:24:37 +0000 Subject: [PATCH 089/206] Remove ContractStorage generic parameter --- crates/env/src/api.rs | 21 ++--- crates/env/src/backend.rs | 10 +- crates/env/src/call/common.rs | 20 ++-- crates/env/src/call/create_builder.rs | 94 +++++-------------- crates/env/src/engine/mod.rs | 19 ++-- crates/env/src/engine/off_chain/impls.rs | 10 +- crates/env/src/engine/on_chain/impls.rs | 10 +- .../generator/as_dependency/contract_ref.rs | 3 +- crates/ink/src/env_access.rs | 4 +- crates/ink/src/reflect/contract.rs | 11 +++ 10 files changed, 77 insertions(+), 125 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index e77a18066ac..63cdea2dece 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -323,29 +323,22 @@ where /// - If the instantiation process runs out of gas. /// - If given insufficient endowment. /// - If the returned account ID failed to decode properly. -pub fn instantiate_contract( - params: &CreateParams, +pub fn instantiate_contract( + params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult< - >::Output, - >, + ink_primitives::ConstructorResult<>::Output>, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId, { ::on_instance(|instance| { - TypedEnvBackend::instantiate_contract::< - E, - Args, - Salt, - R, - ContractStorage, - ContractRef, - >(instance, params) + TypedEnvBackend::instantiate_contract::( + instance, params, + ) }) } diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 801bf6c078c..f2f1d1ac5f9 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -441,19 +441,17 @@ pub trait TypedEnvBackend: EnvBackend { /// # Note /// /// For more details visit: [`instantiate_contract`][`crate::instantiate_contract`] - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult< - >::Output, - >, + ink_primitives::ConstructorResult<>::Output>, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId; /// Terminates a smart contract. diff --git a/crates/env/src/call/common.rs b/crates/env/src/call/common.rs index 9b9ab2d2f02..d17d06de031 100644 --- a/crates/env/src/call/common.rs +++ b/crates/env/src/call/common.rs @@ -57,48 +57,48 @@ pub trait InstantiateResult: private::Sealed { const IS_RESULT: bool = false; /// Reflects the output type of the dispatchable ink! constructor. - type Output; + type Output; /// The error type of the constructor return type. type Error: scale::Decode; /// Construct a success value of the `Output` type. - fn ok(value: O) -> Self::Output; + fn ok(value: C) -> Self::Output; /// Construct an error value of the `Output` type. - fn err(err: Self::Error) -> Self::Output; + fn err(err: Self::Error) -> Self::Output; } impl private::Sealed for T {} impl InstantiateResult for C { - type Output = O; + type Output = C; type Error = (); - fn ok(value: O) -> Self::Output { + fn ok(value: C) -> Self::Output { value } - fn err(_err: Self::Error) -> Self::Output { + fn err(_err: Self::Error) -> Self::Output { // todo! unreachable!() } } -impl InstantiateResult for Result +impl InstantiateResult for core::result::Result where E: scale::Decode, { const IS_RESULT: bool = true; - type Output = Result; + type Output = core::result::Result; type Error = E; - fn ok(value: O) -> Self::Output { + fn ok(value: C) -> Self::Output { Ok(value) } - fn err(err: Self::Error) -> Self::Output { + fn err(err: Self::Error) -> Self::Output { Err(err) } } diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 51c62a483b1..0099b8cc35e 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -53,7 +53,7 @@ where /// Builds up contract instantiations. #[derive(Debug)] -pub struct CreateParams +pub struct CreateParams where E: Environment, { @@ -68,13 +68,12 @@ where /// The salt for determining the hash for the contract account ID. salt_bytes: Salt, /// The return type of the target contracts constructor method. - _return_type: ReturnType<(R, ContractStorage)>, + _return_type: ReturnType, /// Phantom for ContractRef: todo! _contract_ref: PhantomData, } -impl - CreateParams +impl CreateParams where E: Environment, { @@ -103,8 +102,7 @@ where } } -impl - CreateParams +impl CreateParams where E: Environment, Salt: AsRef<[u8]>, @@ -116,13 +114,12 @@ where } } -impl - CreateParams +impl CreateParams where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId, { /// Instantiates the contract and returns its account ID back to the caller. @@ -134,10 +131,7 @@ where #[inline] pub fn instantiate( &self, - ) -> Result< - >::Output, - crate::Error, - > { + ) -> Result<>::Output, crate::Error> { crate::instantiate_contract(self).map(|inner| { inner.unwrap_or_else(|error| { panic!("Received a `LangError` while instantiating: {:?}", error) @@ -154,9 +148,7 @@ where pub fn try_instantiate( &self, ) -> Result< - ink_primitives::ConstructorResult< - >::Output, - >, + ink_primitives::ConstructorResult<>::Output>, crate::Error, > { crate::instantiate_contract(self) @@ -172,7 +164,6 @@ pub struct CreateBuilder< Args, Salt, RetType, - ContractStorage, ContractRef, > where E: Environment, @@ -183,7 +174,7 @@ pub struct CreateBuilder< exec_input: Args, salt: Salt, return_type: RetType, - _phantom: PhantomData (E, ContractStorage, ContractRef)>, + _phantom: PhantomData (E, ContractRef)>, } /// Returns a new [`CreateBuilder`] to build up the parameters to a cross-contract instantiation. @@ -276,7 +267,7 @@ pub struct CreateBuilder< /// /// Note the usage of the [`CreateBuilder::instantiate_fallible`] method. #[allow(clippy::type_complexity)] -pub fn build_create() -> CreateBuilder< +pub fn build_create() -> CreateBuilder< E, Unset, Unset, @@ -284,7 +275,6 @@ pub fn build_create() -> CreateBuilder< Unset>, Unset, Set>, - ContractStorage, ContractRef, > where @@ -301,7 +291,7 @@ where } } -impl +impl CreateBuilder< E, Unset, @@ -310,7 +300,6 @@ impl Args, Salt, RetType, - ContractStorage, ContractRef, > where @@ -329,7 +318,6 @@ where Args, Salt, RetType, - ContractStorage, ContractRef, > { CreateBuilder { @@ -344,18 +332,8 @@ where } } -impl - CreateBuilder< - E, - CodeHash, - Unset, - Endowment, - Args, - Salt, - RetType, - ContractStorage, - ContractRef, - > +impl + CreateBuilder, Endowment, Args, Salt, RetType, ContractRef> where E: Environment, { @@ -364,17 +342,8 @@ where pub fn gas_limit( self, gas_limit: u64, - ) -> CreateBuilder< - E, - CodeHash, - Set, - Endowment, - Args, - Salt, - RetType, - ContractStorage, - ContractRef, - > { + ) -> CreateBuilder, Endowment, Args, Salt, RetType, ContractRef> + { CreateBuilder { code_hash: self.code_hash, gas_limit: Set(gas_limit), @@ -387,7 +356,7 @@ where } } -impl +impl CreateBuilder< E, CodeHash, @@ -396,7 +365,6 @@ impl Args, Salt, RetType, - ContractStorage, ContractRef, > where @@ -415,7 +383,6 @@ where Args, Salt, RetType, - ContractStorage, ContractRef, > { CreateBuilder { @@ -430,7 +397,7 @@ where } } -impl +impl CreateBuilder< E, CodeHash, @@ -439,7 +406,6 @@ impl>, Salt, RetType, - ContractStorage, ContractRef, > where @@ -458,7 +424,6 @@ where Set>, Salt, RetType, - ContractStorage, ContractRef, > { CreateBuilder { @@ -473,7 +438,7 @@ where } } -impl +impl CreateBuilder< E, CodeHash, @@ -482,7 +447,6 @@ impl, RetType, - ContractStorage, ContractRef, > where @@ -501,7 +465,6 @@ where Args, Set, RetType, - ContractStorage, ContractRef, > where @@ -519,7 +482,7 @@ where } } -impl +impl CreateBuilder< E, CodeHash, @@ -528,7 +491,6 @@ impl Args, Salt, Unset>, - ContractStorage, ContractRef, > where @@ -554,7 +516,6 @@ where Args, Salt, Set>, - ContractStorage, ContractRef, > { CreateBuilder { @@ -569,7 +530,7 @@ where } } -impl +impl CreateBuilder< E, Set, @@ -578,7 +539,6 @@ impl Set>, Set, Set>, - ContractStorage, ContractRef, > where @@ -587,9 +547,7 @@ where { /// Finalizes the create builder, allowing it to instantiate a contract. #[inline] - pub fn params( - self, - ) -> CreateParams { + pub fn params(self) -> CreateParams { CreateParams { code_hash: self.code_hash.value(), gas_limit: self.gas_limit.unwrap_or_else(|| 0), @@ -602,7 +560,7 @@ where } } -impl +impl CreateBuilder< E, Set, @@ -611,7 +569,6 @@ impl Set>, Set, Set>, - ContractStorage, ContractRef, > where @@ -619,7 +576,7 @@ where GasLimit: Unwrap, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType: InstantiateResult, + RetType: InstantiateResult, ContractRef: FromAccountId, { /// Instantiates the contract using the given instantiation parameters. @@ -631,8 +588,7 @@ where #[inline] pub fn instantiate( self, - ) -> Result<>::Output, Error> - { + ) -> Result<>::Output, Error> { self.params().instantiate() } @@ -646,7 +602,7 @@ where self, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, Error, > { diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 0627ce5e041..d237933e427 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -53,17 +53,15 @@ cfg_if! { // We only use this function when 1) compiling to Wasm 2) compiling for tests. #[cfg_attr(all(feature = "std", not(test)), allow(dead_code))] -pub(crate) fn decode_instantiate_result( +pub(crate) fn decode_instantiate_result( instantiate_result: EnvResult<()>, out_address: &mut I, out_return_value: &mut I, -) -> EnvResult< - ConstructorResult<>::Output>, -> +) -> EnvResult>::Output>> where I: scale::Input, E: crate::Environment, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId, { match instantiate_result { @@ -71,7 +69,7 @@ where let account_id = scale::Decode::decode(out_address)?; let contract_ref = >::from_account_id(account_id); - let output = >::ok(contract_ref); + let output = >::ok(contract_ref); Ok(Ok(output)) } Err(EnvError::CalleeReverted) => { @@ -79,16 +77,16 @@ where match constructor_result_variant { // 0 == `ConstructorResult::Ok` variant 0 => { - if >::IS_RESULT { + if >::IS_RESULT { let result_variant = out_return_value.read_byte()?; match result_variant { // 0 == `Ok` variant 0 => panic!("The callee reverted, but did not encode an error in the output buffer."), // 1 == `Err` variant 1 => { - let contract_err = <>::Error + let contract_err = <>::Error as scale::Decode>::decode(out_return_value)?; - let err = >::err(contract_err); + let err = >::err(contract_err); Ok(Ok(err)) } _ => Err(Error::Decode("Invalid inner constructor Result encoding, expected 0 or 1 as the first byte".into())) @@ -158,8 +156,7 @@ mod decode_instantiate_result_tests { decode_instantiate_result::< I, crate::DefaultEnvironment, - Result<(), ContractError>, - (), + Result, ContractError>, TestContractRef, >(Err(Error::CalleeReverted), out_address, out_return_value) } diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 7949ea70ee3..beb65d270c6 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -471,19 +471,17 @@ impl TypedEnvBackend for EnvInstance { ) } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult< - >::Output, - >, + ink_primitives::ConstructorResult<>::Output>, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId, { let _code_hash = params.code_hash(); diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 8afeef27e43..c55660bf2ec 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -481,19 +481,19 @@ impl TypedEnvBackend for EnvInstance { } } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType: InstantiateResult, + RetType: InstantiateResult, ContractRef: FromAccountId, { let mut scoped = self.scoped_buffer(); @@ -518,7 +518,7 @@ impl TypedEnvBackend for EnvInstance { salt, ); - crate::engine::decode_instantiate_result::<_, E, RetType, ContractStorage, ContractRef>( + crate::engine::decode_instantiate_result::<_, E, RetType, ContractRef>( instantiate_result.map_err(Into::into), &mut &out_address[..], &mut &out_return_value[..], 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 f3d1a057958..d927b757bfc 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -422,10 +422,9 @@ impl ContractRef<'_> { ::ink::env::call::utils::Set<::ink::env::call::ExecutionInput<#arg_list>>, ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, - #storage_ident, Self, > { - ::ink::env::call::build_create::() + ::ink::env::call::build_create::() .exec_input( ::ink::env::call::ExecutionInput::new( ::ink::env::call::Selector::new([ #( #selector_bytes ),* ]) diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index e61312e2efc..87344ef192e 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -485,13 +485,13 @@ where params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, > where Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId, { ink_env::instantiate_contract::( diff --git a/crates/ink/src/reflect/contract.rs b/crates/ink/src/reflect/contract.rs index 3488980a3cf..a10da63ea24 100644 --- a/crates/ink/src/reflect/contract.rs +++ b/crates/ink/src/reflect/contract.rs @@ -177,8 +177,19 @@ pub trait ContractEnv { /// // are of the same type. /// const _: IsSameType<::Type> = /// >::new(); +/// const _: IsSameType< as ContractReference>::Type> = +/// >>::new(); /// ``` pub trait ContractReference { /// The generated contract reference type. type Type; } + +/// Blanket impl for [`ContractRef`] for mapping to the equivalent [`Result`] +/// type. Enables handling constructors which return a `Result`. +impl ContractReference for core::result::Result +where + C: ContractReference, +{ + type Type = core::result::Result<::Type, E>; +} From aca74ac819041d24664ff3317117d80e6e0fafd6 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 17 Jan 2023 21:26:00 +0000 Subject: [PATCH 090/206] Fix env access --- crates/ink/src/env_access.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 87344ef192e..0fa258db870 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -480,12 +480,12 @@ where /// # Note /// /// For more details visit: [`ink_env::instantiate_contract`] - pub fn instantiate_contract( + pub fn instantiate_contract( self, - params: &CreateParams, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, > where @@ -494,7 +494,7 @@ where R: InstantiateResult, ContractRef: FromAccountId, { - ink_env::instantiate_contract::( + ink_env::instantiate_contract::( params, ) } From 604a16a1205c57b29166c0a7e7056727f21985ca Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 17 Jan 2023 22:01:41 +0000 Subject: [PATCH 091/206] Use generated constructor ref, introduces update_selector --- crates/env/src/call/create_builder.rs | 9 ++++++ crates/env/src/call/execution_input.rs | 10 ++++++ .../generator/as_dependency/contract_ref.rs | 1 - crates/ink/src/env_access.rs | 8 ++--- .../call-builder/lib.rs | 31 +++++++++---------- 5 files changed, 35 insertions(+), 24 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 0099b8cc35e..16683b64d4c 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -23,6 +23,7 @@ use crate::{ Unwrap, }, ExecutionInput, + Selector, }, Environment, Error, @@ -100,6 +101,14 @@ where pub fn exec_input(&self) -> &ExecutionInput { &self.exec_input } + + /// Modify the selector. + /// + /// Useful when using the [`CreateParams`] generated as part of the + /// contract ref, but using a custom selector. + pub fn update_selector(&mut self, selector: Selector) { + self.exec_input.update_selector(selector) + } } impl CreateParams diff --git a/crates/env/src/call/execution_input.rs b/crates/env/src/call/execution_input.rs index fba340ebf1c..8f3f79dd171 100644 --- a/crates/env/src/call/execution_input.rs +++ b/crates/env/src/call/execution_input.rs @@ -63,6 +63,16 @@ impl ExecutionInput, Rest>> { } } +impl ExecutionInput { + /// Modify the selector. + /// + /// Useful when using the [`ExecutionInput`] generated as part of the + /// contract ref, but using a custom selector. + pub fn update_selector(&mut self, selector: Selector) { + self.selector = selector; + } +} + /// An argument list. /// /// This type is constructed mainly at compile type via type constructions 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 d927b757bfc..ab318ad6eb3 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -407,7 +407,6 @@ impl ContractRef<'_> { .output() .map(quote::ToTokens::to_token_stream) .unwrap_or_else(|| quote::quote! { Self }); - let storage_ident = self.contract.module().storage().ident(); quote_spanned!(span => #( #attrs )* #[inline] diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 0fa258db870..3134839e744 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -484,9 +484,7 @@ where self, params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult< - >::Output, - >, + ink_primitives::ConstructorResult<>::Output>, > where Args: scale::Encode, @@ -494,9 +492,7 @@ where R: InstantiateResult, ContractRef: FromAccountId, { - ink_env::instantiate_contract::( - params, - ) + ink_env::instantiate_contract::(params) } /// Invokes a contract message and returns its result. diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 5ef06bf6d52..b0164557bbb 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -17,10 +17,10 @@ #[ink::contract] mod call_builder { + use constructors_return_value::ConstructorsReturnValueRef; use ink::env::{ call::{ build_call, - build_create, Call, ExecutionInput, Selector, @@ -81,16 +81,16 @@ mod call_builder { selector: [u8; 4], init_value: bool, ) -> Option { - let result = build_create::() + let mut params = ConstructorsReturnValueRef::new(init_value) .code_hash(code_hash) .gas_limit(0) .endowment(0) - .exec_input( - ExecutionInput::new(Selector::new(selector)).push_arg(init_value), - ) .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) - .returns::() - .params() + .params(); + + params.update_selector(Selector::new(selector)); + + let result = params .try_instantiate() .expect("Error from the Contracts pallet."); @@ -122,20 +122,17 @@ mod call_builder { ink::LangError, >, > { - let lang_result = build_create::() + let mut params = ConstructorsReturnValueRef::try_new(init_value) .code_hash(code_hash) .gas_limit(0) .endowment(0) - .exec_input( - ExecutionInput::new(Selector::new(selector)).push_arg(init_value), - ) .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) - .returns::>() - .params() - .try_instantiate_fallible() + .params(); + + params.update_selector(Selector::new(selector)); + + let lang_result = params + .try_instantiate() .expect("Error from the Contracts pallet."); Some(lang_result.map(|contract_result| { From fcc7b1ee9fd64134816e0f0c9815560fa279b9ec Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 17 Jan 2023 22:07:51 +0000 Subject: [PATCH 092/206] Fix e2e --- crates/e2e/src/builders.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/e2e/src/builders.rs b/crates/e2e/src/builders.rs index b08eaf8649f..164f1c07ca1 100644 --- a/crates/e2e/src/builders.rs +++ b/crates/e2e/src/builders.rs @@ -39,8 +39,7 @@ pub type CreateBuilderPartial = CreateBuilder< Unset<::Balance>, Set>, Unset, - Set>, - R, // todo ContractStorage param? + Set>, R, >; From 9a14e21be6c3d609ea341dbc759b7101563add9c Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 18 Jan 2023 09:46:31 +0000 Subject: [PATCH 093/206] Use return_value() method in e2e test --- examples/lang-err-integration-tests/call-builder/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 33f27c0c6b3..252353046b2 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -366,7 +366,7 @@ mod call_builder { .call(&mut ink_e2e::eve(), call, 0, None) .await .expect("Calling `call_builder::call_instantiate_fallible` failed") - .value + .return_value() .expect("Dispatching `call_builder::call_instantiate_fallible` failed."); assert!( @@ -404,7 +404,7 @@ mod call_builder { .call(&mut ink_e2e::ferdie(), call, 0, None) .await .expect("Calling `call_builder::call_instantiate_fallible` failed") - .value + .return_value() .expect("Dispatching `call_builder::call_instantiate_fallible` failed."); let contract_result = call_result @@ -496,7 +496,7 @@ mod call_builder { .expect( "Client failed to call `call_builder::call_instantiate_fallible`.", ) - .value + .return_value() .expect("Dispatching `call_builder::call_instantiate_fallible` failed."); assert!( From 1af170b82b18d8366bbce9d3f40349f2010418c8 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 17 Jan 2023 22:42:27 +0000 Subject: [PATCH 094/206] Remove commented out code --- crates/env/src/call/common.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/crates/env/src/call/common.rs b/crates/env/src/call/common.rs index d17d06de031..46a7e0cb23f 100644 --- a/crates/env/src/call/common.rs +++ b/crates/env/src/call/common.rs @@ -172,16 +172,3 @@ impl Unwrap for Set { self.value() } } - -// #[cfg(test)] -// mod tests { -// use super::*; -// -// #[test] -// fn instantiate_result_types() { -// static_assertions::assert_type_eq_all!( -// Result<(), u8>, -// as InstantiateResult<()>> -// ); -// } -// } From a7a2f7a07505963fd19435b2badc568557f7fe16 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 18 Jan 2023 09:52:19 +0000 Subject: [PATCH 095/206] Typos --- .../constructors-return-value/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 339cc95b508..6c70e3eaa32 100644 --- a/examples/lang-err-integration-tests/constructors-return-value/lib.rs +++ b/examples/lang-err-integration-tests/constructors-return-value/lib.rs @@ -34,7 +34,7 @@ pub mod constructors_return_value { } } - /// A constructor which reverts and fills the output buffer with an erronenously encoded + /// A constructor which reverts and fills the output buffer with an erroneously encoded /// return value. #[ink(constructor)] pub fn revert_new(_init_value: bool) -> Self { @@ -44,7 +44,7 @@ pub mod constructors_return_value { ) } - /// A constructor which reverts and fills the output buffer with an erronenously encoded + /// A constructor which reverts and fills the output buffer with an erroneously encoded /// return value. #[ink(constructor)] pub fn try_revert_new(init_value: bool) -> Result { From e259331f212533088cccdd0a05ebbec85c224425 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 18 Jan 2023 10:09:20 +0000 Subject: [PATCH 096/206] Clippy --- crates/env/src/engine/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index d237933e427..a89d2692c0a 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -103,7 +103,7 @@ where _ => Err(Error::Decode("Invalid outer constructor Result encoding, expected 0 or 1 as the first byte".into())) } } - Err(actual_error) => Err(actual_error.into()), + Err(actual_error) => Err(actual_error), } } From 9cb02cba825d0a2bc40760866d955c0bd5a3836f Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 18 Jan 2023 10:35:58 +0000 Subject: [PATCH 097/206] Rename some instantiate_fallible --- crates/env/src/call/create_builder.rs | 4 +--- examples/lang-err-integration-tests/contract-ref/lib.rs | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 16683b64d4c..4878f2f5d59 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -233,7 +233,6 @@ pub struct CreateBuilder< /// ) /// .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) /// .returns::() -/// .params() /// .instantiate() /// .unwrap(); /// ``` @@ -268,8 +267,7 @@ pub struct CreateBuilder< /// ) /// .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) /// .returns::>() -/// .params() -/// .instantiate_fallible() +/// .instantiate() /// .unwrap() /// .unwrap(); /// ``` diff --git a/examples/lang-err-integration-tests/contract-ref/lib.rs b/examples/lang-err-integration-tests/contract-ref/lib.rs index 03ed299bce5..0061c9deed3 100755 --- a/examples/lang-err-integration-tests/contract-ref/lib.rs +++ b/examples/lang-err-integration-tests/contract-ref/lib.rs @@ -32,7 +32,7 @@ mod contract_ref { .endowment(0) .code_hash(flipper_code_hash) .salt_bytes(salt) - .instantiate_fallible() + .instantiate() .unwrap_or_else(|error| { panic!("Received an error from the Contracts pallet while instantiating Flipper {:?}", error) }) From 24f8e83ae839a1e99ac18476050e484a512f3da4 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 18 Jan 2023 11:23:59 +0000 Subject: [PATCH 098/206] Restore `returns` method --- crates/env/src/call/create_builder.rs | 6 +++--- .../ink/codegen/src/generator/as_dependency/contract_ref.rs | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 4878f2f5d59..8e18c51be63 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -274,14 +274,14 @@ pub struct CreateBuilder< /// /// Note the usage of the [`CreateBuilder::instantiate_fallible`] method. #[allow(clippy::type_complexity)] -pub fn build_create() -> CreateBuilder< +pub fn build_create() -> CreateBuilder< E, Unset, Unset, Unset, Unset>, Unset, - Set>, + Unset>, ContractRef, > where @@ -293,7 +293,7 @@ where endowment: Default::default(), exec_input: Default::default(), salt: Default::default(), - return_type: Set(Default::default()), + return_type: Default::default(), _phantom: Default::default(), } } 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 ab318ad6eb3..8f997cc3940 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -423,7 +423,7 @@ impl ContractRef<'_> { ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, Self, > { - ::ink::env::call::build_create::() + ::ink::env::call::build_create::() .exec_input( ::ink::env::call::ExecutionInput::new( ::ink::env::call::Selector::new([ #( #selector_bytes ),* ]) @@ -432,6 +432,7 @@ impl ContractRef<'_> { .push_arg(#input_bindings) )* ) + .returns::<#ret_type>() } ) } From 5fb57361a4eded436471206fbfda64bad2a65570 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 19 Jan 2023 11:15:54 +0000 Subject: [PATCH 099/206] Remove ContractReference Result impl --- crates/ink/src/reflect/contract.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/crates/ink/src/reflect/contract.rs b/crates/ink/src/reflect/contract.rs index a10da63ea24..3488980a3cf 100644 --- a/crates/ink/src/reflect/contract.rs +++ b/crates/ink/src/reflect/contract.rs @@ -177,19 +177,8 @@ pub trait ContractEnv { /// // are of the same type. /// const _: IsSameType<::Type> = /// >::new(); -/// const _: IsSameType< as ContractReference>::Type> = -/// >>::new(); /// ``` pub trait ContractReference { /// The generated contract reference type. type Type; } - -/// Blanket impl for [`ContractRef`] for mapping to the equivalent [`Result`] -/// type. Enables handling constructors which return a `Result`. -impl ContractReference for core::result::Result -where - C: ContractReference, -{ - type Type = core::result::Result<::Type, E>; -} From 167a21654b148155477c07ccd61ff4e01159e147 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 19 Jan 2023 18:16:49 +0000 Subject: [PATCH 100/206] WIP implementing ConstructorReturnType --- crates/env/src/api.rs | 6 +- crates/env/src/backend.rs | 6 +- crates/env/src/call/common.rs | 65 ------- crates/env/src/call/create_builder.rs | 171 ++++++++++++------ crates/env/src/call/mod.rs | 2 +- crates/env/src/engine/mod.rs | 18 +- crates/env/src/engine/off_chain/impls.rs | 6 +- .../generator/as_dependency/contract_ref.rs | 10 + .../constructors-return-value/lib.rs | 2 +- 9 files changed, 149 insertions(+), 137 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 63cdea2dece..9b99a79059e 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -21,10 +21,10 @@ use crate::{ TypedEnvBackend, }, call::{ - utils::InstantiateResult, Call, CallParams, CreateParams, + ConstructorReturnType, DelegateCall, FromAccountId, }, @@ -326,13 +326,13 @@ where pub fn instantiate_contract( params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult<>::Output>, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: ConstructorReturnType, ContractRef: FromAccountId, { ::on_instance(|instance| { diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index f2f1d1ac5f9..8531913938a 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -14,9 +14,9 @@ use crate::{ call::{ - utils::InstantiateResult, Call, CallParams, + ConstructorReturnType, CreateParams, DelegateCall, FromAccountId, @@ -445,13 +445,13 @@ pub trait TypedEnvBackend: EnvBackend { &mut self, params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult<>::Output>, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: ConstructorReturnType, ContractRef: FromAccountId; /// Terminates a smart contract. diff --git a/crates/env/src/call/common.rs b/crates/env/src/call/common.rs index 46a7e0cb23f..e1cc4171a2d 100644 --- a/crates/env/src/call/common.rs +++ b/crates/env/src/call/common.rs @@ -38,71 +38,6 @@ impl Default for ReturnType { } } -mod private { - /// Seals the implementation of `ConstructorReturnType`. - pub trait Sealed {} -} - -/// Guards against using invalid contract initializer types. -/// -/// # Note -/// -/// Currently the only allowed types are `()` and `Result<(), E>` -/// where `E` is some unspecified error type. -/// If the contract initializer returns `Result::Err` the utility -/// method that is used to initialize an ink! smart contract will -/// revert the state of the contract instantiation. -pub trait InstantiateResult: private::Sealed { - /// Is `true` if `Self` is `Result`. - const IS_RESULT: bool = false; - - /// Reflects the output type of the dispatchable ink! constructor. - type Output; - - /// The error type of the constructor return type. - type Error: scale::Decode; - - /// Construct a success value of the `Output` type. - fn ok(value: C) -> Self::Output; - - /// Construct an error value of the `Output` type. - fn err(err: Self::Error) -> Self::Output; -} - -impl private::Sealed for T {} - -impl InstantiateResult for C { - type Output = C; - type Error = (); - - fn ok(value: C) -> Self::Output { - value - } - - fn err(_err: Self::Error) -> Self::Output { - // todo! - unreachable!() - } -} - -impl InstantiateResult for core::result::Result -where - E: scale::Decode, -{ - const IS_RESULT: bool = true; - - type Output = core::result::Result; - type Error = E; - - fn ok(value: C) -> Self::Output { - Ok(value) - } - - fn err(err: Self::Error) -> Self::Output { - Err(err) - } -} - /// A parameter that has been set to some value. #[derive(Debug, Copy, Clone)] pub struct Set(pub T); diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 8e18c51be63..c117709733c 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -16,7 +16,6 @@ use crate::{ call::{ utils::{ EmptyArgumentList, - InstantiateResult, ReturnType, Set, Unset, @@ -52,9 +51,74 @@ where fn from_account_id(account_id: ::AccountId) -> Self; } +/// todo! +pub trait ConstructorReturnType { + /// Is `true` if `Self` is `Result`. + const IS_RESULT: bool = false; + + /// The type of the contract returned from a constructor. + /// If a constructor returns `Self`, then `Contract = Self` + /// If a constructor returns a `Result`, then `Contract = Self`. + type Contract; + + /// The actual return type of the constructor. + /// If a constructor returns `Self`, then `Output = Self` + /// If a constructor returns a `Result`, then `Output = Result`. + type Output; + + /// The error type of the constructor return type. + type Error: scale::Decode; + + /// Construct a success value of the `Output` type. + fn ok(value: C) -> Self::Output; + + /// Construct an error value of the `Output` type. + fn err(err: Self::Error) -> Self::Output; +} + +impl ConstructorReturnType for C +where + C: FromAccountId +{ + type Contract = C; + type Output = C; + type Error = (); + + fn ok(value: C) -> Self::Output { + value + } + + fn err(_err: Self::Error) -> Self::Output { + // todo! + unreachable!() + } +} + +impl ConstructorReturnType for core::result::Result +where + C: FromAccountId, + E: scale::Decode, +{ + const IS_RESULT: bool = true; + + type Contract = C; + type Output = core::result::Result; + type Error = E; + + fn ok(value: C) -> Self::Output { + Ok(value) + } + + fn err(err: Self::Error) -> Self::Output { + Err(err) + } +} + +// pub type InstantiateOutput = <>::Type as Instantiate + /// Builds up contract instantiations. #[derive(Debug)] -pub struct CreateParams +pub struct CreateParams where E: Environment, { @@ -70,11 +134,11 @@ where salt_bytes: Salt, /// The return type of the target contracts constructor method. _return_type: ReturnType, - /// Phantom for ContractRef: todo! - _contract_ref: PhantomData, + /// The type of the reference to the contract returned from the constructor. + _phantom: PhantomData ContractRef>, } -impl CreateParams +impl CreateParams where E: Environment, { @@ -111,7 +175,7 @@ where } } -impl CreateParams +impl CreateParams where E: Environment, Salt: AsRef<[u8]>, @@ -123,13 +187,13 @@ where } } -impl CreateParams +impl CreateParams where E: Environment, + ContractRef: FromAccountId, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, - ContractRef: FromAccountId, + R: ConstructorReturnType, { /// Instantiates the contract and returns its account ID back to the caller. /// @@ -140,7 +204,7 @@ where #[inline] pub fn instantiate( &self, - ) -> Result<>::Output, crate::Error> { + ) -> Result<>::Output, crate::Error> { crate::instantiate_contract(self).map(|inner| { inner.unwrap_or_else(|error| { panic!("Received a `LangError` while instantiating: {:?}", error) @@ -157,7 +221,7 @@ where pub fn try_instantiate( &self, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult<>::Output>, crate::Error, > { crate::instantiate_contract(self) @@ -167,13 +231,13 @@ where /// Builds up contract instantiations. pub struct CreateBuilder< E, + ContractRef, CodeHash, GasLimit, Endowment, Args, Salt, RetType, - ContractRef, > where E: Environment, { @@ -276,16 +340,17 @@ pub struct CreateBuilder< #[allow(clippy::type_complexity)] pub fn build_create() -> CreateBuilder< E, + ContractRef, Unset, Unset, Unset, Unset>, Unset, Unset>, - ContractRef, > where E: Environment, + ContractRef: FromAccountId, { CreateBuilder { code_hash: Default::default(), @@ -298,16 +363,16 @@ where } } -impl +impl CreateBuilder< E, + ContractRef, Unset, GasLimit, Endowment, Args, Salt, - RetType, - ContractRef, + RetType > where E: Environment, @@ -319,13 +384,13 @@ where code_hash: E::Hash, ) -> CreateBuilder< E, + ContractRef, Set, GasLimit, Endowment, Args, Salt, - RetType, - ContractRef, + RetType > { CreateBuilder { code_hash: Set(code_hash), @@ -339,8 +404,8 @@ where } } -impl - CreateBuilder, Endowment, Args, Salt, RetType, ContractRef> +impl + CreateBuilder, Endowment, Args, Salt, RetType> where E: Environment, { @@ -349,7 +414,7 @@ where pub fn gas_limit( self, gas_limit: u64, - ) -> CreateBuilder, Endowment, Args, Salt, RetType, ContractRef> + ) -> CreateBuilder, Endowment, Args, Salt, RetType> { CreateBuilder { code_hash: self.code_hash, @@ -363,16 +428,16 @@ where } } -impl +impl CreateBuilder< E, + ContractRef, CodeHash, GasLimit, Unset, Args, Salt, - RetType, - ContractRef, + RetType > where E: Environment, @@ -384,13 +449,13 @@ where endowment: E::Balance, ) -> CreateBuilder< E, + ContractRef, CodeHash, GasLimit, Set, Args, Salt, - RetType, - ContractRef, + RetType > { CreateBuilder { code_hash: self.code_hash, @@ -404,16 +469,16 @@ where } } -impl +impl CreateBuilder< E, + ContractRef, CodeHash, GasLimit, Endowment, Unset>, Salt, - RetType, - ContractRef, + RetType > where E: Environment, @@ -425,13 +490,13 @@ where exec_input: ExecutionInput, ) -> CreateBuilder< E, + ContractRef, CodeHash, GasLimit, Endowment, Set>, Salt, - RetType, - ContractRef, + RetType > { CreateBuilder { code_hash: self.code_hash, @@ -445,16 +510,16 @@ where } } -impl +impl CreateBuilder< E, + ContractRef, CodeHash, GasLimit, Endowment, Args, Unset, - RetType, - ContractRef, + RetType > where E: Environment, @@ -466,13 +531,13 @@ where salt: Salt, ) -> CreateBuilder< E, + ContractRef, CodeHash, GasLimit, Endowment, Args, Set, - RetType, - ContractRef, + RetType > where Salt: AsRef<[u8]>, @@ -489,16 +554,16 @@ where } } -impl +impl CreateBuilder< E, + ContractRef, CodeHash, GasLimit, Endowment, Args, Salt, Unset>, - ContractRef, > where E: Environment, @@ -517,14 +582,18 @@ where self, ) -> CreateBuilder< E, + ContractRef, CodeHash, GasLimit, Endowment, Args, Salt, - Set>, - ContractRef, - > { + Set> + > + where + ContractRef: FromAccountId, + R: ConstructorReturnType, + { CreateBuilder { code_hash: self.code_hash, gas_limit: self.gas_limit, @@ -537,16 +606,16 @@ where } } -impl +impl CreateBuilder< E, + ContractRef, Set, GasLimit, Set, Set>, Set, Set>, - ContractRef, > where E: Environment, @@ -554,7 +623,7 @@ where { /// Finalizes the create builder, allowing it to instantiate a contract. #[inline] - pub fn params(self) -> CreateParams { + pub fn params(self) -> CreateParams { CreateParams { code_hash: self.code_hash.value(), gas_limit: self.gas_limit.unwrap_or_else(|| 0), @@ -562,29 +631,29 @@ where exec_input: self.exec_input.value(), salt_bytes: self.salt.value(), _return_type: Default::default(), - _contract_ref: Default::default(), + _phantom: Default::default(), } } } -impl +impl CreateBuilder< E, + ContractRef, Set, GasLimit, Set, Set>, Set, Set>, - ContractRef, > where E: Environment, + ContractRef: FromAccountId, GasLimit: Unwrap, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType: InstantiateResult, - ContractRef: FromAccountId, + RetType: ConstructorReturnType, { /// Instantiates the contract using the given instantiation parameters. /// @@ -595,7 +664,7 @@ where #[inline] pub fn instantiate( self, - ) -> Result<>::Output, Error> { + ) -> Result<>::Output, Error> { self.params().instantiate() } @@ -609,7 +678,7 @@ where self, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, Error, > { diff --git a/crates/env/src/call/mod.rs b/crates/env/src/call/mod.rs index 971d0cc4d15..7d170eab2ab 100644 --- a/crates/env/src/call/mod.rs +++ b/crates/env/src/call/mod.rs @@ -24,7 +24,6 @@ mod selector; pub mod utils { pub use super::{ common::{ - InstantiateResult, ReturnType, Set, Unset, @@ -54,6 +53,7 @@ pub use self::{ CreateBuilder, CreateParams, FromAccountId, + ConstructorReturnType, }, execution_input::ExecutionInput, selector::Selector, diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index a89d2692c0a..fe08c6a1544 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -17,10 +17,7 @@ use crate::{ EnvBackend, TypedEnvBackend, }, - call::{ - utils::InstantiateResult, - FromAccountId, - }, + call::FromAccountId, Error as EnvError, Error, Result as EnvResult, @@ -30,6 +27,7 @@ use ink_primitives::{ ConstructorResult, LangError, }; +use crate::call::ConstructorReturnType; pub trait OnInstance: EnvBackend + TypedEnvBackend { fn on_instance(f: F) -> R @@ -57,11 +55,11 @@ pub(crate) fn decode_instantiate_result( instantiate_result: EnvResult<()>, out_address: &mut I, out_return_value: &mut I, -) -> EnvResult>::Output>> +) -> EnvResult>::Output>> where I: scale::Input, E: crate::Environment, - R: InstantiateResult, + R: ConstructorReturnType, ContractRef: FromAccountId, { match instantiate_result { @@ -69,7 +67,7 @@ where let account_id = scale::Decode::decode(out_address)?; let contract_ref = >::from_account_id(account_id); - let output = >::ok(contract_ref); + let output = >::ok(contract_ref); Ok(Ok(output)) } Err(EnvError::CalleeReverted) => { @@ -77,16 +75,16 @@ where match constructor_result_variant { // 0 == `ConstructorResult::Ok` variant 0 => { - if >::IS_RESULT { + if >::IS_RESULT { let result_variant = out_return_value.read_byte()?; match result_variant { // 0 == `Ok` variant 0 => panic!("The callee reverted, but did not encode an error in the output buffer."), // 1 == `Err` variant 1 => { - let contract_err = <>::Error + let contract_err = <>::Error as scale::Decode>::decode(out_return_value)?; - let err = >::err(contract_err); + let err = >::err(contract_err); Ok(Ok(err)) } _ => Err(Error::Decode("Invalid inner constructor Result encoding, expected 0 or 1 as the first byte".into())) diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index ce958c3b3a5..5f9da93b512 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -15,9 +15,9 @@ use super::EnvInstance; use crate::{ call::{ - utils::InstantiateResult, Call, CallParams, + ConstructorReturnType, CreateParams, DelegateCall, FromAccountId, @@ -475,13 +475,13 @@ impl TypedEnvBackend for EnvInstance { &mut self, params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult<>::Output>, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: ConstructorReturnType, ContractRef: FromAccountId, { let _code_hash = params.code_hash(); 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 8f997cc3940..854c5773d63 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -109,6 +109,16 @@ impl ContractRef<'_> { type Type = #ref_ident; } + impl ::ink::env::call::ConstructorReturnType for #storage_ident { + type ContractRef = #ref_ident; + type Type = #ref_ident; + } + + impl ::ink::env::call::ConstructorReturnType for ::core::result::Result<#storage_ident, E> { + type ContractRef = #ref_ident; + type Type = ::core::result::Result<#ref_ident, E>; + } + impl ::ink::reflect::ContractEnv for #ref_ident { type Env = <#storage_ident as ::ink::reflect::ContractEnv>::Env; } 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 6c70e3eaa32..9cc69fa32ec 100644 --- a/examples/lang-err-integration-tests/constructors-return-value/lib.rs +++ b/examples/lang-err-integration-tests/constructors-return-value/lib.rs @@ -26,7 +26,7 @@ pub mod constructors_return_value { /// Fallible constructor #[ink(constructor)] - pub fn try_new(succeed: bool) -> Result { + pub fn try_new(succeed: bool) -> Result { if succeed { Ok(Self::new(true)) } else { From ac70452c41368abd6ac6d7c2da3bdcee23c7fd8b Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 19 Jan 2023 21:16:01 +0000 Subject: [PATCH 101/206] Reorder ContractRef parameter, move ContractRef and ContractEnv trait to env crate --- crates/env/Cargo.toml | 3 + crates/env/src/api.rs | 8 +- crates/env/src/backend.rs | 8 +- crates/env/src/call/create_builder.rs | 11 +- crates/env/src/contract.rs | 134 +++++++++++++++++ crates/env/src/engine/mod.rs | 26 ++-- crates/env/src/engine/off_chain/impls.rs | 6 +- crates/env/src/lib.rs | 5 + .../generator/as_dependency/call_builder.rs | 4 +- .../generator/as_dependency/contract_ref.rs | 18 +-- crates/ink/codegen/src/generator/dispatch.rs | 14 +- crates/ink/codegen/src/generator/env.rs | 14 +- crates/ink/codegen/src/generator/events.rs | 2 +- .../ink/codegen/src/generator/item_impls.rs | 4 +- crates/ink/codegen/src/generator/metadata.rs | 4 +- crates/ink/codegen/src/generator/storage.rs | 4 +- .../src/generator/trait_def/call_builder.rs | 2 +- .../src/generator/trait_def/call_forwarder.rs | 2 +- .../src/generator/trait_def/definition.rs | 2 +- crates/ink/src/env_access.rs | 14 +- crates/ink/src/reflect/contract.rs | 137 +----------------- crates/ink/src/reflect/mod.rs | 6 +- crates/ink/src/reflect/trait_def/registry.rs | 2 +- .../ui/trait_def/pass/using-env-types.rs | 2 +- examples/multisig/lib.rs | 4 +- 25 files changed, 218 insertions(+), 218 deletions(-) create mode 100644 crates/env/src/contract.rs diff --git a/crates/env/Cargo.toml b/crates/env/Cargo.toml index c6ef99cf836..bacc9ba4af4 100644 --- a/crates/env/Cargo.toml +++ b/crates/env/Cargo.toml @@ -49,6 +49,9 @@ secp256k1 = { version = "0.26.0", features = ["recovery", "global-context"], opt # Never use this crate outside the off-chain environment! scale-info = { version = "2.3", default-features = false, features = ["derive"], optional = true } +[dev-dependencies] +ink = { path = "../ink" } + [features] default = ["std"] std = [ diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 9b99a79059e..7c1bd969a8e 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -323,20 +323,20 @@ where /// - If the instantiation process runs out of gas. /// - If given insufficient endowment. /// - If the returned account ID failed to decode properly. -pub fn instantiate_contract( - params: &CreateParams, +pub fn instantiate_contract( + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult<>::Output>, > where E: Environment, + ContractRef: FromAccountId, Args: scale::Encode, Salt: AsRef<[u8]>, R: ConstructorReturnType, - ContractRef: FromAccountId, { ::on_instance(|instance| { - TypedEnvBackend::instantiate_contract::( + TypedEnvBackend::instantiate_contract::( instance, params, ) }) diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 8531913938a..8db8fe9acdb 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -441,18 +441,18 @@ pub trait TypedEnvBackend: EnvBackend { /// # Note /// /// For more details visit: [`instantiate_contract`][`crate::instantiate_contract`] - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult<>::Output>, > where E: Environment, + ContractRef: FromAccountId, Args: scale::Encode, Salt: AsRef<[u8]>, - R: ConstructorReturnType, - ContractRef: FromAccountId; + R: ConstructorReturnType; /// Terminates a smart contract. /// diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index c117709733c..28a3e13e37f 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -24,6 +24,7 @@ use crate::{ ExecutionInput, Selector, }, + ContractEnv, Environment, Error, }; @@ -76,9 +77,9 @@ pub trait ConstructorReturnType { fn err(err: Self::Error) -> Self::Output; } -impl ConstructorReturnType for C +impl ConstructorReturnType for C where - C: FromAccountId + C: ContractEnv + FromAccountId<::Env> { type Contract = C; type Output = C; @@ -94,9 +95,9 @@ where } } -impl ConstructorReturnType for core::result::Result +impl ConstructorReturnType for core::result::Result where - C: FromAccountId, + C: ContractEnv + FromAccountId<::Env>, E: scale::Decode, { const IS_RESULT: bool = true; @@ -591,7 +592,7 @@ where Set> > where - ContractRef: FromAccountId, + ContractRef: FromAccountId, R: ConstructorReturnType, { CreateBuilder { diff --git a/crates/env/src/contract.rs b/crates/env/src/contract.rs new file mode 100644 index 00000000000..9a7b168da02 --- /dev/null +++ b/crates/env/src/contract.rs @@ -0,0 +1,134 @@ +/// Stores the used host environment type of the ink! smart contract. +/// +/// # Note +/// +/// The used host environment can be altered using the `env` configuration +/// parameter in the `#[ink::contract]` parameters. For example if the user +/// wanted to use an environment type definition called `MyEnvironment` they +/// issue the ink! smart contract as follows: +/// +/// ```no_compile +/// #[ink::contract(env = MyEnvironment)] +/// ``` +/// +/// # Usage: Default Environment +/// +/// ``` +/// +/// #[ink::contract] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor() -> Self { Self {} } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// +/// use contract::Contract; +/// +/// # use ink::env::ContractEnv; +/// # use ink::codegen::utils::IsSameType; +/// +/// // The following line only compiles successfully if both +/// // `ink_env::DefaultEnvironment` and `::Env` +/// // are of the same type. +/// const _: IsSameType<::Env> = +/// >::new(); +/// ``` +/// +/// # Usage: Custom Environment +/// +/// ``` +/// # use ink_env::{Environment, DefaultEnvironment}; +/// +/// pub struct CustomEnvironment {} +/// +/// impl Environment for CustomEnvironment { +/// const MAX_EVENT_TOPICS: usize = 4; +/// +/// type AccountId = ::AccountId; +/// type Balance = u64; +/// type Hash = ::Hash; +/// type BlockNumber = u32; +/// type Timestamp = u64; +/// type ChainExtension = ::ChainExtension; +/// } +/// +/// #[ink::contract(env = super::CustomEnvironment)] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor() -> Self { Self {} } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// +/// use contract::Contract; +/// # use ink::env::ContractEnv; +/// # use ink::codegen::utils::IsSameType; +/// +/// // The following line only compiles successfully if both +/// // `CustomEnvironment` and `::Env` +/// // are of the same type. +/// const _: IsSameType<::Env> = +/// >::new(); +/// +/// fn main() {} +/// ``` +pub trait ContractEnv { + /// The environment type. + type Env: crate::Environment; +} + +/// Refers to the generated ink! smart contract reference type. +/// +/// # Note +/// +/// Given an ink! storage struct with identifier `Contract` the ink! codegen produces +/// the ink! root type `Contract` and the ink! reference type `ContractRef`. +/// +/// This trait exists so that users can avoid using a generated identifier to refer to +/// the generated reference type of the ink! smart contract. +/// +/// # Usage +/// +/// ``` +/// +/// #[ink::contract] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor() -> Self { Self {} } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// +/// use contract::{Contract, ContractRef}; +/// # use ink::codegen::utils::IsSameType; +/// # use ink::env::ContractReference; +/// +/// // The following line only compiles successfully if both +/// // `ContractReference` and `::Type` +/// // are of the same type. +/// const _: IsSameType<::Type> = +/// >::new(); +/// ``` +pub trait ContractReference { + /// The generated contract reference type. + type Type; +} \ No newline at end of file diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index fe08c6a1544..8baf2dcb004 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -51,7 +51,7 @@ cfg_if! { // We only use this function when 1) compiling to Wasm 2) compiling for tests. #[cfg_attr(all(feature = "std", not(test)), allow(dead_code))] -pub(crate) fn decode_instantiate_result( +pub(crate) fn decode_instantiate_result( instantiate_result: EnvResult<()>, out_address: &mut I, out_return_value: &mut I, @@ -59,8 +59,8 @@ pub(crate) fn decode_instantiate_result( where I: scale::Input, E: crate::Environment, - R: ConstructorReturnType, ContractRef: FromAccountId, + R: ConstructorReturnType, { match instantiate_result { Ok(()) => { @@ -109,6 +109,7 @@ where mod decode_instantiate_result_tests { use super::*; use crate::{ + DefaultEnvironment, Environment, Error, }; @@ -120,10 +121,15 @@ mod decode_instantiate_result_tests { #[derive(scale::Encode, scale::Decode)] struct ContractError(String); - struct TestContractRef(::AccountId); + type AccountId = ::AccountId; + struct TestContractRef(AccountId); + + impl crate::ContractEnv for TestContractRef { + type Env = DefaultEnvironment; + } - impl FromAccountId for TestContractRef { - fn from_account_id(account_id: ::AccountId) -> Self { + impl FromAccountId for TestContractRef { + fn from_account_id(account_id: AccountId) -> Self { Self(account_id) } } @@ -132,7 +138,7 @@ mod decode_instantiate_result_tests { return_value: ConstructorResult>, ) -> EnvResult< ConstructorResult< - Result, ContractError>, + Result, >, > { let out_address = Vec::new(); @@ -148,14 +154,14 @@ mod decode_instantiate_result_tests { out_return_value: &mut I, ) -> EnvResult< ConstructorResult< - Result, ContractError>, + Result, >, > { decode_instantiate_result::< I, - crate::DefaultEnvironment, - Result, ContractError>, - TestContractRef, + DefaultEnvironment, + TestContractRef, + Result, >(Err(Error::CalleeReverted), out_address, out_return_value) } diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 5f9da93b512..979d6894d8c 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -471,18 +471,18 @@ impl TypedEnvBackend for EnvInstance { ) } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult<>::Output>, > where E: Environment, + ContractRef: FromAccountId, Args: scale::Encode, Salt: AsRef<[u8]>, R: ConstructorReturnType, - ContractRef: FromAccountId, { let _code_hash = params.code_hash(); let _gas_limit = params.gas_limit(); diff --git a/crates/env/src/lib.rs b/crates/env/src/lib.rs index e9d9be7dcf1..2c56eba77fe 100644 --- a/crates/env/src/lib.rs +++ b/crates/env/src/lib.rs @@ -73,6 +73,7 @@ mod arithmetic; mod backend; pub mod call; pub mod chain_extension; +mod contract; mod engine; mod error; pub mod hash; @@ -97,6 +98,10 @@ pub use self::{ CallFlags, ReturnFlags, }, + contract::{ + ContractEnv, + ContractReference, + }, error::{ Error, Result, 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..65c8d11a977 100644 --- a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs @@ -104,8 +104,8 @@ impl CallBuilder<'_> { type Type = #cb_ident; } - impl ::ink::reflect::ContractEnv for #cb_ident { - type Env = <#storage_ident as ::ink::reflect::ContractEnv>::Env; + impl ::ink::env::ContractEnv for #cb_ident { + type Env = <#storage_ident as ::ink::env::ContractEnv>::Env; } }; ) 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 854c5773d63..61da16201b7 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -105,22 +105,12 @@ impl ContractRef<'_> { } const _: () = { - impl ::ink::reflect::ContractReference for #storage_ident { + impl ::ink::env::ContractReference for #storage_ident { type Type = #ref_ident; } - impl ::ink::env::call::ConstructorReturnType for #storage_ident { - type ContractRef = #ref_ident; - type Type = #ref_ident; - } - - impl ::ink::env::call::ConstructorReturnType for ::core::result::Result<#storage_ident, E> { - type ContractRef = #ref_ident; - type Type = ::core::result::Result<#ref_ident, E>; - } - - impl ::ink::reflect::ContractEnv for #ref_ident { - type Env = <#storage_ident as ::ink::reflect::ContractEnv>::Env; + impl ::ink::env::ContractEnv for #ref_ident { + type Env = <#storage_ident as ::ink::env::ContractEnv>::Env; } }; ) @@ -425,13 +415,13 @@ impl ContractRef<'_> { #( #input_bindings : #input_types ),* ) -> ::ink::env::call::CreateBuilder< Environment, + Self, ::ink::env::call::utils::Unset, ::ink::env::call::utils::Unset, ::ink::env::call::utils::Unset, ::ink::env::call::utils::Set<::ink::env::call::ExecutionInput<#arg_list>>, ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, - Self, > { ::ink::env::call::build_create::() .exec_input( diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index 4246d982103..e7c896dcc43 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -171,7 +171,7 @@ impl Dispatch<'_> { quote_spanned!(span=> { ::core::primitive::u32::from_be_bytes( - <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::reflect::ContractEnv>::Env> + <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::env::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink::reflect::TraitMessageInfo<#local_id>>::SELECTOR ) @@ -352,12 +352,12 @@ impl Dispatch<'_> { let mutates = message.receiver().is_ref_mut(); let local_id = message.local_id().hex_padded_suffixed(); let payable = quote! {{ - <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::reflect::ContractEnv>::Env> + <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::env::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink::reflect::TraitMessageInfo<#local_id>>::PAYABLE }}; let selector = quote! {{ - <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::reflect::ContractEnv>::Env> + <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::env::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink::reflect::TraitMessageInfo<#local_id>>::SELECTOR }}; @@ -416,7 +416,7 @@ impl Dispatch<'_> { #[allow(clippy::nonminimal_bool)] fn deploy() { if !#any_constructor_accept_payment { - ::ink::codegen::deny_payment::<<#storage_ident as ::ink::reflect::ContractEnv>::Env>() + ::ink::codegen::deny_payment::<<#storage_ident as ::ink::env::ContractEnv>::Env>() .unwrap_or_else(|error| ::core::panic!("{}", error)) } @@ -454,7 +454,7 @@ impl Dispatch<'_> { #[allow(clippy::nonminimal_bool)] fn call() { if !#any_message_accept_payment { - ::ink::codegen::deny_payment::<<#storage_ident as ::ink::reflect::ContractEnv>::Env>() + ::ink::codegen::deny_payment::<<#storage_ident as ::ink::env::ContractEnv>::Env>() .unwrap_or_else(|error| ::core::panic!("{}", error)) } @@ -618,7 +618,7 @@ impl Dispatch<'_> { Self::#constructor_ident(input) => { if #any_constructor_accept_payment && #deny_payment { ::ink::codegen::deny_payment::< - <#storage_ident as ::ink::reflect::ContractEnv>::Env>()?; + <#storage_ident as ::ink::env::ContractEnv>::Env>()?; } let result: #constructor_output = #constructor_callable(input); @@ -822,7 +822,7 @@ impl Dispatch<'_> { Self::#message_ident(input) => { if #any_message_accept_payment && #deny_payment { ::ink::codegen::deny_payment::< - <#storage_ident as ::ink::reflect::ContractEnv>::Env>()?; + <#storage_ident as ::ink::env::ContractEnv>::Env>()?; } let result: #message_output = #message_callable(&mut contract, input); diff --git a/crates/ink/codegen/src/generator/env.rs b/crates/ink/codegen/src/generator/env.rs index a9ebd428731..31361cd9cbd 100644 --- a/crates/ink/codegen/src/generator/env.rs +++ b/crates/ink/codegen/src/generator/env.rs @@ -28,17 +28,17 @@ impl GenerateCode for Env<'_> { let env = self.contract.config().env(); let storage_ident = self.contract.module().storage().ident(); quote! { - impl ::ink::reflect::ContractEnv for #storage_ident { + impl ::ink::env::ContractEnv for #storage_ident { type Env = #env; } - type Environment = <#storage_ident as ::ink::reflect::ContractEnv>::Env; + type Environment = <#storage_ident as ::ink::env::ContractEnv>::Env; - type AccountId = <<#storage_ident as ::ink::reflect::ContractEnv>::Env as ::ink::env::Environment>::AccountId; - type Balance = <<#storage_ident as ::ink::reflect::ContractEnv>::Env as ::ink::env::Environment>::Balance; - type Hash = <<#storage_ident as ::ink::reflect::ContractEnv>::Env as ::ink::env::Environment>::Hash; - type Timestamp = <<#storage_ident as ::ink::reflect::ContractEnv>::Env as ::ink::env::Environment>::Timestamp; - type BlockNumber = <<#storage_ident as ::ink::reflect::ContractEnv>::Env as ::ink::env::Environment>::BlockNumber; + type AccountId = <<#storage_ident as ::ink::env::ContractEnv>::Env as ::ink::env::Environment>::AccountId; + type Balance = <<#storage_ident as ::ink::env::ContractEnv>::Env as ::ink::env::Environment>::Balance; + type Hash = <<#storage_ident as ::ink::env::ContractEnv>::Env as ::ink::env::Environment>::Hash; + type Timestamp = <<#storage_ident as ::ink::env::ContractEnv>::Env as ::ink::env::Environment>::Timestamp; + type BlockNumber = <<#storage_ident as ::ink::env::ContractEnv>::Env as ::ink::env::Environment>::BlockNumber; } } } diff --git a/crates/ink/codegen/src/generator/events.rs b/crates/ink/codegen/src/generator/events.rs index 62344eab8fb..1dd1613b49d 100644 --- a/crates/ink/codegen/src/generator/events.rs +++ b/crates/ink/codegen/src/generator/events.rs @@ -153,7 +153,7 @@ impl<'a> Events<'a> { let event_ident = event.ident(); let len_topics = event.fields().filter(|event| event.is_topic).count(); let max_len_topics = quote_spanned!(span=> - <<#storage_ident as ::ink::reflect::ContractEnv>::Env + <<#storage_ident as ::ink::env::ContractEnv>::Env as ::ink::env::Environment>::MAX_EVENT_TOPICS ); quote_spanned!(span=> diff --git a/crates/ink/codegen/src/generator/item_impls.rs b/crates/ink/codegen/src/generator/item_impls.rs index 673c6fe9779..819d452bd4d 100644 --- a/crates/ink/codegen/src/generator/item_impls.rs +++ b/crates/ink/codegen/src/generator/item_impls.rs @@ -91,7 +91,7 @@ impl ItemImpls<'_> { let message_guard_payable = message.is_payable().then(|| { quote_spanned!(message_span=> const _: ::ink::codegen::TraitMessagePayable<{ - <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::reflect::ContractEnv>::Env> + <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::env::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink::reflect::TraitMessageInfo<#message_local_id>>::PAYABLE }> = ::ink::codegen::TraitMessagePayable::; @@ -102,7 +102,7 @@ impl ItemImpls<'_> { quote_spanned!(message_span=> const _: ::ink::codegen::TraitMessageSelector<{ ::core::primitive::u32::from_be_bytes( - <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::reflect::ContractEnv>::Env> + <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::env::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink::reflect::TraitMessageInfo<#message_local_id>>::SELECTOR ) diff --git a/crates/ink/codegen/src/generator/metadata.rs b/crates/ink/codegen/src/generator/metadata.rs index 57e1b03a16f..717f0c35705 100644 --- a/crates/ink/codegen/src/generator/metadata.rs +++ b/crates/ink/codegen/src/generator/metadata.rs @@ -288,12 +288,12 @@ impl Metadata<'_> { let mutates = message.receiver().is_ref_mut(); let local_id = message.local_id().hex_padded_suffixed(); let is_payable = quote! {{ - <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::reflect::ContractEnv>::Env> + <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::env::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink::reflect::TraitMessageInfo<#local_id>>::PAYABLE }}; let selector = quote! {{ - <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::reflect::ContractEnv>::Env> + <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::env::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink::reflect::TraitMessageInfo<#local_id>>::SELECTOR }}; diff --git a/crates/ink/codegen/src/generator/storage.rs b/crates/ink/codegen/src/generator/storage.rs index dcc38a3b0f5..90d05f970b3 100644 --- a/crates/ink/codegen/src/generator/storage.rs +++ b/crates/ink/codegen/src/generator/storage.rs @@ -62,7 +62,7 @@ impl Storage<'_> { const _: () = { impl<'a> ::ink::codegen::Env for &'a #storage_ident { type EnvAccess = ::ink::EnvAccess< - 'a, <#storage_ident as ::ink::reflect::ContractEnv>::Env>; + 'a, <#storage_ident as ::ink::env::ContractEnv>::Env>; fn env(self) -> Self::EnvAccess { <::EnvAccess @@ -72,7 +72,7 @@ impl Storage<'_> { impl<'a> ::ink::codegen::StaticEnv for #storage_ident { type EnvAccess = ::ink::EnvAccess< - 'static, <#storage_ident as ::ink::reflect::ContractEnv>::Env>; + 'static, <#storage_ident as ::ink::env::ContractEnv>::Env>; fn env() -> Self::EnvAccess { <::EnvAccess diff --git a/crates/ink/codegen/src/generator/trait_def/call_builder.rs b/crates/ink/codegen/src/generator/trait_def/call_builder.rs index 4cfa4a716b7..34221367b36 100644 --- a/crates/ink/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/ink/codegen/src/generator/trait_def/call_builder.rs @@ -247,7 +247,7 @@ impl CallBuilder<'_> { let builder_ident = self.ident(); let message_impls = self.generate_ink_trait_impl_messages(); quote_spanned!(span=> - impl ::ink::reflect::ContractEnv for #builder_ident + impl ::ink::env::ContractEnv for #builder_ident where E: ::ink::env::Environment, { diff --git a/crates/ink/codegen/src/generator/trait_def/call_forwarder.rs b/crates/ink/codegen/src/generator/trait_def/call_forwarder.rs index d2828712aa7..b910f80568f 100644 --- a/crates/ink/codegen/src/generator/trait_def/call_forwarder.rs +++ b/crates/ink/codegen/src/generator/trait_def/call_forwarder.rs @@ -274,7 +274,7 @@ impl CallForwarder<'_> { let forwarder_ident = self.ident(); let message_impls = self.generate_ink_trait_impl_messages(); quote_spanned!(span=> - impl ::ink::reflect::ContractEnv for #forwarder_ident + impl ::ink::env::ContractEnv for #forwarder_ident where E: ::ink::env::Environment, { diff --git a/crates/ink/codegen/src/generator/trait_def/definition.rs b/crates/ink/codegen/src/generator/trait_def/definition.rs index f29de733f72..ea50c1b6d92 100644 --- a/crates/ink/codegen/src/generator/trait_def/definition.rs +++ b/crates/ink/codegen/src/generator/trait_def/definition.rs @@ -59,7 +59,7 @@ impl TraitDefinition<'_> { .map(Self::generate_for_message); quote_spanned!(span => #(#attrs)* - pub trait #ident: ::ink::reflect::ContractEnv { + pub trait #ident: ::ink::env::ContractEnv { /// Holds general and global information about the trait. #[doc(hidden)] #[allow(non_camel_case_types)] diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 66d4b15c043..2b2e8cb758a 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -16,10 +16,10 @@ use crate::ChainExtensionInstance; use core::marker::PhantomData; use ink_env::{ call::{ - utils::InstantiateResult, Call, CallParams, CreateParams, + ConstructorReturnType, DelegateCall, FromAccountId, }, @@ -480,19 +480,19 @@ where /// # Note /// /// For more details visit: [`ink_env::instantiate_contract`] - pub fn instantiate_contract( + pub fn instantiate_contract( self, - params: &CreateParams, + params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult<>::Output>, > where + ContractRef: FromAccountId, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, - ContractRef: FromAccountId, + R: ConstructorReturnType, { - ink_env::instantiate_contract::(params) + ink_env::instantiate_contract::(params) } /// Invokes a contract message and returns its result. diff --git a/crates/ink/src/reflect/contract.rs b/crates/ink/src/reflect/contract.rs index 3488980a3cf..2e5854c4d74 100644 --- a/crates/ink/src/reflect/contract.rs +++ b/crates/ink/src/reflect/contract.rs @@ -46,139 +46,4 @@ pub trait ContractName { /// The name of the ink! smart contract. const NAME: &'static str; -} - -/// Stores the used host environment type of the ink! smart contract. -/// -/// # Note -/// -/// The used host environment can be altered using the `env` configuration -/// parameter in the `#[ink::contract]` parameters. For example if the user -/// wanted to use an environment type definition called `MyEnvironment` they -/// issue the ink! smart contract as follows: -/// -/// ```no_compile -/// #[ink::contract(env = MyEnvironment)] -/// ``` -/// -/// # Usage: Default Environment -/// -/// ``` -/// -/// #[ink::contract] -/// pub mod contract { -/// #[ink(storage)] -/// pub struct Contract {} -/// -/// impl Contract { -/// #[ink(constructor)] -/// pub fn constructor() -> Self { Self {} } -/// -/// #[ink(message)] -/// pub fn message(&self) {} -/// } -/// } -/// -/// use contract::Contract; -/// -/// # use ink::reflect::ContractEnv; -/// # use ink::codegen::utils::IsSameType; -/// -/// // The following line only compiles successfully if both -/// // `ink_env::DefaultEnvironment` and `::Env` -/// // are of the same type. -/// const _: IsSameType<::Env> = -/// >::new(); -/// ``` -/// -/// # Usage: Custom Environment -/// -/// ``` -/// # use ink_env::{Environment, DefaultEnvironment}; -/// -/// pub struct CustomEnvironment {} -/// -/// impl Environment for CustomEnvironment { -/// const MAX_EVENT_TOPICS: usize = 4; -/// -/// type AccountId = ::AccountId; -/// type Balance = u64; -/// type Hash = ::Hash; -/// type BlockNumber = u32; -/// type Timestamp = u64; -/// type ChainExtension = ::ChainExtension; -/// } -/// -/// #[ink::contract(env = super::CustomEnvironment)] -/// pub mod contract { -/// #[ink(storage)] -/// pub struct Contract {} -/// -/// impl Contract { -/// #[ink(constructor)] -/// pub fn constructor() -> Self { Self {} } -/// -/// #[ink(message)] -/// pub fn message(&self) {} -/// } -/// } -/// -/// use contract::Contract; -/// # use ink::reflect::ContractEnv; -/// # use ink::codegen::utils::IsSameType; -/// -/// // The following line only compiles successfully if both -/// // `CustomEnvironment` and `::Env` -/// // are of the same type. -/// const _: IsSameType<::Env> = -/// >::new(); -/// -/// fn main() {} -/// ``` -pub trait ContractEnv { - /// The environment type. - type Env: ::ink_env::Environment; -} - -/// Refers to the generated ink! smart contract reference type. -/// -/// # Note -/// -/// Given an ink! storage struct with identifier `Contract` the ink! codegen produces -/// the ink! root type `Contract` and the ink! reference type `ContractRef`. -/// -/// This trait exists so that users can avoid using a generated identifier to refer to -/// the generated reference type of the ink! smart contract. -/// -/// # Usage -/// -/// ``` -/// -/// #[ink::contract] -/// pub mod contract { -/// #[ink(storage)] -/// pub struct Contract {} -/// -/// impl Contract { -/// #[ink(constructor)] -/// pub fn constructor() -> Self { Self {} } -/// -/// #[ink(message)] -/// pub fn message(&self) {} -/// } -/// } -/// -/// use contract::{Contract, ContractRef}; -/// # use ink::codegen::utils::IsSameType; -/// # use ink::reflect::ContractReference; -/// -/// // The following line only compiles successfully if both -/// // `ContractReference` and `::Type` -/// // are of the same type. -/// const _: IsSameType<::Type> = -/// >::new(); -/// ``` -pub trait ContractReference { - /// The generated contract reference type. - type Type; -} +} \ No newline at end of file diff --git a/crates/ink/src/reflect/mod.rs b/crates/ink/src/reflect/mod.rs index 65f15f2e6db..0ebdb294f24 100644 --- a/crates/ink/src/reflect/mod.rs +++ b/crates/ink/src/reflect/mod.rs @@ -29,11 +29,7 @@ mod event; mod trait_def; pub use self::{ - contract::{ - ContractEnv, - ContractName, - ContractReference, - }, + contract::ContractName, dispatch::{ ConstructorOutput, ConstructorOutputValue, diff --git a/crates/ink/src/reflect/trait_def/registry.rs b/crates/ink/src/reflect/trait_def/registry.rs index 005d8eb1cc4..75044073f33 100644 --- a/crates/ink/src/reflect/trait_def/registry.rs +++ b/crates/ink/src/reflect/trait_def/registry.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::reflect::ContractEnv; +use ink_env::ContractEnv; use core::marker::PhantomData; /// Type that is guaranteed by ink! to implement all ink! trait definitions. diff --git a/crates/ink/tests/ui/trait_def/pass/using-env-types.rs b/crates/ink/tests/ui/trait_def/pass/using-env-types.rs index 2822af913e4..e1f913f3099 100644 --- a/crates/ink/tests/ui/trait_def/pass/using-env-types.rs +++ b/crates/ink/tests/ui/trait_def/pass/using-env-types.rs @@ -1,4 +1,4 @@ -use ink::reflect::ContractEnv; +use ink::env::ContractEnv; use ink_env::Environment; #[ink::trait_definition] diff --git a/examples/multisig/lib.rs b/examples/multisig/lib.rs index 16a35430528..f6c2962ce20 100755 --- a/examples/multisig/lib.rs +++ b/examples/multisig/lib.rs @@ -537,7 +537,7 @@ mod multisig { self.ensure_confirmed(trans_id); let t = self.take_transaction(trans_id).expect(WRONG_TRANSACTION_ID); assert!(self.env().transferred_value() == t.transferred_value); - let result = build_call::<::Env>() + let result = build_call::<::Env>() .call_type( Call::new() .callee(t.callee) @@ -570,7 +570,7 @@ mod multisig { ) -> Result, Error> { self.ensure_confirmed(trans_id); let t = self.take_transaction(trans_id).expect(WRONG_TRANSACTION_ID); - let result = build_call::<::Env>() + let result = build_call::<::Env>() .call_type( Call::new() .callee(t.callee) From 1736a6a1325ae57c6f38e3cea6058a99ec836209 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 19 Jan 2023 22:19:55 +0000 Subject: [PATCH 102/206] Fmt and fix --- crates/env/src/api.rs | 2 +- crates/env/src/backend.rs | 4 +++- crates/env/src/call/create_builder.rs | 24 +++++++++++--------- crates/env/src/call/mod.rs | 2 +- crates/env/src/contract.rs | 6 ++--- crates/env/src/engine/mod.rs | 18 +++++---------- crates/env/src/engine/off_chain/impls.rs | 4 +++- crates/env/src/engine/on_chain/impls.rs | 14 ++++++------ crates/ink/src/env_access.rs | 6 +++-- crates/ink/src/reflect/contract.rs | 2 +- crates/ink/src/reflect/trait_def/registry.rs | 2 +- 11 files changed, 43 insertions(+), 41 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 7c1bd969a8e..962d4d8d142 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -23,8 +23,8 @@ use crate::{ call::{ Call, CallParams, - CreateParams, ConstructorReturnType, + CreateParams, DelegateCall, FromAccountId, }, diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 8db8fe9acdb..47f6181f442 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -445,7 +445,9 @@ pub trait TypedEnvBackend: EnvBackend { &mut self, params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult< + >::Output, + >, > where E: Environment, diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 28a3e13e37f..b9538aaa899 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -79,7 +79,7 @@ pub trait ConstructorReturnType { impl ConstructorReturnType for C where - C: ContractEnv + FromAccountId<::Env> + C: ContractEnv + FromAccountId<::Env>, { type Contract = C; type Output = C; @@ -222,7 +222,9 @@ where pub fn try_instantiate( &self, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult< + >::Output, + >, crate::Error, > { crate::instantiate_contract(self) @@ -373,7 +375,7 @@ impl Endowment, Args, Salt, - RetType + RetType, > where E: Environment, @@ -391,7 +393,7 @@ where Endowment, Args, Salt, - RetType + RetType, > { CreateBuilder { code_hash: Set(code_hash), @@ -438,7 +440,7 @@ impl Unset, Args, Salt, - RetType + RetType, > where E: Environment, @@ -456,7 +458,7 @@ where Set, Args, Salt, - RetType + RetType, > { CreateBuilder { code_hash: self.code_hash, @@ -479,7 +481,7 @@ impl Endowment, Unset>, Salt, - RetType + RetType, > where E: Environment, @@ -497,7 +499,7 @@ where Endowment, Set>, Salt, - RetType + RetType, > { CreateBuilder { code_hash: self.code_hash, @@ -520,7 +522,7 @@ impl Endowment, Args, Unset, - RetType + RetType, > where E: Environment, @@ -538,7 +540,7 @@ where Endowment, Args, Set, - RetType + RetType, > where Salt: AsRef<[u8]>, @@ -589,7 +591,7 @@ where Endowment, Args, Salt, - Set> + Set>, > where ContractRef: FromAccountId, diff --git a/crates/env/src/call/mod.rs b/crates/env/src/call/mod.rs index 7d170eab2ab..f5fd923cef7 100644 --- a/crates/env/src/call/mod.rs +++ b/crates/env/src/call/mod.rs @@ -50,10 +50,10 @@ pub use self::{ create_builder::{ build_create, state, + ConstructorReturnType, CreateBuilder, CreateParams, FromAccountId, - ConstructorReturnType, }, execution_input::ExecutionInput, selector::Selector, diff --git a/crates/env/src/contract.rs b/crates/env/src/contract.rs index 9a7b168da02..4eef18fa49b 100644 --- a/crates/env/src/contract.rs +++ b/crates/env/src/contract.rs @@ -14,7 +14,7 @@ /// # Usage: Default Environment /// /// ``` -/// +/// /// #[ink::contract] /// pub mod contract { /// #[ink(storage)] @@ -103,7 +103,7 @@ pub trait ContractEnv { /// # Usage /// /// ``` -/// +/// /// #[ink::contract] /// pub mod contract { /// #[ink(storage)] @@ -131,4 +131,4 @@ pub trait ContractEnv { pub trait ContractReference { /// The generated contract reference type. type Type; -} \ No newline at end of file +} diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 8baf2dcb004..aa2d0e5ba61 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -17,7 +17,10 @@ use crate::{ EnvBackend, TypedEnvBackend, }, - call::FromAccountId, + call::{ + ConstructorReturnType, + FromAccountId, + }, Error as EnvError, Error, Result as EnvResult, @@ -27,7 +30,6 @@ use ink_primitives::{ ConstructorResult, LangError, }; -use crate::call::ConstructorReturnType; pub trait OnInstance: EnvBackend + TypedEnvBackend { fn on_instance(f: F) -> R @@ -136,11 +138,7 @@ mod decode_instantiate_result_tests { fn encode_and_decode_return_value( return_value: ConstructorResult>, - ) -> EnvResult< - ConstructorResult< - Result, - >, - > { + ) -> EnvResult>> { let out_address = Vec::new(); let encoded_return_value = return_value.encode(); decode_return_value_fallible( @@ -152,11 +150,7 @@ mod decode_instantiate_result_tests { fn decode_return_value_fallible( out_address: &mut I, out_return_value: &mut I, - ) -> EnvResult< - ConstructorResult< - Result, - >, - > { + ) -> EnvResult>> { decode_instantiate_result::< I, DefaultEnvironment, diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 979d6894d8c..005cceab7ec 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -475,7 +475,9 @@ impl TypedEnvBackend for EnvInstance { &mut self, params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult< + >::Output, + >, > where E: Environment, diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 051a242762b..961cb27a345 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -20,9 +20,9 @@ use super::{ }; use crate::{ call::{ - utils::InstantiateResult, Call, CallParams, + ConstructorReturnType, CreateParams, DelegateCall, FromAccountId, @@ -481,20 +481,20 @@ impl TypedEnvBackend for EnvInstance { } } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, > where E: Environment, + ContractRef: FromAccountId, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType: InstantiateResult, - ContractRef: FromAccountId, + RetType: ConstructorReturnType, { let mut scoped = self.scoped_buffer(); let gas_limit = params.gas_limit(); @@ -518,7 +518,7 @@ impl TypedEnvBackend for EnvInstance { salt, ); - crate::engine::decode_instantiate_result::<_, E, RetType, ContractRef>( + crate::engine::decode_instantiate_result::<_, E, ContractRef, RetType>( instantiate_result.map_err(Into::into), &mut &out_address[..], &mut &out_return_value[..], diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 2b2e8cb758a..e3c79c595ac 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -18,8 +18,8 @@ use ink_env::{ call::{ Call, CallParams, - CreateParams, ConstructorReturnType, + CreateParams, DelegateCall, FromAccountId, }, @@ -484,7 +484,9 @@ where self, params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult< + >::Output, + >, > where ContractRef: FromAccountId, diff --git a/crates/ink/src/reflect/contract.rs b/crates/ink/src/reflect/contract.rs index 2e5854c4d74..5c81a4f82e1 100644 --- a/crates/ink/src/reflect/contract.rs +++ b/crates/ink/src/reflect/contract.rs @@ -46,4 +46,4 @@ pub trait ContractName { /// The name of the ink! smart contract. const NAME: &'static str; -} \ No newline at end of file +} diff --git a/crates/ink/src/reflect/trait_def/registry.rs b/crates/ink/src/reflect/trait_def/registry.rs index 75044073f33..933b70324c8 100644 --- a/crates/ink/src/reflect/trait_def/registry.rs +++ b/crates/ink/src/reflect/trait_def/registry.rs @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use ink_env::ContractEnv; use core::marker::PhantomData; +use ink_env::ContractEnv; /// Type that is guaranteed by ink! to implement all ink! trait definitions. /// From 252a5ef2c3134e21ae275df7679955718e47e6cf Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 19 Jan 2023 22:23:39 +0000 Subject: [PATCH 103/206] Remove E param from build_create --- crates/env/src/call/create_builder.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index b9538aaa899..deeca18df81 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -341,19 +341,18 @@ pub struct CreateBuilder< /// /// Note the usage of the [`CreateBuilder::instantiate_fallible`] method. #[allow(clippy::type_complexity)] -pub fn build_create() -> CreateBuilder< - E, +pub fn build_create() -> CreateBuilder< + ::Env, ContractRef, - Unset, + Unset<<::Env as Environment>::Hash>, Unset, - Unset, + Unset<<::Env as Environment>::Balance>, Unset>, Unset, Unset>, > where - E: Environment, - ContractRef: FromAccountId, + ContractRef: ContractEnv, { CreateBuilder { code_hash: Default::default(), From f3bf47677975e5fbb475fae2e73221cf9d506423 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 10:18:00 +0000 Subject: [PATCH 104/206] Fix up build_create --- crates/env/src/call/create_builder.rs | 4 ++-- .../ink/codegen/src/generator/as_dependency/contract_ref.rs | 2 +- crates/ink/src/env_access.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index deeca18df81..b45860b4c22 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -288,7 +288,7 @@ pub struct CreateBuilder< /// # impl FromAccountId for MyContract { /// # fn from_account_id(account_id: AccountId) -> Self { Self } /// # } -/// let my_contract: MyContract = build_create::() +/// let my_contract: MyContract = build_create::() /// .code_hash(Hash::from([0x42; 32])) /// .gas_limit(4000) /// .endowment(25) @@ -322,7 +322,7 @@ pub struct CreateBuilder< /// # #[derive(scale::Encode, scale::Decode, Debug)] /// # #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] /// # pub struct ConstructorError; -/// let my_contract: MyContract = build_create::() +/// let my_contract: MyContract = build_create::() /// .code_hash(Hash::from([0x42; 32])) /// .gas_limit(4000) /// .endowment(25) 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 61da16201b7..7d249878230 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -423,7 +423,7 @@ impl ContractRef<'_> { ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, > { - ::ink::env::call::build_create::() + ::ink::env::call::build_create::() .exec_input( ::ink::env::call::ExecutionInput::new( ::ink::env::call::Selector::new([ #( #selector_bytes ),* ]) diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index e3c79c595ac..32811a977e2 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -446,7 +446,7 @@ where /// /// Instantiates another contract. /// #[ink(message)] /// pub fn instantiate_contract(&self) -> AccountId { - /// let create_params = build_create::() + /// let create_params = build_create::() /// .code_hash(Hash::from([0x42; 32])) /// .gas_limit(4000) /// .endowment(25) From 8684af82262f88d1c44a3d52024aa7e18e2b212c Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 10:37:02 +0000 Subject: [PATCH 105/206] Fix up e2e creat builder --- crates/e2e/src/builders.rs | 13 ++++++++----- crates/e2e/src/client.rs | 12 ++++++------ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/crates/e2e/src/builders.rs b/crates/e2e/src/builders.rs index 8d23ff7fd65..4a9f468722c 100644 --- a/crates/e2e/src/builders.rs +++ b/crates/e2e/src/builders.rs @@ -32,21 +32,24 @@ use scale::Encode; /// The type returned from `ContractRef` constructors, partially initialized with the execution /// input arguments. -pub type CreateBuilderPartial = CreateBuilder< +pub type CreateBuilderPartial = CreateBuilder< E, + ContractRef, Unset<::Hash>, Unset, Unset<::Balance>, Set>, Unset, Set>, - R, >; /// Get the encoded constructor arguments from the partially initialized `CreateBuilder` -pub fn constructor_exec_input( - builder: CreateBuilderPartial, -) -> Vec { +pub fn constructor_exec_input( + builder: CreateBuilderPartial, +) -> Vec +where + E: Environment +{ // set all the other properties to default values, we only require the `exec_input`. builder .endowment(0u32.into()) diff --git a/crates/e2e/src/client.rs b/crates/e2e/src/client.rs index 3f9981d2cc5..453ac29618c 100644 --- a/crates/e2e/src/client.rs +++ b/crates/e2e/src/client.rs @@ -342,11 +342,11 @@ where /// Calling this function multiple times is idempotent, the contract is /// newly instantiated each time using a unique salt. No existing contract /// instance is reused! - pub async fn instantiate( + pub async fn instantiate( &mut self, contract_name: &str, signer: &Signer, - constructor: CreateBuilderPartial, + constructor: CreateBuilderPartial, value: E::Balance, storage_deposit_limit: Option, ) -> Result, Error> @@ -366,11 +366,11 @@ where } /// Dry run contract instantiation using the given constructor. - pub async fn instantiate_dry_run( + pub async fn instantiate_dry_run( &mut self, contract_name: &str, signer: &Signer, - constructor: CreateBuilderPartial, + constructor: CreateBuilderPartial, value: E::Balance, storage_deposit_limit: Option, ) -> ContractInstantiateResult @@ -398,11 +398,11 @@ where } /// Executes an `instantiate_with_code` call and captures the resulting events. - async fn exec_instantiate( + async fn exec_instantiate( &mut self, signer: &Signer, code: Vec, - constructor: CreateBuilderPartial, + constructor: CreateBuilderPartial, value: E::Balance, storage_deposit_limit: Option, ) -> Result, Error> From a1d6fc7733a12e6f789af71dff2e07637e35c1a7 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 11:22:17 +0000 Subject: [PATCH 106/206] Implement ContstructorReturnType for the storage_ident --- crates/env/src/call/create_builder.rs | 25 ++++++-------- .../generator/as_dependency/contract_ref.rs | 34 +++++++++++++++++++ 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index b45860b4c22..6954975a71f 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -12,22 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{ - call::{ - utils::{ - EmptyArgumentList, - ReturnType, - Set, - Unset, - Unwrap, - }, - ExecutionInput, - Selector, +use crate::{call::{ + utils::{ + EmptyArgumentList, + ReturnType, + Set, + Unset, + Unwrap, }, - ContractEnv, - Environment, - Error, -}; + ExecutionInput, + Selector, +}, ContractEnv, Environment, Error}; use core::marker::PhantomData; pub mod state { 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 7d249878230..9463bcad68f 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -109,6 +109,40 @@ impl ContractRef<'_> { type Type = #ref_ident; } + impl ::ink::env::call::ConstructorReturnType<#ref_ident> for #storage_ident { + type Contract = #ref_ident; + type Output = #ref_ident; + type Error = (); + + fn ok(value: #ref_ident) -> Self::Output { + value + } + + fn err(_err: Self::Error) -> Self::Output { + // todo! + unreachable!() + } + } + + impl ::ink::env::call::ConstructorReturnType<#ref_ident> for Result<#storage_ident, E> + where + E: ::scale::Decode + { + const IS_RESULT: bool = true; + + type Contract = #ref_ident; + type Output = ::core::result::Result<#ref_ident, E>; + type Error = E; + + fn ok(value: #ref_ident) -> Self::Output { + Ok(value) + } + + fn err(err: Self::Error) -> Self::Output { + Err(err) + } + } + impl ::ink::env::ContractEnv for #ref_ident { type Env = <#storage_ident as ::ink::env::ContractEnv>::Env; } From 7b9f6e4c06c580e362a49a778e2f627c3172116f Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 11:23:35 +0000 Subject: [PATCH 107/206] Fmt --- crates/e2e/src/builders.rs | 2 +- crates/env/src/call/create_builder.rs | 25 +++++++++++++++---------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/crates/e2e/src/builders.rs b/crates/e2e/src/builders.rs index 4a9f468722c..f0ae3b36eaf 100644 --- a/crates/e2e/src/builders.rs +++ b/crates/e2e/src/builders.rs @@ -48,7 +48,7 @@ pub fn constructor_exec_input( builder: CreateBuilderPartial, ) -> Vec where - E: Environment + E: Environment, { // set all the other properties to default values, we only require the `exec_input`. builder diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 6954975a71f..b45860b4c22 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -12,17 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{call::{ - utils::{ - EmptyArgumentList, - ReturnType, - Set, - Unset, - Unwrap, +use crate::{ + call::{ + utils::{ + EmptyArgumentList, + ReturnType, + Set, + Unset, + Unwrap, + }, + ExecutionInput, + Selector, }, - ExecutionInput, - Selector, -}, ContractEnv, Environment, Error}; + ContractEnv, + Environment, + Error, +}; use core::marker::PhantomData; pub mod state { From 54ea022f6a3c40434840f79ff4cfc14fe603749f Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 11:43:10 +0000 Subject: [PATCH 108/206] Fix envaccess test --- crates/ink/src/env_access.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 32811a977e2..549f21c9e88 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -445,7 +445,7 @@ where /// /// /// Instantiates another contract. /// #[ink(message)] - /// pub fn instantiate_contract(&self) -> AccountId { + /// pub fn instantiate_contract(&self) -> MyContractRef { /// let create_params = build_create::() /// .code_hash(Hash::from([0x42; 32])) /// .gas_limit(4000) From 9657d958d00123f913a319ba10cf0a7c9805a162 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 11:49:08 +0000 Subject: [PATCH 109/206] Fully qualify Result in macro --- crates/ink/codegen/src/generator/as_dependency/contract_ref.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 9463bcad68f..8785247ed91 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -124,7 +124,8 @@ impl ContractRef<'_> { } } - impl ::ink::env::call::ConstructorReturnType<#ref_ident> for Result<#storage_ident, E> + impl ::ink::env::call::ConstructorReturnType<#ref_ident> + for ::core::result::Result<#storage_ident, E> where E: ::scale::Decode { From e6c8e1c35bb7cfc57c72c50324aa5b2299046b2a Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 11:55:44 +0000 Subject: [PATCH 110/206] More fully qualify Result in macro --- .../ink/codegen/src/generator/as_dependency/contract_ref.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 8785247ed91..3a77c908bc9 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -136,11 +136,11 @@ impl ContractRef<'_> { type Error = E; fn ok(value: #ref_ident) -> Self::Output { - Ok(value) + ::core::result::Result::Ok(value) } fn err(err: Self::Error) -> Self::Output { - Err(err) + ::core::result::Result::Err(err) } } From ed3136fbcabb60abddfb9fa3a61c14243559da38 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 15:48:48 +0000 Subject: [PATCH 111/206] Fix up build_create examples --- crates/env/src/call/create_builder.rs | 61 ++++++++++++++++++--------- 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index b45860b4c22..03ca94ec5c9 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -282,13 +282,23 @@ pub struct CreateBuilder< /// # call::{build_create, Selector, ExecutionInput, FromAccountId} /// # }; /// # type Hash = ::Hash; -/// # type AccountId = ::AccountId; -/// # type Salt = &'static [u8]; -/// # struct MyContract; -/// # impl FromAccountId for MyContract { -/// # fn from_account_id(account_id: AccountId) -> Self { Self } -/// # } -/// let my_contract: MyContract = build_create::() +/// +/// #[ink::contract] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct MyContract {} +/// +/// impl MyContract { +/// #[ink(constructor)] +/// pub fn constructor() -> Self { Self {} } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// use contract::MyContractRef; +/// +/// let my_contract: MyContractRef = build_create::() /// .code_hash(Hash::from([0x42; 32])) /// .gas_limit(4000) /// .endowment(25) @@ -299,7 +309,7 @@ pub struct CreateBuilder< /// .push_arg(&[0x10u8; 32]) /// ) /// .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) -/// .returns::() +/// .returns::() /// .instantiate() /// .unwrap(); /// ``` @@ -313,16 +323,29 @@ pub struct CreateBuilder< /// # call::{build_create, Selector, ExecutionInput, FromAccountId} /// # }; /// # type Hash = ::Hash; -/// # type AccountId = ::AccountId; -/// # type Salt = &'static [u8]; -/// # struct MyContract; -/// # impl FromAccountId for MyContract { -/// # fn from_account_id(account_id: AccountId) -> Self { Self } -/// # } -/// # #[derive(scale::Encode, scale::Decode, Debug)] -/// # #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -/// # pub struct ConstructorError; -/// let my_contract: MyContract = build_create::() +/// +/// #[ink::contract] +/// pub mod contract { +/// #[derive(scale::Encode, scale::Decode, Debug)] +/// #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +/// pub struct ConstructorError; +/// +/// #[ink(storage)] +/// pub struct MyContract {} +/// +/// impl MyContract { +/// #[ink(constructor)] +/// pub fn constructor() -> Result { +/// Ok(Self {}) +/// } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// use contract::{MyContractRef, ConstructorError}; +/// +/// let my_contract: MyContractRef = build_create::() /// .code_hash(Hash::from([0x42; 32])) /// .gas_limit(4000) /// .endowment(25) @@ -333,7 +356,7 @@ pub struct CreateBuilder< /// .push_arg(&[0x10u8; 32]) /// ) /// .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) -/// .returns::>() +/// .returns::>() /// .instantiate() /// .unwrap() /// .unwrap(); From 19aaec2c7373bfbbac66f8541520c9756f01efbd Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 15:57:53 +0000 Subject: [PATCH 112/206] Add test for different combos of Self and struct name --- ...onstructor-return-result-cross-contract.rs | 118 ++++++++++++++++++ .../constructors-return-value/lib.rs | 2 +- 2 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs diff --git a/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs b/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs new file mode 100644 index 00000000000..f10199778d1 --- /dev/null +++ b/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs @@ -0,0 +1,118 @@ +#[ink::contract] +mod contract_callee { + #[ink(storage)] + pub struct Callee {} + + #[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)] + #[cfg_attr(feature = "std", derive(::scale_info::TypeInfo))] + pub enum Error { + Foo, + } + + impl Callee { + #[ink(constructor)] + pub fn new_self() -> Self { + Self { } + } + + #[ink(constructor)] + pub fn new_storage_name() -> Callee { + Callee { } + } + + #[ink(constructor)] + pub fn new_result_self() -> Result { + Ok(Self { }) + } + + #[ink(constructor)] + pub fn new_result_storage_name() -> Result { + Ok(Callee { }) + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +// #[ink::contract] +// mod contract_caller { +// use super::contract_callee::{CalleeRef, Error}; +// +// #[ink(storage)] +// pub struct Caller {} +// +// impl Caller { +// #[ink(constructor)] +// pub fn new() -> Self { +// Self { } +// } +// +// #[ink(message)] +// pub fn invoke_callee_constructors(&self) { +// let _: Result = CalleeRef::new_result_self() +// .code_hash(Hash::from([0x42; 32])) +// .gas_limit(4000) +// .endowment(25) +// .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) +// .instantiate() +// .unwrap(); +// +// // let _: Result = CalleeRef::new_result_storage_name().instantiate(); +// // +// // let _: CalleeRef = CalleeRef::new_self().instantiate(); +// // +// // let _: CalleeRef = CalleeRef::new_storage_name().instantiate(); +// } +// } +// } + +fn main() { + use contract_callee::{CalleeRef, Error}; + + // fn new_self() -> Self + let _: fn() -> CalleeRef = || { + CalleeRef::new_self() + .code_hash(ink_primitives::Clear::CLEAR_HASH) + .gas_limit(4000) + .endowment(25) + .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) + .instantiate() + .unwrap() + }; + + // fn new_storage_name() -> Callee + let _: fn() -> CalleeRef = || { + CalleeRef::new_storage_name() + .code_hash(ink_primitives::Clear::CLEAR_HASH) + .gas_limit(4000) + .endowment(25) + .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) + .instantiate() + .unwrap() + }; + + // fn new_result_self() -> Result + let _: fn() -> Result = || { + CalleeRef::new_result_self() + .code_hash(ink_primitives::Clear::CLEAR_HASH) + .gas_limit(4000) + .endowment(25) + .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) + .instantiate() + .unwrap() + }; + + // fn new_result_storage_name() -> Result + let _: fn() -> Result = || { + CalleeRef::new_result_self() + .code_hash(ink_primitives::Clear::CLEAR_HASH) + .gas_limit(4000) + .endowment(25) + .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) + .instantiate() + .unwrap() + }; +} + + 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 9cc69fa32ec..6c70e3eaa32 100644 --- a/examples/lang-err-integration-tests/constructors-return-value/lib.rs +++ b/examples/lang-err-integration-tests/constructors-return-value/lib.rs @@ -26,7 +26,7 @@ pub mod constructors_return_value { /// Fallible constructor #[ink(constructor)] - pub fn try_new(succeed: bool) -> Result { + pub fn try_new(succeed: bool) -> Result { if succeed { Ok(Self::new(true)) } else { From e9fe0e7936ec6ca8fd1ec67c4ab50df841478dd6 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 16:07:47 +0000 Subject: [PATCH 113/206] Fix ui test --- ...ructor-return-result-non-codec-error.stderr | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/crates/ink/tests/ui/contract/fail/constructor-return-result-non-codec-error.stderr b/crates/ink/tests/ui/contract/fail/constructor-return-result-non-codec-error.stderr index 19d2d86df6d..0fcf8ce9f45 100644 --- a/crates/ink/tests/ui/contract/fail/constructor-return-result-non-codec-error.stderr +++ b/crates/ink/tests/ui/contract/fail/constructor-return-result-non-codec-error.stderr @@ -11,6 +11,24 @@ note: required by a bound in `return_value` | R: scale::Encode, | ^^^^^^^^^^^^^ required by this bound in `return_value` +error[E0277]: the trait bound `contract::Error: WrapperTypeDecode` is not satisfied + --> tests/ui/contract/fail/constructor-return-result-non-codec-error.rs:13:9 + | +13 | pub fn constructor() -> Result { + | ^^^ the trait `WrapperTypeDecode` is not implemented for `contract::Error` + | + = help: the following other types implement trait `WrapperTypeDecode`: + Arc + Box + Rc + = note: required for `contract::Error` to implement `parity_scale_codec::Decode` + = note: required for `Result` to implement `ConstructorReturnType` +note: required by a bound in `CreateBuilder::>>::returns` + --> $WORKSPACE/crates/env/src/call/create_builder.rs + | + | R: ConstructorReturnType, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `CreateBuilder::>>::returns` + error[E0277]: the trait bound `contract::Error: TypeInfo` is not satisfied --> tests/ui/contract/fail/constructor-return-result-non-codec-error.rs:4:16 | From 431aa2b5f0d250f2618447a3f6116955b3d3c9a7 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 16:10:00 +0000 Subject: [PATCH 114/206] Fmt --- .../constructor-return-result-cross-contract.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs b/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs index f10199778d1..dee9e13a3c7 100644 --- a/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs +++ b/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs @@ -12,22 +12,22 @@ mod contract_callee { impl Callee { #[ink(constructor)] pub fn new_self() -> Self { - Self { } + Self {} } #[ink(constructor)] pub fn new_storage_name() -> Callee { - Callee { } + Callee {} } #[ink(constructor)] pub fn new_result_self() -> Result { - Ok(Self { }) + Ok(Self {}) } #[ink(constructor)] pub fn new_result_storage_name() -> Result { - Ok(Callee { }) + Ok(Callee {}) } #[ink(message)] @@ -68,7 +68,10 @@ mod contract_callee { // } fn main() { - use contract_callee::{CalleeRef, Error}; + use contract_callee::{ + CalleeRef, + Error, + }; // fn new_self() -> Self let _: fn() -> CalleeRef = || { @@ -114,5 +117,3 @@ fn main() { .unwrap() }; } - - From f9c474d55291a56a0c65dbf9f243ececbabc05d0 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 16:20:45 +0000 Subject: [PATCH 115/206] Remove unused assoc type --- crates/env/src/call/create_builder.rs | 7 ------- .../codegen/src/generator/as_dependency/contract_ref.rs | 2 -- 2 files changed, 9 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 03ca94ec5c9..1da613053b2 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -57,11 +57,6 @@ pub trait ConstructorReturnType { /// Is `true` if `Self` is `Result`. const IS_RESULT: bool = false; - /// The type of the contract returned from a constructor. - /// If a constructor returns `Self`, then `Contract = Self` - /// If a constructor returns a `Result`, then `Contract = Self`. - type Contract; - /// The actual return type of the constructor. /// If a constructor returns `Self`, then `Output = Self` /// If a constructor returns a `Result`, then `Output = Result`. @@ -81,7 +76,6 @@ impl ConstructorReturnType for C where C: ContractEnv + FromAccountId<::Env>, { - type Contract = C; type Output = C; type Error = (); @@ -102,7 +96,6 @@ where { const IS_RESULT: bool = true; - type Contract = C; type Output = core::result::Result; type Error = E; 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 3a77c908bc9..802dc418495 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -110,7 +110,6 @@ impl ContractRef<'_> { } impl ::ink::env::call::ConstructorReturnType<#ref_ident> for #storage_ident { - type Contract = #ref_ident; type Output = #ref_ident; type Error = (); @@ -131,7 +130,6 @@ impl ContractRef<'_> { { const IS_RESULT: bool = true; - type Contract = #ref_ident; type Output = ::core::result::Result<#ref_ident, E>; type Error = E; From 7286c4e3bb5a7f8f66e6640d1f302dcfbb767ca8 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 16:36:54 +0000 Subject: [PATCH 116/206] Change error fn to return Option --- crates/env/src/call/create_builder.rs | 17 +++++++---------- crates/env/src/engine/mod.rs | 5 ++++- .../src/generator/as_dependency/contract_ref.rs | 9 ++------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 1da613053b2..83418a7299d 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -69,7 +69,11 @@ pub trait ConstructorReturnType { fn ok(value: C) -> Self::Output; /// Construct an error value of the `Output` type. - fn err(err: Self::Error) -> Self::Output; + /// + /// `Result` impls should return `Some(Err(err))`, otherwise default to `None`. + fn err(_err: Self::Error) -> Option { + None + } } impl ConstructorReturnType for C @@ -82,11 +86,6 @@ where fn ok(value: C) -> Self::Output { value } - - fn err(_err: Self::Error) -> Self::Output { - // todo! - unreachable!() - } } impl ConstructorReturnType for core::result::Result @@ -103,13 +102,11 @@ where Ok(value) } - fn err(err: Self::Error) -> Self::Output { - Err(err) + fn err(err: Self::Error) -> Option { + Some(Err(err)) } } -// pub type InstantiateOutput = <>::Type as Instantiate - /// Builds up contract instantiations. #[derive(Debug)] pub struct CreateParams diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index aa2d0e5ba61..4fbebde8fa8 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -86,7 +86,10 @@ where 1 => { let contract_err = <>::Error as scale::Decode>::decode(out_return_value)?; - let err = >::err(contract_err); + let err = >::err(contract_err) + .unwrap_or_else(|| { + panic!("Expected an error instance for return type where IS_RESULT == true") + }); Ok(Ok(err)) } _ => Err(Error::Decode("Invalid inner constructor Result encoding, expected 0 or 1 as the first byte".into())) 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 802dc418495..a319689964c 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -116,11 +116,6 @@ impl ContractRef<'_> { fn ok(value: #ref_ident) -> Self::Output { value } - - fn err(_err: Self::Error) -> Self::Output { - // todo! - unreachable!() - } } impl ::ink::env::call::ConstructorReturnType<#ref_ident> @@ -137,8 +132,8 @@ impl ContractRef<'_> { ::core::result::Result::Ok(value) } - fn err(err: Self::Error) -> Self::Output { - ::core::result::Result::Err(err) + fn err(err: Self::Error) -> ::core::option::Option { + ::core::option::Option::Some(::core::result::Result::Err(err)) } } From 698f7e3096c2f2a48a2942d163afa8555efee3e5 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 16:49:33 +0000 Subject: [PATCH 117/206] Remove commented out code --- ...onstructor-return-result-cross-contract.rs | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs b/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs index dee9e13a3c7..c16b31cd2a4 100644 --- a/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs +++ b/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs @@ -35,38 +35,6 @@ mod contract_callee { } } -// #[ink::contract] -// mod contract_caller { -// use super::contract_callee::{CalleeRef, Error}; -// -// #[ink(storage)] -// pub struct Caller {} -// -// impl Caller { -// #[ink(constructor)] -// pub fn new() -> Self { -// Self { } -// } -// -// #[ink(message)] -// pub fn invoke_callee_constructors(&self) { -// let _: Result = CalleeRef::new_result_self() -// .code_hash(Hash::from([0x42; 32])) -// .gas_limit(4000) -// .endowment(25) -// .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) -// .instantiate() -// .unwrap(); -// -// // let _: Result = CalleeRef::new_result_storage_name().instantiate(); -// // -// // let _: CalleeRef = CalleeRef::new_self().instantiate(); -// // -// // let _: CalleeRef = CalleeRef::new_storage_name().instantiate(); -// } -// } -// } - fn main() { use contract_callee::{ CalleeRef, From e9cd71ca21adab6338dc80862e8d491ebf9a3491 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 17:24:35 +0000 Subject: [PATCH 118/206] Fmt --- crates/env/src/engine/mod.rs | 77 ++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 30 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 4fbebde8fa8..f75a32c4aed 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -73,40 +73,57 @@ where Ok(Ok(output)) } Err(EnvError::CalleeReverted) => { - let constructor_result_variant = out_return_value.read_byte()?; - match constructor_result_variant { - // 0 == `ConstructorResult::Ok` variant - 0 => { - if >::IS_RESULT { - let result_variant = out_return_value.read_byte()?; - match result_variant { - // 0 == `Ok` variant - 0 => panic!("The callee reverted, but did not encode an error in the output buffer."), - // 1 == `Err` variant - 1 => { - let contract_err = <>::Error - as scale::Decode>::decode(out_return_value)?; - let err = >::err(contract_err) - .unwrap_or_else(|| { - panic!("Expected an error instance for return type where IS_RESULT == true") - }); - Ok(Ok(err)) - } - _ => Err(Error::Decode("Invalid inner constructor Result encoding, expected 0 or 1 as the first byte".into())) - } - } else { - panic!("The callee reverted, but did not encode an error in the output buffer.") + decode_instantiate_err::(out_return_value) + } + Err(actual_error) => Err(actual_error), + } +} + +#[cfg_attr(all(feature = "std", not(test)), allow(dead_code))] +fn decode_instantiate_err( + out_return_value: &mut I, +) -> EnvResult>::Output>> +where + I: scale::Input, + E: crate::Environment, + ContractRef: FromAccountId, + R: ConstructorReturnType, +{ + let constructor_result_variant = out_return_value.read_byte()?; + match constructor_result_variant { + // 0 == `ConstructorResult::Ok` variant + 0 => { + if >::IS_RESULT { + let result_variant = out_return_value.read_byte()?; + match result_variant { + // 0 == `Ok` variant + 0 => panic!("The callee reverted, but did not encode an error in the output buffer."), + // 1 == `Err` variant + 1 => { + let contract_err = <>::Error + as scale::Decode>::decode(out_return_value)?; + let err = >::err(contract_err) + .unwrap_or_else(|| { + panic!("Expected an error instance for return type where IS_RESULT == true") + }); + Ok(Ok(err)) } + _ => Err(Error::Decode( + "Invalid inner constructor Result encoding, expected 0 or 1 as the first byte".into()) + ) } - // 1 == `ConstructorResult::Err` variant - 1 => { - let lang_err = ::decode(out_return_value)?; - Ok(Err(lang_err)) - } - _ => Err(Error::Decode("Invalid outer constructor Result encoding, expected 0 or 1 as the first byte".into())) + } else { + panic!("The callee reverted, but did not encode an error in the output buffer.") } } - Err(actual_error) => Err(actual_error), + // 1 == `ConstructorResult::Err` variant + 1 => { + let lang_err = ::decode(out_return_value)?; + Ok(Err(lang_err)) + } + _ => Err(Error::Decode( + "Invalid outer constructor Result encoding, expected 0 or 1 as the first byte".into()) + ) } } From 37d8e80f03c95ace187f9ab9eae3fad02163d215 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 20 Jan 2023 09:24:55 -0800 Subject: [PATCH 119/206] Fix `call-builder` E2E test compilation --- .../call-builder/lib.rs | 73 ++++--------------- 1 file changed, 14 insertions(+), 59 deletions(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index f4ba5d83641..5620a08cad1 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -54,13 +54,8 @@ mod call_builder { let result = build_call::() .call_type(Call::new().callee(address)) .exec_input(ExecutionInput::new(Selector::new(selector))) -<<<<<<< HEAD - .returns::>() - .fire() -======= .returns::<()>() .try_invoke() ->>>>>>> master .expect("Error from the Contracts pallet."); match result { @@ -72,15 +67,6 @@ mod call_builder { } } -<<<<<<< HEAD - /// Instantiate a contract using the `CreateBuilder`. - /// - /// Since we can't use the `CreateBuilder` in a test environment directly we need this - /// wrapper to test things like crafting calls with invalid selectors. - /// - /// We also wrap the output in an `Option` since we can't return a `Result` directly from a - /// contract message without erroring out ourselves. -======= /// Call a contract using the `CallBuilder`. /// /// Since we can't use the `CallBuilder` in a test environment directly we need this @@ -99,7 +85,13 @@ mod call_builder { .invoke() } ->>>>>>> master + /// Instantiate a contract using the `CreateBuilder`. + /// + /// Since we can't use the `CreateBuilder` in a test environment directly we need this + /// wrapper to test things like crafting calls with invalid selectors. + /// + /// We also wrap the output in an `Option` since we can't return a `Result` directly from a + /// contract message without erroring out ourselves. #[ink(message)] pub fn call_instantiate( &mut self, @@ -120,7 +112,6 @@ mod call_builder { .try_instantiate() .expect("Error from the Contracts pallet."); -<<<<<<< HEAD match result { Ok(_) => None, Err(e @ ink::LangError::CouldNotReadInput) => Some(e), @@ -168,25 +159,6 @@ mod call_builder { Some(lang_result.map(|contract_result| { contract_result.map(|inner| ink::ToAccountId::to_account_id(&inner)) })) -======= - let result = build_create::< - DefaultEnvironment, - constructors_return_value::ConstructorsReturnValueRef, - >() - .code_hash(code_hash) - .gas_limit(0) - .endowment(0) - .exec_input(ExecutionInput::new(Selector::new(selector)).push_arg(init_value)) - .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) - .params() - .try_instantiate(); - - // 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)) ->>>>>>> master } } @@ -330,8 +302,7 @@ mod call_builder { .call(&ink_e2e::bob(), 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(), @@ -368,8 +339,7 @@ mod call_builder { .call(&ink_e2e::charlie(), 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!( matches!(call_result, Some(ink::LangError::CouldNotReadInput)), @@ -402,16 +372,8 @@ mod call_builder { build_message::(contract_acc_id).call(|contract| { contract.call_instantiate(code_hash, selector, init_value) }); -<<<<<<< HEAD - let call_result = client.call(&mut ink_e2e::dave(), call, 0, None).await; -======= - let call_result = client - .call(&ink_e2e::dave(), call, 0, None) - .await - .expect("Client failed to call `call_builder::call_instantiate`.") - .return_value(); ->>>>>>> master + let call_result = client.call(&mut ink_e2e::dave(), call, 0, None).await; assert!( call_result.is_err(), "Call execution should've failed, but didn't." @@ -457,17 +419,12 @@ mod call_builder { let call_result = client .call(&mut ink_e2e::eve(), call, 0, None) .await -<<<<<<< HEAD .expect("Calling `call_builder::call_instantiate_fallible` failed") .return_value() - .expect("Dispatching `call_builder::call_instantiate_fallible` failed."); -======= - .expect("Client failed to call `call_builder::call_instantiate`.") - .return_value(); ->>>>>>> master + .expect("TODO"); assert!( - call_result.unwrap().is_ok(), + call_result.is_ok(), "Call to falliable constructor failed, when it should have succeeded." ); @@ -501,8 +458,7 @@ mod call_builder { .call(&mut ink_e2e::ferdie(), call, 0, None) .await .expect("Calling `call_builder::call_instantiate_fallible` failed") - .return_value() - .expect("Dispatching `call_builder::call_instantiate_fallible` failed."); + .return_value(); let contract_result = call_result .unwrap() @@ -593,8 +549,7 @@ mod call_builder { .expect( "Client failed to call `call_builder::call_instantiate_fallible`.", ) - .return_value() - .expect("Dispatching `call_builder::call_instantiate_fallible` failed."); + .return_value(); assert!( matches!(call_result, Some(Err(ink::LangError::CouldNotReadInput))), From 0c568b5bc07b325d96dd0d29dff51b3c5b48ae02 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 20 Jan 2023 09:27:48 -0800 Subject: [PATCH 120/206] Fix `contract-ref` E2E test compilation --- .../lang-err-integration-tests/contract-ref/lib.rs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/examples/lang-err-integration-tests/contract-ref/lib.rs b/examples/lang-err-integration-tests/contract-ref/lib.rs index b9b1d521052..4ea1196c27e 100755 --- a/examples/lang-err-integration-tests/contract-ref/lib.rs +++ b/examples/lang-err-integration-tests/contract-ref/lib.rs @@ -17,11 +17,7 @@ mod contract_ref { .endowment(0) .code_hash(flipper_code_hash) .salt_bytes(salt) -<<<<<<< HEAD - .instantiate() - .unwrap_or_else(|error| { - panic!("Received an error from the Contracts pallet while instantiating Flipper {:?}", error) - }); + .instantiate(); Self { flipper } } @@ -40,9 +36,6 @@ mod contract_ref { .unwrap_or_else(|error| { panic!("Received an error from the Flipper constructor while instantiating Flipper {:?}", error) }); -======= - .instantiate(); ->>>>>>> master Self { flipper } } @@ -151,9 +144,7 @@ mod contract_ref { .call(&ink_e2e::bob(), get_check, 0, None) .await .expect("Calling `get_check` failed"); - let initial_value = get_call_result - .value - .expect("Input is valid, call must not fail."); + let initial_value = get_call_result.return_value(); assert!(initial_value); Ok(()) From 612fae4fb9e221ef4bf5fcc4705a3f28f6a153fc Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 17:51:37 +0000 Subject: [PATCH 121/206] ConstructorReturnType comments --- crates/env/src/call/create_builder.rs | 56 ++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 83418a7299d..f369acb91ae 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -52,7 +52,55 @@ where fn from_account_id(account_id: ::AccountId) -> Self; } -/// todo! +/// Represents any type that can be returned from an `ink!` constructor. The following contract +/// implements the four different return type signatures implementing this trait: +/// +/// - `Self` +/// - `Result` +/// - `Contract` +/// - `Result` +/// +/// ```rust +/// #[ink::contract] +/// mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// #[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)] +/// #[cfg_attr(feature = "std", derive(::scale_info::TypeInfo))] +/// pub enum Error { +/// Foo, +/// } +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn new_self() -> Self { +/// Self {} +/// } +/// +/// #[ink(constructor)] +/// pub fn new_storage_name() -> Contract { +/// Contract {} +/// } +/// +/// #[ink(constructor)] +/// pub fn new_result_self() -> Result { +/// Ok(Self {}) +/// } +/// +/// #[ink(constructor)] +/// pub fn new_result_storage_name() -> Result { +/// Ok(Contract {}) +/// } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// ``` +/// +/// These constructor return signatures are then used by the contract ref codegen for the +/// [`CreateBuilder::returns`] type parameter. pub trait ConstructorReturnType { /// Is `true` if `Self` is `Result`. const IS_RESULT: bool = false; @@ -76,6 +124,10 @@ pub trait ConstructorReturnType { } } +/// Blanket impl for contract ref types, generated for cross-contract calls. +/// +/// In the context of a contract ref inherent, `Self` from a constructor return +/// type will become the type of the contract ref's type. impl ConstructorReturnType for C where C: ContractEnv + FromAccountId<::Env>, @@ -88,6 +140,8 @@ where } } +/// Blanket impl for a `Result` return type. `Self` in the context +/// of a contract ref inherent becomes the contract refs type. impl ConstructorReturnType for core::result::Result where C: ContractEnv + FromAccountId<::Env>, From 6993240f78e32d61754056c74305adf3261b4bc9 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 17:55:53 +0000 Subject: [PATCH 122/206] Fix up return types after merge --- crates/env/src/call/create_builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 2df149f1d21..774f8a12896 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -251,7 +251,7 @@ where /// [`ink::primitives::LangError`][`ink_primitives::LangError`]. If you want to handle those /// use the [`try_instantiate`][`CreateParams::try_instantiate`] method instead. #[inline] - pub fn instantiate(&self) -> R { + pub fn instantiate(&self) -> >::Output { crate::instantiate_contract(self) .unwrap_or_else(|env_error| { panic!("Cross-contract instantiation failed with {:?}", env_error) From a15a20c8f24d97a0fe12994c9ccafdf3f6bf08f8 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 17:57:27 +0000 Subject: [PATCH 123/206] Fmt --- crates/env/src/call/create_builder.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 774f8a12896..9df25a58d06 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -740,9 +740,7 @@ where /// [`ink::primitives::LangError`][`ink_primitives::LangError`]. If you want to handle those /// use the [`try_instantiate`][`CreateBuilder::try_instantiate`] method instead. #[inline] - pub fn instantiate( - self, - ) -> >::Output { + pub fn instantiate(self) -> >::Output { self.params().instantiate() } From d7b83c503b8212361d3a72bf1253abb3b7defd11 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 17:58:24 +0000 Subject: [PATCH 124/206] Clippy --- crates/e2e/src/client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/e2e/src/client.rs b/crates/e2e/src/client.rs index 9cda18473fb..1ed00fa18d8 100644 --- a/crates/e2e/src/client.rs +++ b/crates/e2e/src/client.rs @@ -706,7 +706,7 @@ where }); let account_data = get_composite_field_value(&account, "data")?; - let balance = get_composite_field_value(&account_data, "free")?; + let balance = get_composite_field_value(account_data, "free")?; let balance = balance.as_u128().ok_or_else(|| { Error::Balance(format!("{:?} should convert to u128", balance)) })?; From 417dca5b7d90cda57794301fbe38d5a4f71e032b Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 18:14:24 +0000 Subject: [PATCH 125/206] Fix create_builder tests --- crates/env/src/call/create_builder.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 9df25a58d06..513be662db1 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -362,8 +362,7 @@ pub struct CreateBuilder< /// ) /// .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) /// .returns::() -/// .instantiate() -/// .unwrap(); +/// .instantiate(); /// ``` /// /// ## Example 2: Handles Result from Fallible Constructor @@ -410,7 +409,6 @@ pub struct CreateBuilder< /// .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) /// .returns::>() /// .instantiate() -/// .unwrap() /// .unwrap(); /// ``` /// From 7d20051b30d00829f83f4b2f73f4e34119f4040d Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 20 Jan 2023 16:09:50 -0800 Subject: [PATCH 126/206] Fix some of the comment links --- crates/env/src/call/call_builder.rs | 9 ++++++--- crates/env/src/call/create_builder.rs | 17 ++++++++++------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/crates/env/src/call/call_builder.rs b/crates/env/src/call/call_builder.rs index 3f9a5d71aac..ae6ab49edba 100644 --- a/crates/env/src/call/call_builder.rs +++ b/crates/env/src/call/call_builder.rs @@ -132,7 +132,8 @@ where /// # Note /// /// On failure this returns an outer [`ink::env::Error`][`crate::Error`] or inner - /// [`ink_primitives::LangError`], both of which can be handled by the caller. + /// [`ink::primitives::LangError`][`ink_primitives::LangError`], both of which can be handled + /// by the caller. pub fn try_invoke(&self) -> Result, crate::Error> { crate::invoke_contract(self) } @@ -691,7 +692,8 @@ where /// # Note /// /// On failure this returns an outer [`ink::env::Error`][`crate::Error`] or inner - /// [`ink_primitives::LangError`], both of which can be handled by the caller. + /// [`ink::primitives::LangError`][`ink_primitives::LangError`], both of which can be handled + /// by the caller. pub fn try_invoke(self) -> Result, Error> { self.params().try_invoke() } @@ -750,7 +752,8 @@ where /// # Note /// /// On failure this returns an outer [`ink::env::Error`][`crate::Error`] or inner - /// [`ink_primitives::LangError`], both of which can be handled by the caller. + /// [`ink::primitives::LangError`][`ink_primitives::LangError`], both of which can be handled + /// by the caller. pub fn try_invoke(self) -> Result, Error> { self.params().try_invoke() } diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index c10b1281bdd..921e8e3c6a1 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -122,9 +122,6 @@ where /// /// # Panics /// - /// This method panics if it encounters an [`ink::env::Error`][`crate::Error`]. If you want to - /// handle those use the [`try_instantiate`][`CreateParams::try_instantiate`] method instead. - /// /// This method panics if it encounters an [`ink::env::Error`][`crate::Error`] or an /// [`ink::primitives::LangError`][`ink_primitives::LangError`]. If you want to handle those /// use the [`try_instantiate`][`CreateParams::try_instantiate`] method instead. @@ -148,7 +145,8 @@ where /// # Note /// /// On failure this returns an outer [`ink::env::Error`][`crate::Error`] or inner - /// [`ink_primitives::LangError`], both of which can be handled by the caller. + /// [`ink::primitives::LangError`][`ink_primitives::LangError`], both of which can be handled + /// by the caller. #[inline] pub fn try_instantiate( &self, @@ -188,7 +186,9 @@ where /// /// # Note /// - /// On failure this returns an [`ink_primitives::LangError`] which can be handled by the caller. + /// On failure this returns an outer [`ink::env::Error`][`crate::Error`] or inner + /// [`ink::primitives::LangError`][`ink_primitives::LangError`], both of which can be handled + /// by the caller. #[inline] pub fn try_instantiate_fallible( &self, @@ -555,7 +555,8 @@ where /// # Note /// /// On failure this returns an outer [`ink::env::Error`][`crate::Error`] or inner - /// [`ink_primitives::LangError`], both of which can be handled by the caller. + /// [`ink::primitives::LangError`][`ink_primitives::LangError`], both of which can be handled + /// by the caller. #[inline] pub fn try_instantiate( self, @@ -597,7 +598,9 @@ where /// /// # Note /// - /// On failure this returns an [`ink_primitives::LangError`] which can be handled by the caller. + /// On failure this returns an outer [`ink::env::Error`][`crate::Error`] or inner + /// [`ink::primitives::LangError`][`ink_primitives::LangError`], both of which can be handled + /// by the caller. #[inline] pub fn try_instantiate_fallible( self, From eeb7b855a6fc1434749692abc2b564e57fc36005 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 20 Jan 2023 16:16:37 -0800 Subject: [PATCH 127/206] Unwrap errors from default `instantiate_fallible` codepath --- crates/env/src/call/create_builder.rs | 31 ++++++++++++++++----------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 921e8e3c6a1..fb2e31028d8 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -170,16 +170,21 @@ where /// # Panics /// /// This method panics if it encounters an [`ink_primitives::LangError`]. If you want to handle - /// those use the [`try_instantiate_fallible`][`CreateParams::try_instantiate_fallible`] method instead. + /// those use the [`try_instantiate_fallible`][`CreateParams::try_instantiate_fallible`] method + /// instead. #[inline] - pub fn instantiate_fallible(&self) -> Result, crate::Error> { - crate::instantiate_fallible_contract(self).map(|constructor_result| { - constructor_result - .unwrap_or_else(|error| { - panic!("Received a `LangError` while instantiating: {:?}", error) - }) - .map(FromAccountId::from_account_id) - }) + pub fn instantiate_fallible(&self) -> Result { + crate::instantiate_fallible_contract(self) + .unwrap_or_else(|env_error| { + panic!("Cross-contract instantiation failed with {:?}", env_error) + }) + .unwrap_or_else(|lang_error| { + panic!( + "Received a `LangError` while instantiating: {:?}", + lang_error + ) + }) + .map(FromAccountId::from_account_id) } /// Attempts to instantiate the contract, returning the execution result back to the caller. @@ -587,10 +592,12 @@ where /// /// # Panics /// - /// This method panics if it encounters an [`ink_primitives::LangError`]. If you want to handle - /// those use the [`try_instantiate_fallible`][`CreateParams::try_instantiate_fallible`] method instead. + /// This method panics if it encounters an [`ink::env::Error`][`crate::Error`] or an + /// [`ink::primitives::LangError`][`ink_primitives::LangError`]. If you want to handle those + /// use the [`try_instantiate_fallible`][`CreateParams::try_instantiate_fallible`] method + /// instead. #[inline] - pub fn instantiate_fallible(self) -> Result, Error> { + pub fn instantiate_fallible(self) -> Result { self.params().instantiate_fallible() } From 658fed186242b00ea099a5cd17380a2fdd50e89a Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 20 Jan 2023 16:21:08 -0800 Subject: [PATCH 128/206] Fix `contract-ref` E2E test --- examples/lang-err-integration-tests/contract-ref/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/lang-err-integration-tests/contract-ref/lib.rs b/examples/lang-err-integration-tests/contract-ref/lib.rs index 4ea1196c27e..7e42eb65be0 100755 --- a/examples/lang-err-integration-tests/contract-ref/lib.rs +++ b/examples/lang-err-integration-tests/contract-ref/lib.rs @@ -30,9 +30,6 @@ mod contract_ref { .code_hash(flipper_code_hash) .salt_bytes(salt) .instantiate_fallible() - .unwrap_or_else(|error| { - panic!("Received an error from the Contracts pallet while instantiating Flipper {:?}", error) - }) .unwrap_or_else(|error| { panic!("Received an error from the Flipper constructor while instantiating Flipper {:?}", error) }); From aac62db0b7fd88b2a6ab60878b87eb89e1e5bc61 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 20 Jan 2023 16:27:00 -0800 Subject: [PATCH 129/206] Wrap long line --- examples/lang-err-integration-tests/contract-ref/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/lang-err-integration-tests/contract-ref/lib.rs b/examples/lang-err-integration-tests/contract-ref/lib.rs index 7e42eb65be0..b38d3ff3dd1 100755 --- a/examples/lang-err-integration-tests/contract-ref/lib.rs +++ b/examples/lang-err-integration-tests/contract-ref/lib.rs @@ -31,7 +31,10 @@ mod contract_ref { .salt_bytes(salt) .instantiate_fallible() .unwrap_or_else(|error| { - panic!("Received an error from the Flipper constructor while instantiating Flipper {:?}", error) + panic!( + "Received an error from the Flipper constructor while instantiating \ + Flipper {:?}", error + ) }); Self { flipper } From 619cc71004f50330bc3fa295cfd28badf003b2d4 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 20 Jan 2023 16:45:18 -0800 Subject: [PATCH 130/206] Remove TODO --- examples/lang-err-integration-tests/call-builder/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 5620a08cad1..6b4638d01a1 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -420,11 +420,10 @@ mod call_builder { .call(&mut ink_e2e::eve(), call, 0, None) .await .expect("Calling `call_builder::call_instantiate_fallible` failed") - .return_value() - .expect("TODO"); + .return_value(); assert!( - call_result.is_ok(), + matches!(call_result, Some(Ok(_))), "Call to falliable constructor failed, when it should have succeeded." ); From dd4148593b336e220046c84ccb9673f49e303f51 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 20 Jan 2023 16:47:37 -0800 Subject: [PATCH 131/206] Fix instatiation doc test --- crates/env/src/call/create_builder.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index fb2e31028d8..6dd80724439 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -304,8 +304,7 @@ where /// .returns::>() /// .params() /// .instantiate_fallible() -/// .unwrap() -/// .unwrap(); +/// .expect("Constructor should've run without errors."); /// ``` /// /// Note the usage of the [`CreateBuilder::instantiate_fallible`] method. From cd33f29500206bec9d243ecc4b51db0f9dc6f252 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sat, 21 Jan 2023 11:22:03 -0800 Subject: [PATCH 132/206] Fix cross-contract compile test --- .../contract/pass/constructor-return-result-cross-contract.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs b/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs index c16b31cd2a4..984c053d8b6 100644 --- a/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs +++ b/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs @@ -49,7 +49,6 @@ fn main() { .endowment(25) .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) .instantiate() - .unwrap() }; // fn new_storage_name() -> Callee @@ -60,7 +59,6 @@ fn main() { .endowment(25) .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) .instantiate() - .unwrap() }; // fn new_result_self() -> Result @@ -71,7 +69,6 @@ fn main() { .endowment(25) .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) .instantiate() - .unwrap() }; // fn new_result_storage_name() -> Result @@ -82,6 +79,5 @@ fn main() { .endowment(25) .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) .instantiate() - .unwrap() }; } From 4897616e8c8a6b7bcfb8168453b5d21844b73bd1 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sat, 21 Jan 2023 11:25:05 -0800 Subject: [PATCH 133/206] Clean up some comments --- crates/env/src/call/create_builder.rs | 14 +++++++------- crates/env/src/call/execution_input.rs | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 513be662db1..a5bba30eec7 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -99,7 +99,7 @@ where /// } /// ``` /// -/// These constructor return signatures are then used by the contract ref codegen for the +/// These constructor return signatures are then used by the `ContractRef` codegen for the /// [`CreateBuilder::returns`] type parameter. pub trait ConstructorReturnType { /// Is `true` if `Self` is `Result`. @@ -124,10 +124,10 @@ pub trait ConstructorReturnType { } } -/// Blanket impl for contract ref types, generated for cross-contract calls. +/// Blanket implementation for `ContractRef` types, generated for cross-contract calls. /// -/// In the context of a contract ref inherent, `Self` from a constructor return -/// type will become the type of the contract ref's type. +/// In the context of a `ContractRef` inherent, `Self` from a constructor return +/// type will become the type of the `ContractRef`'s type. impl ConstructorReturnType for C where C: ContractEnv + FromAccountId<::Env>, @@ -140,8 +140,8 @@ where } } -/// Blanket impl for a `Result` return type. `Self` in the context -/// of a contract ref inherent becomes the contract refs type. +/// Blanket implementation for a `Result` return type. `Self` in the context +/// of a `ContractRef` inherent becomes the `ContractRef`s type. impl ConstructorReturnType for core::result::Result where C: ContractEnv + FromAccountId<::Env>, @@ -214,7 +214,7 @@ where /// Modify the selector. /// /// Useful when using the [`CreateParams`] generated as part of the - /// contract ref, but using a custom selector. + /// `ContractRef`, but using a custom selector. pub fn update_selector(&mut self, selector: Selector) { self.exec_input.update_selector(selector) } diff --git a/crates/env/src/call/execution_input.rs b/crates/env/src/call/execution_input.rs index 8f3f79dd171..fb491468522 100644 --- a/crates/env/src/call/execution_input.rs +++ b/crates/env/src/call/execution_input.rs @@ -67,7 +67,7 @@ impl ExecutionInput { /// Modify the selector. /// /// Useful when using the [`ExecutionInput`] generated as part of the - /// contract ref, but using a custom selector. + /// `ContractRef`, but using a custom selector. pub fn update_selector(&mut self, selector: Selector) { self.selector = selector; } From 459c4e06c3116e11cbe04cd34425f35142423529 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sat, 21 Jan 2023 11:27:45 -0800 Subject: [PATCH 134/206] Fix `contract-ref` compilation --- examples/lang-err-integration-tests/contract-ref/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/lang-err-integration-tests/contract-ref/lib.rs b/examples/lang-err-integration-tests/contract-ref/lib.rs index 0aba592a579..3f86a3bdf49 100755 --- a/examples/lang-err-integration-tests/contract-ref/lib.rs +++ b/examples/lang-err-integration-tests/contract-ref/lib.rs @@ -30,9 +30,6 @@ mod contract_ref { .code_hash(flipper_code_hash) .salt_bytes(salt) .instantiate() - .unwrap_or_else(|error| { - panic!("Received an error from the Contracts pallet while instantiating Flipper {:?}", error) - }) .unwrap_or_else(|error| { panic!("Received an error from the Flipper constructor while instantiating Flipper {:?}", error) }); From 19d5b4bda62b89f8c5bc7162d08e1f1e796d843a Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sat, 21 Jan 2023 11:28:17 -0800 Subject: [PATCH 135/206] Remove outdated doc --- crates/env/src/call/create_builder.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index a5bba30eec7..574743464bb 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -411,8 +411,6 @@ pub struct CreateBuilder< /// .instantiate() /// .unwrap(); /// ``` -/// -/// Note the usage of the [`CreateBuilder::instantiate_fallible`] method. #[allow(clippy::type_complexity)] pub fn build_create() -> CreateBuilder< ::Env, From 193c801e2c27eb8df589882407c7bd0c92a27ef1 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sat, 21 Jan 2023 11:31:17 -0800 Subject: [PATCH 136/206] Update comment --- crates/env/src/call/create_builder.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 574743464bb..a2067b38846 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -106,8 +106,8 @@ pub trait ConstructorReturnType { const IS_RESULT: bool = false; /// The actual return type of the constructor. - /// If a constructor returns `Self`, then `Output = Self` - /// If a constructor returns a `Result`, then `Output = Result`. + /// - If a constructor returns `Self`, then `Output = Self` + /// - If a constructor returns a `Result`, then `Output = Result` type Output; /// The error type of the constructor return type. From 5ff122e504539ebc751f3311f17112ee02712a98 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sat, 21 Jan 2023 11:31:38 -0800 Subject: [PATCH 137/206] Another comment fix --- crates/env/src/call/create_builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index a2067b38846..70875052ac4 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -177,7 +177,7 @@ where exec_input: ExecutionInput, /// The salt for determining the hash for the contract account ID. salt_bytes: Salt, - /// The return type of the target contracts constructor method. + /// The return type of the target contract's constructor method. _return_type: ReturnType, /// The type of the reference to the contract returned from the constructor. _phantom: PhantomData ContractRef>, From 4dd4a3f718617becd748cff3baa431b7203db744 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sat, 21 Jan 2023 11:56:40 -0800 Subject: [PATCH 138/206] Bump `contract-metadata` Fixes some inconsistent errors between Clippy and `rustc` --- crates/e2e/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/e2e/Cargo.toml b/crates/e2e/Cargo.toml index 397a2d098ee..252765b6cb0 100644 --- a/crates/e2e/Cargo.toml +++ b/crates/e2e/Cargo.toml @@ -21,7 +21,7 @@ ink = { version = "4.0.0-beta", path = "../ink" } ink_env = { version = "4.0.0-beta", path = "../env" } ink_primitives = { version = "4.0.0-beta", path = "../primitives" } -contract-metadata = { version = "2.0.0-beta.1" } +contract-metadata = { version = "2.0.0-rc" } impl-serde = { version = "0.3.1", default-features = false } jsonrpsee = { version = "0.16.0", features = ["ws-client"] } serde = { version = "1.0.137", default-features = false, features = ["derive"] } From 3758e09345cfdf32a3b2df0e54fcc11187e612eb Mon Sep 17 00:00:00 2001 From: andrew Date: Fri, 13 Jan 2023 17:56:43 +0000 Subject: [PATCH 139/206] Remove fallible create_builder.rs methods --- crates/env/src/call/create_builder.rs | 47 --------------------------- 1 file changed, 47 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 6dd80724439..0b392ae1bfd 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -568,50 +568,3 @@ where self.params().try_instantiate() } } - -impl - CreateBuilder< - E, - Set, - GasLimit, - Set, - Set>, - Set, - Set>>, - > -where - E: Environment, - GasLimit: Unwrap, - Args: scale::Encode, - Salt: AsRef<[u8]>, - RetType: FromAccountId, - ContractError: scale::Decode, -{ - /// Attempts to instantiate the contract, returning the execution result back to the caller. - /// - /// # Panics - /// - /// This method panics if it encounters an [`ink::env::Error`][`crate::Error`] or an - /// [`ink::primitives::LangError`][`ink_primitives::LangError`]. If you want to handle those - /// use the [`try_instantiate_fallible`][`CreateParams::try_instantiate_fallible`] method - /// instead. - #[inline] - pub fn instantiate_fallible(self) -> Result { - self.params().instantiate_fallible() - } - - /// Attempts to instantiate the contract, returning the execution result back to the caller. - /// - /// # Note - /// - /// On failure this returns an outer [`ink::env::Error`][`crate::Error`] or inner - /// [`ink::primitives::LangError`][`ink_primitives::LangError`], both of which can be handled - /// by the caller. - #[inline] - pub fn try_instantiate_fallible( - self, - ) -> Result>, Error> - { - self.params().try_instantiate_fallible() - } -} From cdcc50201553f1c93e026af8da792b9a322ee67d Mon Sep 17 00:00:00 2001 From: andrew Date: Sat, 14 Jan 2023 11:18:15 +0000 Subject: [PATCH 140/206] WIP experiment --- crates/env/src/api.rs | 5 +- crates/env/src/backend.rs | 10 +- crates/env/src/call/common.rs | 96 +++++++++++++++++++ crates/env/src/call/create_builder.rs | 3 +- crates/env/src/call/mod.rs | 2 + crates/env/src/engine/off_chain/impls.rs | 8 +- crates/env/src/engine/on_chain/impls.rs | 21 ++-- .../generator/as_dependency/contract_ref.rs | 4 +- 8 files changed, 135 insertions(+), 14 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 90c1294da19..518af944d7a 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -25,6 +25,8 @@ use crate::{ CallParams, CreateParams, DelegateCall, + FromAccountId, + utils::ConstructorOutputValue, }, engine::{ EnvInstance, @@ -325,11 +327,12 @@ where /// - If the returned account ID failed to decode properly. pub fn instantiate_contract( params: &CreateParams, -) -> Result> +) -> Result>> where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, + R: FromAccountId, { ::on_instance(|instance| { TypedEnvBackend::instantiate_contract::(instance, params) diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 99b2024f39d..d78b45ea241 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -17,7 +17,12 @@ use crate::{ Call, CallParams, CreateParams, + FromAccountId, DelegateCall, + utils::{ + ConstructorOutput, + ConstructorOutputValue, + } }, hash::{ CryptoHash, @@ -442,11 +447,12 @@ pub trait TypedEnvBackend: EnvBackend { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result> + ) -> Result>> where E: Environment, Args: scale::Encode, - Salt: AsRef<[u8]>; + Salt: AsRef<[u8]>, + R: FromAccountId,; /// Attempts to instantiate another contract, returning the instantiation result back to the /// caller. diff --git a/crates/env/src/call/common.rs b/crates/env/src/call/common.rs index e1cc4171a2d..a2bc4addd00 100644 --- a/crates/env/src/call/common.rs +++ b/crates/env/src/call/common.rs @@ -15,6 +15,8 @@ //! Utilities, types and abstractions common to call and instantiation routines. use core::marker::PhantomData; +use crate::call::FromAccountId; +use crate::Environment; /// Represents a return type. /// @@ -38,6 +40,100 @@ impl Default for ReturnType { } } +mod private { + /// Seals the implementation of `ConstructorReturnType`. + pub trait Sealed {} +} + +/// Guards against using invalid contract initializer types. +/// +/// # Note +/// +/// Currently the only allowed types are `()` and `Result<(), E>` +/// where `E` is some unspecified error type. +/// If the contract initializer returns `Result::Err` the utility +/// method that is used to initialize an ink! smart contract will +/// revert the state of the contract instantiation. +pub trait ConstructorOutput: private::Sealed { + /// Is `true` if `Self` is `Result`. + const IS_RESULT: bool = false; + + /// Reflects the output type of the dispatchable ink! constructor. + type Output; + + /// The error type of the constructor return type. + /// + /// # Note + /// + /// For infallible constructors this is `()` whereas for fallible + /// constructors this is the actual return error type. Since we only ever + /// return a value in case of `Result::Err` the `Result::Ok` value type + /// does not matter. + type Error; + + // todo: docs + fn from_account_id(account_id: Env::AccountId) -> Self::Output; + + /// Converts the return value into a `Result` instance. + /// + /// # Note + /// + /// For infallible constructor returns this always yields `Ok`. + fn as_result(&self) -> Result<&C, &Self::Error>; +} + +/// todo: comment +pub struct ConstructorOutputValue(T, PhantomData); + +impl ConstructorOutputValue +where + Env: Environment, +{ + pub fn new(val: T) -> Self { + Self(val, PhantomData) + } +} + +impl private::Sealed for ConstructorOutputValue {} + +impl ConstructorOutput for ConstructorOutputValue +where + C: FromAccountId, + Env: Environment, +{ + type Output = C; + type Error = &'static (); + + fn from_account_id(account_id: Env::AccountId) -> Self::Output { + C::from_account_id(account_id) + } + + #[inline(always)] + fn as_result(&self) -> Result<&C, &Self::Error> { + Ok(&self.0) + } +} + +impl ConstructorOutput for ConstructorOutputValue, Env> +where + C: FromAccountId, + Env: Environment, +{ + const IS_RESULT: bool = true; + + type Output = Result; + type Error = E; + + fn from_account_id(account_id: Env::AccountId) -> Self::Output { + Ok(C::from_account_id(account_id)) + } + + #[inline(always)] + fn as_result(&self) -> Result<&C, &Self::Error> { + self.0.as_ref() + } +} + /// A parameter that has been set to some value. #[derive(Debug, Copy, Clone)] pub struct Set(pub T); diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 0b392ae1bfd..dde38849ab3 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -15,6 +15,8 @@ use crate::{ call::{ utils::{ + ConstructorOutput, + ConstructorOutputValue, EmptyArgumentList, ReturnType, Set, @@ -152,7 +154,6 @@ where &self, ) -> Result, crate::Error> { crate::instantiate_contract(self) - .map(|inner| inner.map(FromAccountId::from_account_id)) } } diff --git a/crates/env/src/call/mod.rs b/crates/env/src/call/mod.rs index ac4ba6cc4bb..b5b24066b5c 100644 --- a/crates/env/src/call/mod.rs +++ b/crates/env/src/call/mod.rs @@ -24,6 +24,8 @@ mod selector; pub mod utils { pub use super::{ common::{ + ConstructorOutput, + ConstructorOutputValue, ReturnType, Set, Unset, diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 771d8608054..2d8b1e9c474 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -18,7 +18,12 @@ use crate::{ Call, CallParams, CreateParams, + FromAccountId, DelegateCall, + utils::{ + ConstructorOutput, + ConstructorOutputValue, + } }, hash::{ Blake2x128, @@ -472,11 +477,12 @@ impl TypedEnvBackend for EnvInstance { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result> + ) -> Result>> where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, + R: FromAccountId, { let _code_hash = params.code_hash(); let _gas_limit = params.gas_limit(); diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 3b98fa02ec9..97b89edced7 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -24,6 +24,10 @@ use crate::{ CallParams, CreateParams, DelegateCall, + utils::{ + ConstructorOutput, + ConstructorOutputValue, + } }, hash::{ Blake2x128, @@ -41,6 +45,7 @@ use crate::{ EnvBackend, Environment, Error, + FromAccountId, FromLittleEndian, Result, ReturnFlags, @@ -482,11 +487,12 @@ impl TypedEnvBackend for EnvInstance { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result> + ) -> Result>> where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, + R: FromAccountId, { let mut scoped = self.scoped_buffer(); let gas_limit = params.gas_limit(); @@ -513,17 +519,18 @@ impl TypedEnvBackend for EnvInstance { match instantiate_result { Ok(()) => { let account_id = scale::Decode::decode(&mut &out_address[..])?; - Ok(Ok(account_id)) + Ok(Ok(>::from_account_id(account_id))) } Err(ext::Error::CalleeReverted) => { // We don't wrap manually with an extra `Err` like we do in the `Ok` case since the // buffer already comes back in the form of `Err(LangError)` (assuming it's encoded // by the ink! codegen and not the contract). - let out = ink_primitives::ConstructorResult::::decode( - &mut &out_return_value[..], - )?; - assert!(out.is_err(), "The callee reverted, but did not encode an error in the output buffer."); - Ok(out) + // let out = ink_primitives::ConstructorResult::::decode( + // &mut &out_return_value[..], + // )?; + // assert!(out.is_err(), "The callee reverted, but did not encode an error in the output buffer."); + // Ok(out) + todo!("custom decoding based on ConstructorOutputValue") } Err(actual_error) => Err(actual_error.into()), } 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 a1242d5cdeb..04ec25e9a26 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -420,7 +420,8 @@ impl ContractRef<'_> { ::ink::env::call::utils::Unset, ::ink::env::call::utils::Set<::ink::env::call::ExecutionInput<#arg_list>>, ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, - ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, + ::ink::env::call::utils::Set<::ink::env::call::utils::ConstructorOutputValue<#ret_type>>, + Self, > { ::ink::env::call::build_create::() .exec_input( @@ -431,7 +432,6 @@ impl ContractRef<'_> { .push_arg(#input_bindings) )* ) - .returns::<#ret_type>() } ) } From 6f590775d3cd29a43e4a73139cc84ecb6cb7cac6 Mon Sep 17 00:00:00 2001 From: andrew Date: Sat, 14 Jan 2023 21:22:43 +0000 Subject: [PATCH 141/206] InstantiateResult blanket impl for T and Result --- crates/env/src/api.rs | 43 +----------- crates/env/src/backend.rs | 30 +------- crates/env/src/call/common.rs | 68 +++++-------------- crates/env/src/call/create_builder.rs | 53 --------------- crates/env/src/call/mod.rs | 3 +- crates/env/src/engine/off_chain/impls.rs | 32 +-------- crates/env/src/engine/on_chain/impls.rs | 16 ++--- .../generator/as_dependency/contract_ref.rs | 2 +- 8 files changed, 34 insertions(+), 213 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 518af944d7a..52f7754d9b1 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -25,8 +25,6 @@ use crate::{ CallParams, CreateParams, DelegateCall, - FromAccountId, - utils::ConstructorOutputValue, }, engine::{ EnvInstance, @@ -42,6 +40,7 @@ use crate::{ Result, }; use ink_storage_traits::Storable; +use crate::call::utils::InstantiateResult; /// Returns the address of the caller of the executed contract. /// @@ -327,54 +326,18 @@ where /// - If the returned account ID failed to decode properly. pub fn instantiate_contract( params: &CreateParams, -) -> Result>> +) -> Result>::Output>> where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: FromAccountId, + R: InstantiateResult, { ::on_instance(|instance| { TypedEnvBackend::instantiate_contract::(instance, params) }) } -/// Attempts to instantiate another contract, returning the instantiation result back to the -/// caller. -/// -/// # Note -/// -/// This is a low level way to instantiate another smart contract. -/// -/// Prefer to use methods on a `ContractRef` or the [`CreateBuilder`](`crate::call::CreateBuilder`) -/// through [`build_create`](`crate::call::build_create`) instead. -/// -/// # Errors -/// -/// - If the code hash is invalid. -/// - If the arguments passed to the instantiation process are invalid. -/// - If the instantiation process traps. -/// - If the instantiation process runs out of gas. -/// - If given insufficient endowment. -/// - If the returned account ID failed to decode properly. -pub fn instantiate_fallible_contract( - params: &CreateParams, -) -> Result< - ink_primitives::ConstructorResult>, -> -where - E: Environment, - Args: scale::Encode, - Salt: AsRef<[u8]>, - ContractError: scale::Decode, -{ - ::on_instance(|instance| { - TypedEnvBackend::instantiate_fallible_contract::( - instance, params, - ) - }) -} - /// Terminates the existence of the currently executed smart contract. /// /// This removes the calling account and transfers all remaining balance diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index d78b45ea241..081a1b88705 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -17,12 +17,8 @@ use crate::{ Call, CallParams, CreateParams, - FromAccountId, DelegateCall, - utils::{ - ConstructorOutput, - ConstructorOutputValue, - } + utils::InstantiateResult, }, hash::{ CryptoHash, @@ -447,32 +443,12 @@ pub trait TypedEnvBackend: EnvBackend { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result>> - where - E: Environment, - Args: scale::Encode, - Salt: AsRef<[u8]>, - R: FromAccountId,; - - /// Attempts to instantiate another contract, returning the instantiation result back to the - /// caller. - /// - /// # Note - /// - /// For more details visit: [`instantiate_fallible_contract`][`crate::instantiate_fallible_contract`] - fn instantiate_fallible_contract( - &mut self, - params: &CreateParams, - ) -> Result< - ink_primitives::ConstructorResult< - core::result::Result, - >, - > + ) -> Result>::Output>> where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - ContractError: scale::Decode; + R: InstantiateResult; /// Terminates a smart contract. /// diff --git a/crates/env/src/call/common.rs b/crates/env/src/call/common.rs index a2bc4addd00..e562c0e428b 100644 --- a/crates/env/src/call/common.rs +++ b/crates/env/src/call/common.rs @@ -15,8 +15,6 @@ //! Utilities, types and abstractions common to call and instantiation routines. use core::marker::PhantomData; -use crate::call::FromAccountId; -use crate::Environment; /// Represents a return type. /// @@ -54,12 +52,12 @@ mod private { /// If the contract initializer returns `Result::Err` the utility /// method that is used to initialize an ink! smart contract will /// revert the state of the contract instantiation. -pub trait ConstructorOutput: private::Sealed { +pub trait InstantiateResult: private::Sealed { /// Is `true` if `Self` is `Result`. const IS_RESULT: bool = false; /// Reflects the output type of the dispatchable ink! constructor. - type Output; + type Output; /// The error type of the constructor return type. /// @@ -69,68 +67,34 @@ pub trait ConstructorOutput: private::Sealed { /// constructors this is the actual return error type. Since we only ever /// return a value in case of `Result::Err` the `Result::Ok` value type /// does not matter. - type Error; - - // todo: docs - fn from_account_id(account_id: Env::AccountId) -> Self::Output; + type Error: scale::Decode; - /// Converts the return value into a `Result` instance. - /// - /// # Note - /// - /// For infallible constructor returns this always yields `Ok`. - fn as_result(&self) -> Result<&C, &Self::Error>; + /// todo: docs! + fn output(value: O) -> Self::Output; } -/// todo: comment -pub struct ConstructorOutputValue(T, PhantomData); +impl private::Sealed for T {} -impl ConstructorOutputValue -where - Env: Environment, -{ - pub fn new(val: T) -> Self { - Self(val, PhantomData) - } -} +impl InstantiateResult for C { + type Output = O; + type Error = (); -impl private::Sealed for ConstructorOutputValue {} - -impl ConstructorOutput for ConstructorOutputValue -where - C: FromAccountId, - Env: Environment, -{ - type Output = C; - type Error = &'static (); - - fn from_account_id(account_id: Env::AccountId) -> Self::Output { - C::from_account_id(account_id) - } - - #[inline(always)] - fn as_result(&self) -> Result<&C, &Self::Error> { - Ok(&self.0) + fn output(value: O) -> Self::Output { + value } } -impl ConstructorOutput for ConstructorOutputValue, Env> +impl InstantiateResult for Result where - C: FromAccountId, - Env: Environment, + E: scale::Decode, { const IS_RESULT: bool = true; - type Output = Result; + type Output = Result; type Error = E; - fn from_account_id(account_id: Env::AccountId) -> Self::Output { - Ok(C::from_account_id(account_id)) - } - - #[inline(always)] - fn as_result(&self) -> Result<&C, &Self::Error> { - self.0.as_ref() + fn output(value: O) -> Self::Output { + Ok(value) } } diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index dde38849ab3..bcc4eaacfdc 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -15,8 +15,6 @@ use crate::{ call::{ utils::{ - ConstructorOutput, - ConstructorOutputValue, EmptyArgumentList, ReturnType, Set, @@ -157,57 +155,6 @@ where } } -impl - CreateParams> -where - E: Environment, - Args: scale::Encode, - Salt: AsRef<[u8]>, - R: FromAccountId, - ContractError: scale::Decode, -{ - /// Attempts to instantiate the contract, returning the execution result back to the caller. - /// - /// # Panics - /// - /// This method panics if it encounters an [`ink_primitives::LangError`]. If you want to handle - /// those use the [`try_instantiate_fallible`][`CreateParams::try_instantiate_fallible`] method - /// instead. - #[inline] - pub fn instantiate_fallible(&self) -> Result { - crate::instantiate_fallible_contract(self) - .unwrap_or_else(|env_error| { - panic!("Cross-contract instantiation failed with {:?}", env_error) - }) - .unwrap_or_else(|lang_error| { - panic!( - "Received a `LangError` while instantiating: {:?}", - lang_error - ) - }) - .map(FromAccountId::from_account_id) - } - - /// Attempts to instantiate the contract, returning the execution result back to the caller. - /// - /// # Note - /// - /// On failure this returns an outer [`ink::env::Error`][`crate::Error`] or inner - /// [`ink::primitives::LangError`][`ink_primitives::LangError`], both of which can be handled - /// by the caller. - #[inline] - pub fn try_instantiate_fallible( - &self, - ) -> Result>, crate::Error> - { - crate::instantiate_fallible_contract(self).map(|constructor_result| { - constructor_result.map(|contract_result| { - contract_result.map(FromAccountId::from_account_id) - }) - }) - } -} - /// Builds up contract instantiations. pub struct CreateBuilder where diff --git a/crates/env/src/call/mod.rs b/crates/env/src/call/mod.rs index b5b24066b5c..971d0cc4d15 100644 --- a/crates/env/src/call/mod.rs +++ b/crates/env/src/call/mod.rs @@ -24,8 +24,7 @@ mod selector; pub mod utils { pub use super::{ common::{ - ConstructorOutput, - ConstructorOutputValue, + InstantiateResult, ReturnType, Set, Unset, diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 2d8b1e9c474..faab8d5154a 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -18,12 +18,8 @@ use crate::{ Call, CallParams, CreateParams, - FromAccountId, DelegateCall, - utils::{ - ConstructorOutput, - ConstructorOutputValue, - } + utils::InstantiateResult, }, hash::{ Blake2x128, @@ -477,34 +473,12 @@ impl TypedEnvBackend for EnvInstance { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result>> - where - E: Environment, - Args: scale::Encode, - Salt: AsRef<[u8]>, - R: FromAccountId, - { - let _code_hash = params.code_hash(); - let _gas_limit = params.gas_limit(); - let _endowment = params.endowment(); - let _input = params.exec_input(); - let _salt_bytes = params.salt_bytes(); - unimplemented!("off-chain environment does not support contract instantiation") - } - - fn instantiate_fallible_contract( - &mut self, - params: &CreateParams, - ) -> Result< - ink_primitives::ConstructorResult< - core::result::Result, - >, - > + ) -> Result>::Output>> where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - ContractError: scale::Decode, + R: InstantiateResult, { let _code_hash = params.code_hash(); let _gas_limit = params.gas_limit(); diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 97b89edced7..e55d3b7abaf 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -24,10 +24,7 @@ use crate::{ CallParams, CreateParams, DelegateCall, - utils::{ - ConstructorOutput, - ConstructorOutputValue, - } + utils::InstantiateResult, }, hash::{ Blake2x128, @@ -484,15 +481,15 @@ impl TypedEnvBackend for EnvInstance { } } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, - ) -> Result>> + params: &CreateParams, + ) -> Result> where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: FromAccountId, + RetType: { let mut scoped = self.scoped_buffer(); let gas_limit = params.gas_limit(); @@ -548,7 +545,6 @@ impl TypedEnvBackend for EnvInstance { E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - ContractError: scale::Decode, { let mut scoped = self.scoped_buffer(); let gas_limit = params.gas_limit(); @@ -572,6 +568,8 @@ impl TypedEnvBackend for EnvInstance { salt, ); + // todo: < + match instantiate_result { Ok(()) => { let account_id: E::AccountId = 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 04ec25e9a26..ac69f05b075 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -420,7 +420,7 @@ impl ContractRef<'_> { ::ink::env::call::utils::Unset, ::ink::env::call::utils::Set<::ink::env::call::ExecutionInput<#arg_list>>, ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, - ::ink::env::call::utils::Set<::ink::env::call::utils::ConstructorOutputValue<#ret_type>>, + ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, Self, > { ::ink::env::call::build_create::() From baecba9ab42a6bf3f0b2000508e3fcc3cabd8239 Mon Sep 17 00:00:00 2001 From: andrew Date: Sat, 14 Jan 2023 21:52:16 +0000 Subject: [PATCH 142/206] Introduce ContractRef type parameter --- crates/env/src/api.rs | 16 ++- crates/env/src/backend.rs | 16 ++- crates/env/src/call/create_builder.rs | 175 ++++++++++++++++++----- crates/env/src/engine/off_chain/impls.rs | 14 +- crates/env/src/engine/on_chain/impls.rs | 4 +- 5 files changed, 174 insertions(+), 51 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 52f7754d9b1..0f8b6ee5fbe 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -21,10 +21,12 @@ use crate::{ TypedEnvBackend, }, call::{ + utils::InstantiateResult, Call, CallParams, CreateParams, DelegateCall, + FromAccountId, }, engine::{ EnvInstance, @@ -40,7 +42,6 @@ use crate::{ Result, }; use ink_storage_traits::Storable; -use crate::call::utils::InstantiateResult; /// Returns the address of the caller of the executed contract. /// @@ -324,17 +325,22 @@ where /// - If the instantiation process runs out of gas. /// - If given insufficient endowment. /// - If the returned account ID failed to decode properly. -pub fn instantiate_contract( - params: &CreateParams, -) -> Result>::Output>> +pub fn instantiate_contract( + params: &CreateParams, +) -> Result< + ink_primitives::ConstructorResult<>::Output>, +> where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, R: InstantiateResult, + ContractRef: FromAccountId, { ::on_instance(|instance| { - TypedEnvBackend::instantiate_contract::(instance, params) + TypedEnvBackend::instantiate_contract::( + instance, params, + ) }) } diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 081a1b88705..2ac7d3e368e 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -14,11 +14,12 @@ use crate::{ call::{ + utils::InstantiateResult, Call, CallParams, CreateParams, DelegateCall, - utils::InstantiateResult, + FromAccountId, }, hash::{ CryptoHash, @@ -440,15 +441,20 @@ pub trait TypedEnvBackend: EnvBackend { /// # Note /// /// For more details visit: [`instantiate_contract`][`crate::instantiate_contract`] - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, - ) -> Result>::Output>> + params: &CreateParams, + ) -> Result< + ink_primitives::ConstructorResult< + >::Output, + >, + > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult; + R: InstantiateResult, + ContractRef: FromAccountId; /// Terminates a smart contract. /// diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index bcc4eaacfdc..84054f95dfc 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -16,6 +16,7 @@ use crate::{ call::{ utils::{ EmptyArgumentList, + InstantiateResult, ReturnType, Set, Unset, @@ -52,7 +53,7 @@ where /// Builds up contract instantiations. #[derive(Debug)] -pub struct CreateParams +pub struct CreateParams where E: Environment, { @@ -66,11 +67,13 @@ where exec_input: ExecutionInput, /// The salt for determining the hash for the contract account ID. salt_bytes: Salt, - /// The type of the instantiated contract. + /// The return type of the target contracts constructor method. _return_type: ReturnType, + /// Phantom for ContractRef: todo! + _contract_ref: PhantomData, } -impl CreateParams +impl CreateParams where E: Environment, { @@ -99,7 +102,7 @@ where } } -impl CreateParams +impl CreateParams where E: Environment, Salt: AsRef<[u8]>, @@ -111,12 +114,13 @@ where } } -impl CreateParams +impl CreateParams where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: FromAccountId, + R: InstantiateResult, + ContractRef: FromAccountId, { /// Instantiates the contract and returns its account ID back to the caller. /// @@ -126,7 +130,9 @@ where /// [`ink::primitives::LangError`][`ink_primitives::LangError`]. If you want to handle those /// use the [`try_instantiate`][`CreateParams::try_instantiate`] method instead. #[inline] - pub fn instantiate(&self) -> R { + pub fn instantiate( + &self, + ) -> Result<>::Output, crate::Error> { crate::instantiate_contract(self) .unwrap_or_else(|env_error| { panic!("Cross-contract instantiation failed with {:?}", env_error) @@ -150,14 +156,27 @@ where #[inline] pub fn try_instantiate( &self, - ) -> Result, crate::Error> { + ) -> Result< + ink_primitives::ConstructorResult< + >::Output, + >, + crate::Error, + > { crate::instantiate_contract(self) } } /// Builds up contract instantiations. -pub struct CreateBuilder -where +pub struct CreateBuilder< + E, + CodeHash, + GasLimit, + Endowment, + Args, + Salt, + RetType, + ContractRef, +> where E: Environment, { code_hash: CodeHash, @@ -166,7 +185,7 @@ where exec_input: Args, salt: Salt, return_type: RetType, - _phantom: PhantomData E>, + _phantom: PhantomData (E, ContractRef)>, } /// Returns a new [`CreateBuilder`] to build up the parameters to a cross-contract instantiation. @@ -257,7 +276,7 @@ where /// /// Note the usage of the [`CreateBuilder::instantiate_fallible`] method. #[allow(clippy::type_complexity)] -pub fn build_create() -> CreateBuilder< +pub fn build_create() -> CreateBuilder< E, Unset, Unset, @@ -265,6 +284,7 @@ pub fn build_create() -> CreateBuilder< Unset>, Unset, Unset>, + ContractRef, > where E: Environment, @@ -280,8 +300,17 @@ where } } -impl - CreateBuilder, GasLimit, Endowment, Args, Salt, RetType> +impl + CreateBuilder< + E, + Unset, + GasLimit, + Endowment, + Args, + Salt, + RetType, + ContractRef, + > where E: Environment, { @@ -290,7 +319,16 @@ where pub fn code_hash( self, code_hash: E::Hash, - ) -> CreateBuilder, GasLimit, Endowment, Args, Salt, RetType> { + ) -> CreateBuilder< + E, + Set, + GasLimit, + Endowment, + Args, + Salt, + RetType, + ContractRef, + > { CreateBuilder { code_hash: Set(code_hash), gas_limit: self.gas_limit, @@ -303,8 +341,8 @@ where } } -impl - CreateBuilder, Endowment, Args, Salt, RetType> +impl + CreateBuilder, Endowment, Args, Salt, RetType, ContractRef> where E: Environment, { @@ -313,7 +351,8 @@ where pub fn gas_limit( self, gas_limit: u64, - ) -> CreateBuilder, Endowment, Args, Salt, RetType> { + ) -> CreateBuilder, Endowment, Args, Salt, RetType, ContractRef> + { CreateBuilder { code_hash: self.code_hash, gas_limit: Set(gas_limit), @@ -326,8 +365,17 @@ where } } -impl - CreateBuilder, Args, Salt, RetType> +impl + CreateBuilder< + E, + CodeHash, + GasLimit, + Unset, + Args, + Salt, + RetType, + ContractRef, + > where E: Environment, { @@ -336,7 +384,16 @@ where pub fn endowment( self, endowment: E::Balance, - ) -> CreateBuilder, Args, Salt, RetType> { + ) -> CreateBuilder< + E, + CodeHash, + GasLimit, + Set, + Args, + Salt, + RetType, + ContractRef, + > { CreateBuilder { code_hash: self.code_hash, gas_limit: self.gas_limit, @@ -349,7 +406,7 @@ where } } -impl +impl CreateBuilder< E, CodeHash, @@ -358,6 +415,7 @@ impl Unset>, Salt, RetType, + ContractRef, > where E: Environment, @@ -375,6 +433,7 @@ where Set>, Salt, RetType, + ContractRef, > { CreateBuilder { code_hash: self.code_hash, @@ -388,8 +447,17 @@ where } } -impl - CreateBuilder, RetType> +impl + CreateBuilder< + E, + CodeHash, + GasLimit, + Endowment, + Args, + Unset, + RetType, + ContractRef, + > where E: Environment, { @@ -398,7 +466,16 @@ where pub fn salt_bytes( self, salt: Salt, - ) -> CreateBuilder, RetType> + ) -> CreateBuilder< + E, + CodeHash, + GasLimit, + Endowment, + Args, + Set, + RetType, + ContractRef, + > where Salt: AsRef<[u8]>, { @@ -414,8 +491,17 @@ where } } -impl - CreateBuilder>> +impl + CreateBuilder< + E, + CodeHash, + GasLimit, + Endowment, + Args, + Salt, + Unset>, + ContractRef, + > where E: Environment, { @@ -431,8 +517,16 @@ where #[inline] pub fn returns( self, - ) -> CreateBuilder>> - { + ) -> CreateBuilder< + E, + CodeHash, + GasLimit, + Endowment, + Args, + Salt, + Set>, + ContractRef, + > { CreateBuilder { code_hash: self.code_hash, gas_limit: self.gas_limit, @@ -445,7 +539,7 @@ where } } -impl +impl CreateBuilder< E, Set, @@ -454,6 +548,7 @@ impl Set>, Set, Set>, + ContractRef, > where E: Environment, @@ -461,7 +556,7 @@ where { /// Finalizes the create builder, allowing it to instantiate a contract. #[inline] - pub fn params(self) -> CreateParams { + pub fn params(self) -> CreateParams { CreateParams { code_hash: self.code_hash.value(), gas_limit: self.gas_limit.unwrap_or_else(|| 0), @@ -469,11 +564,12 @@ where exec_input: self.exec_input.value(), salt_bytes: self.salt.value(), _return_type: Default::default(), + _contract_ref: Default::default(), } } } -impl +impl CreateBuilder< E, Set, @@ -482,13 +578,15 @@ impl Set>, Set, Set>, + ContractRef, > where E: Environment, GasLimit: Unwrap, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType: FromAccountId, + RetType: InstantiateResult, + ContractRef: FromAccountId, { /// Instantiates the contract and returns its account ID back to the caller. /// @@ -498,7 +596,9 @@ where /// [`ink::primitives::LangError`][`ink_primitives::LangError`]. If you want to handle those /// use the [`try_instantiate`][`CreateBuilder::try_instantiate`] method instead. #[inline] - pub fn instantiate(self) -> RetType { + pub fn instantiate( + self, + ) -> Result<>::Output, Error> { self.params().instantiate() } @@ -512,7 +612,12 @@ where #[inline] pub fn try_instantiate( self, - ) -> Result, Error> { + ) -> Result< + ink_primitives::ConstructorResult< + >::Output, + >, + Error, + > { self.params().try_instantiate() } } diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index faab8d5154a..7e0a641205c 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -15,11 +15,12 @@ use super::EnvInstance; use crate::{ call::{ + utils::InstantiateResult, Call, CallParams, CreateParams, DelegateCall, - utils::InstantiateResult, + FromAccountId, }, hash::{ Blake2x128, @@ -470,15 +471,20 @@ impl TypedEnvBackend for EnvInstance { ) } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, - ) -> Result>::Output>> + params: &CreateParams, + ) -> Result< + ink_primitives::ConstructorResult< + >::Output, + >, + > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, R: InstantiateResult, + ContractRef: FromAccountId, { let _code_hash = params.code_hash(); let _gas_limit = params.gas_limit(); diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index e55d3b7abaf..25a97a6b9fa 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -20,11 +20,11 @@ use super::{ }; use crate::{ call::{ + utils::InstantiateResult, Call, CallParams, CreateParams, DelegateCall, - utils::InstantiateResult, }, hash::{ Blake2x128, @@ -489,7 +489,7 @@ impl TypedEnvBackend for EnvInstance { E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType: + RetType:, { let mut scoped = self.scoped_buffer(); let gas_limit = params.gas_limit(); From af69cd5fd733c1d7fb549654078b39948a136d34 Mon Sep 17 00:00:00 2001 From: andrew Date: Sat, 14 Jan 2023 21:59:23 +0000 Subject: [PATCH 143/206] Fix up env access --- crates/env/src/engine/on_chain/impls.rs | 9 +- crates/ink/src/env_access.rs | 105 ++---------------------- 2 files changed, 13 insertions(+), 101 deletions(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 25a97a6b9fa..759892bd6ac 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -481,15 +481,16 @@ impl TypedEnvBackend for EnvInstance { } } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, - ) -> Result> + params: &CreateParams, + ) -> Result>::Output>> where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType:, + RetType: InstantiateResult, + ContractRef: FromAccountId, { let mut scoped = self.scoped_buffer(); let gas_limit = params.gas_limit(); diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 59b3ad376b8..23d39d4851e 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -20,6 +20,8 @@ use ink_env::{ CallParams, CreateParams, DelegateCall, + FromAccountId, + utils::InstantiateResult, }, hash::{ CryptoHash, @@ -478,108 +480,17 @@ where /// # Note /// /// For more details visit: [`ink_env::instantiate_contract`] - pub fn instantiate_contract( + pub fn instantiate_contract( self, - params: &CreateParams, - ) -> Result> + params: &CreateParams, + ) -> Result>::Output>> where Args: scale::Encode, Salt: AsRef<[u8]>, + R: InstantiateResult, + ContractRef: FromAccountId, { - ink_env::instantiate_contract::(params) - } - - /// Attempts to instantiate a contract, returning the execution result back to the caller. - /// - /// # Example - /// - /// ``` - /// # #[ink::contract] - /// # pub mod my_contract { - /// # // In order for this to actually work with another contract we'd need a way - /// # // to turn the `ink-as-dependency` crate feature on in doctests, which we - /// # // can't do. - /// # // - /// # // Instead we use our own contract's `Ref`, which is fine for this example - /// # // (just need something that implements the `ContractRef` trait). - /// # pub mod other_contract { - /// # pub use super::MyContractRef as OtherContractRef; - /// # pub use super::ConstructorError as OtherConstructorError; - /// # } - /// use ink::env::{ - /// DefaultEnvironment, - /// call::{build_create, Selector, ExecutionInput} - /// }; - /// use other_contract::{OtherContractRef, OtherConstructorError}; - /// - /// # #[derive(scale::Encode, scale::Decode, Debug)] - /// # #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] - /// # pub struct ConstructorError; - /// # - /// # #[ink(storage)] - /// # pub struct MyContract { } - /// # - /// # impl MyContract { - /// # #[ink(constructor)] - /// # pub fn try_new() -> Result { - /// # Ok(Self {}) - /// # } - /// # - /// /// Attempts to instantiate a contract, returning the `AccountId` back to the caller. - /// #[ink(message)] - /// pub fn instantiate_fallible_contract(&self) -> AccountId { - /// let create_params = build_create::() - /// .code_hash(Hash::from([0x42; 32])) - /// .gas_limit(4000) - /// .endowment(25) - /// .exec_input( - /// ExecutionInput::new(Selector::new(ink::selector_bytes!("try_new"))) - /// .push_arg(42) - /// .push_arg(true) - /// .push_arg(&[0x10u8; 32]), - /// ) - /// .salt_bytes(&[0xCA, 0xFE, 0xBA, 0xBE]) - /// .returns::>() - /// .params(); - /// self.env() - /// .instantiate_fallible_contract(&create_params) - /// .unwrap_or_else(|error| { - /// panic!( - /// "Received an error from the Contracts pallet while instantiating: {:?}", - /// error - /// ) - /// }) - /// .unwrap_or_else(|error| panic!("Received a `LangError` while instatiating: {:?}", error)) - /// .unwrap_or_else(|error: ConstructorError| { - /// panic!( - /// "Received a `ConstructorError` while instatiating: {:?}", - /// error - /// ) - /// }) - /// } - /// # - /// # } - /// # } - /// ``` - /// - /// # Note - /// - /// For more details visit: [`ink_env::instantiate_fallible_contract`] - pub fn instantiate_fallible_contract( - self, - params: &CreateParams, - ) -> Result< - ink_primitives::ConstructorResult< - core::result::Result, - >, - > - where - E: Environment, - Args: scale::Encode, - Salt: AsRef<[u8]>, - ContractError: scale::Decode, - { - ink_env::instantiate_fallible_contract::(params) + ink_env::instantiate_contract::(params) } /// Invokes a contract message and returns its result. From e134a8c0e70d142eef225ac969918641300fa7e8 Mon Sep 17 00:00:00 2001 From: andrew Date: Sat, 14 Jan 2023 22:07:43 +0000 Subject: [PATCH 144/206] WIP... --- crates/env/src/engine/on_chain/impls.rs | 121 +++++++++--------- .../generator/as_dependency/contract_ref.rs | 2 +- 2 files changed, 59 insertions(+), 64 deletions(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 759892bd6ac..c7c297959b3 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -517,76 +517,71 @@ impl TypedEnvBackend for EnvInstance { match instantiate_result { Ok(()) => { let account_id = scale::Decode::decode(&mut &out_address[..])?; - Ok(Ok(>::from_account_id(account_id))) + let contract_ref = >::from_account_id(account_id); + let output = >::output(contract_ref); + Ok(ink_primitives::ConstructorResult::Ok(output)) } Err(ext::Error::CalleeReverted) => { - // We don't wrap manually with an extra `Err` like we do in the `Ok` case since the - // buffer already comes back in the form of `Err(LangError)` (assuming it's encoded - // by the ink! codegen and not the contract). - // let out = ink_primitives::ConstructorResult::::decode( - // &mut &out_return_value[..], - // )?; - // assert!(out.is_err(), "The callee reverted, but did not encode an error in the output buffer."); - // Ok(out) - todo!("custom decoding based on ConstructorOutputValue") + todo!("custom decoding based on InstantiateResult") + // if InstantiateResult::IS_RESULT, attempt to decode Result manually by first byte } Err(actual_error) => Err(actual_error.into()), } } - fn instantiate_fallible_contract( - &mut self, - params: &CreateParams, - ) -> Result< - ink_primitives::ConstructorResult< - core::result::Result, - >, - > - where - E: Environment, - Args: scale::Encode, - Salt: AsRef<[u8]>, - { - let mut scoped = self.scoped_buffer(); - let gas_limit = params.gas_limit(); - let enc_code_hash = scoped.take_encoded(params.code_hash()); - let enc_endowment = scoped.take_encoded(params.endowment()); - let enc_input = scoped.take_encoded(params.exec_input()); - // We support `AccountId` types with an encoding that requires up to - // 1024 bytes. Beyond that limit ink! contracts will trap for now. - // In the default configuration encoded `AccountId` require 32 bytes. - let out_address = &mut scoped.take(1024); - let salt = params.salt_bytes().as_ref(); - let out_return_value = &mut scoped.take_rest(); - - let instantiate_result = ext::instantiate( - enc_code_hash, - gas_limit, - enc_endowment, - enc_input, - out_address, - out_return_value, - salt, - ); - - // todo: < - - match instantiate_result { - Ok(()) => { - let account_id: E::AccountId = - scale::Decode::decode(&mut &out_address[..])?; - Ok(ink_primitives::ConstructorResult::Ok(Ok(account_id))) - } - Err(ext::Error::CalleeReverted) => { - crate::engine::decode_fallible_constructor_reverted_return_value::< - _, - E, - ContractError, - >(&mut &out_return_value[..]) - } - Err(actual_error) => Err(actual_error.into()), - } - } + // fn instantiate_fallible_contract( + // &mut self, + // params: &CreateParams, + // ) -> Result< + // ink_primitives::ConstructorResult< + // core::result::Result, + // >, + // > + // where + // E: Environment, + // Args: scale::Encode, + // Salt: AsRef<[u8]>, + // { + // let mut scoped = self.scoped_buffer(); + // let gas_limit = params.gas_limit(); + // let enc_code_hash = scoped.take_encoded(params.code_hash()); + // let enc_endowment = scoped.take_encoded(params.endowment()); + // let enc_input = scoped.take_encoded(params.exec_input()); + // // We support `AccountId` types with an encoding that requires up to + // // 1024 bytes. Beyond that limit ink! contracts will trap for now. + // // In the default configuration encoded `AccountId` require 32 bytes. + // let out_address = &mut scoped.take(1024); + // let salt = params.salt_bytes().as_ref(); + // let out_return_value = &mut scoped.take_rest(); + // + // let instantiate_result = ext::instantiate( + // enc_code_hash, + // gas_limit, + // enc_endowment, + // enc_input, + // out_address, + // out_return_value, + // salt, + // ); + // + // // todo: < + // + // match instantiate_result { + // Ok(()) => { + // let account_id: E::AccountId = + // scale::Decode::decode(&mut &out_address[..])?; + // Ok(ink_primitives::ConstructorResult::Ok(Ok(account_id))) + // } + // Err(ext::Error::CalleeReverted) => { + // crate::engine::decode_fallible_constructor_reverted_return_value::< + // _, + // E, + // ContractError, + // >(&mut &out_return_value[..]) + // } + // Err(actual_error) => Err(actual_error.into()), + // } + // } fn terminate_contract(&mut self, beneficiary: E::AccountId) -> ! where 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 ac69f05b075..c0bcb1d6623 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -423,7 +423,7 @@ impl ContractRef<'_> { ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, Self, > { - ::ink::env::call::build_create::() + ::ink::env::call::build_create::() .exec_input( ::ink::env::call::ExecutionInput::new( ::ink::env::call::Selector::new([ #( #selector_bytes ),* ]) From 115dd9ffb3e0b97206607d5c05cd59ebe0f0b9ff Mon Sep 17 00:00:00 2001 From: andrew Date: Sun, 15 Jan 2023 14:08:54 +0000 Subject: [PATCH 145/206] Make it compile --- crates/e2e/src/builders.rs | 3 ++- crates/env/src/call/create_builder.rs | 6 +++--- .../ink/codegen/src/generator/as_dependency/contract_ref.rs | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/e2e/src/builders.rs b/crates/e2e/src/builders.rs index 1ef93fba5a2..6cd518db4ec 100644 --- a/crates/e2e/src/builders.rs +++ b/crates/e2e/src/builders.rs @@ -39,7 +39,8 @@ pub type CreateBuilderPartial = CreateBuilder< Unset<::Balance>, Set>, Unset, - Set>, + Set>, + R, >; /// Get the encoded constructor arguments from the partially initialized `CreateBuilder` diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 84054f95dfc..9d2ada27ad5 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -276,14 +276,14 @@ pub struct CreateBuilder< /// /// Note the usage of the [`CreateBuilder::instantiate_fallible`] method. #[allow(clippy::type_complexity)] -pub fn build_create() -> CreateBuilder< +pub fn build_create() -> CreateBuilder< E, Unset, Unset, Unset, Unset>, Unset, - Unset>, + Set>, ContractRef, > where @@ -295,7 +295,7 @@ where endowment: Default::default(), exec_input: Default::default(), salt: Default::default(), - return_type: Default::default(), + return_type: Set(Default::default()), _phantom: Default::default(), } } 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 c0bcb1d6623..894818ea5dd 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -423,7 +423,7 @@ impl ContractRef<'_> { ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, Self, > { - ::ink::env::call::build_create::() + ::ink::env::call::build_create::() .exec_input( ::ink::env::call::ExecutionInput::new( ::ink::env::call::Selector::new([ #( #selector_bytes ),* ]) From 718d475e6c0446e77a54fbf43213582b92375072 Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 16 Jan 2023 00:15:25 +0000 Subject: [PATCH 146/206] Add ContractStorage parameter --- crates/e2e/src/builders.rs | 1 + crates/env/src/api.rs | 21 ++- crates/env/src/backend.rs | 8 +- crates/env/src/call/common.rs | 40 ++++-- crates/env/src/call/create_builder.rs | 87 ++++++++---- crates/env/src/engine/mod.rs | 133 +++++++++++++----- crates/env/src/engine/off_chain/impls.rs | 8 +- crates/env/src/engine/on_chain/impls.rs | 26 ++-- .../generator/as_dependency/contract_ref.rs | 4 +- crates/ink/src/env_access.rs | 18 ++- 10 files changed, 240 insertions(+), 106 deletions(-) diff --git a/crates/e2e/src/builders.rs b/crates/e2e/src/builders.rs index 6cd518db4ec..1089b67692d 100644 --- a/crates/e2e/src/builders.rs +++ b/crates/e2e/src/builders.rs @@ -40,6 +40,7 @@ pub type CreateBuilderPartial = CreateBuilder< Set>, Unset, Set>, + R, // todo ContractStorage param? R, >; diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 0f8b6ee5fbe..b2247560fc1 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -325,22 +325,29 @@ where /// - If the instantiation process runs out of gas. /// - If given insufficient endowment. /// - If the returned account ID failed to decode properly. -pub fn instantiate_contract( - params: &CreateParams, +pub fn instantiate_contract( + params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult< + >::Output, + >, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId, { ::on_instance(|instance| { - TypedEnvBackend::instantiate_contract::( - instance, params, - ) + TypedEnvBackend::instantiate_contract::< + E, + Args, + Salt, + R, + ContractStorage, + ContractRef, + >(instance, params) }) } diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 2ac7d3e368e..032f6ae9b07 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -441,19 +441,19 @@ pub trait TypedEnvBackend: EnvBackend { /// # Note /// /// For more details visit: [`instantiate_contract`][`crate::instantiate_contract`] - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId; /// Terminates a smart contract. diff --git a/crates/env/src/call/common.rs b/crates/env/src/call/common.rs index e562c0e428b..9b9ab2d2f02 100644 --- a/crates/env/src/call/common.rs +++ b/crates/env/src/call/common.rs @@ -60,17 +60,13 @@ pub trait InstantiateResult: private::Sealed { type Output; /// The error type of the constructor return type. - /// - /// # Note - /// - /// For infallible constructors this is `()` whereas for fallible - /// constructors this is the actual return error type. Since we only ever - /// return a value in case of `Result::Err` the `Result::Ok` value type - /// does not matter. type Error: scale::Decode; - /// todo: docs! - fn output(value: O) -> Self::Output; + /// Construct a success value of the `Output` type. + fn ok(value: O) -> Self::Output; + + /// Construct an error value of the `Output` type. + fn err(err: Self::Error) -> Self::Output; } impl private::Sealed for T {} @@ -79,9 +75,14 @@ impl InstantiateResult for C { type Output = O; type Error = (); - fn output(value: O) -> Self::Output { + fn ok(value: O) -> Self::Output { value } + + fn err(_err: Self::Error) -> Self::Output { + // todo! + unreachable!() + } } impl InstantiateResult for Result @@ -93,9 +94,13 @@ where type Output = Result; type Error = E; - fn output(value: O) -> Self::Output { + fn ok(value: O) -> Self::Output { Ok(value) } + + fn err(err: Self::Error) -> Self::Output { + Err(err) + } } /// A parameter that has been set to some value. @@ -167,3 +172,16 @@ impl Unwrap for Set { self.value() } } + +// #[cfg(test)] +// mod tests { +// use super::*; +// +// #[test] +// fn instantiate_result_types() { +// static_assertions::assert_type_eq_all!( +// Result<(), u8>, +// as InstantiateResult<()>> +// ); +// } +// } diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 9d2ada27ad5..0cc86085cba 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -53,7 +53,7 @@ where /// Builds up contract instantiations. #[derive(Debug)] -pub struct CreateParams +pub struct CreateParams where E: Environment, { @@ -68,12 +68,13 @@ where /// The salt for determining the hash for the contract account ID. salt_bytes: Salt, /// The return type of the target contracts constructor method. - _return_type: ReturnType, + _return_type: ReturnType<(R, ContractStorage)>, /// Phantom for ContractRef: todo! _contract_ref: PhantomData, } -impl CreateParams +impl + CreateParams where E: Environment, { @@ -102,7 +103,8 @@ where } } -impl CreateParams +impl + CreateParams where E: Environment, Salt: AsRef<[u8]>, @@ -114,12 +116,13 @@ where } } -impl CreateParams +impl + CreateParams where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId, { /// Instantiates the contract and returns its account ID back to the caller. @@ -158,7 +161,7 @@ where &self, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, crate::Error, > { @@ -175,6 +178,7 @@ pub struct CreateBuilder< Args, Salt, RetType, + ContractStorage, ContractRef, > where E: Environment, @@ -185,7 +189,7 @@ pub struct CreateBuilder< exec_input: Args, salt: Salt, return_type: RetType, - _phantom: PhantomData (E, ContractRef)>, + _phantom: PhantomData (E, ContractStorage, ContractRef)>, } /// Returns a new [`CreateBuilder`] to build up the parameters to a cross-contract instantiation. @@ -276,7 +280,7 @@ pub struct CreateBuilder< /// /// Note the usage of the [`CreateBuilder::instantiate_fallible`] method. #[allow(clippy::type_complexity)] -pub fn build_create() -> CreateBuilder< +pub fn build_create() -> CreateBuilder< E, Unset, Unset, @@ -284,6 +288,7 @@ pub fn build_create() -> CreateBuilder< Unset>, Unset, Set>, + ContractStorage, ContractRef, > where @@ -300,7 +305,7 @@ where } } -impl +impl CreateBuilder< E, Unset, @@ -309,6 +314,7 @@ impl Args, Salt, RetType, + ContractStorage, ContractRef, > where @@ -327,6 +333,7 @@ where Args, Salt, RetType, + ContractStorage, ContractRef, > { CreateBuilder { @@ -341,8 +348,18 @@ where } } -impl - CreateBuilder, Endowment, Args, Salt, RetType, ContractRef> +impl + CreateBuilder< + E, + CodeHash, + Unset, + Endowment, + Args, + Salt, + RetType, + ContractStorage, + ContractRef, + > where E: Environment, { @@ -351,8 +368,17 @@ where pub fn gas_limit( self, gas_limit: u64, - ) -> CreateBuilder, Endowment, Args, Salt, RetType, ContractRef> - { + ) -> CreateBuilder< + E, + CodeHash, + Set, + Endowment, + Args, + Salt, + RetType, + ContractStorage, + ContractRef, + > { CreateBuilder { code_hash: self.code_hash, gas_limit: Set(gas_limit), @@ -365,7 +391,7 @@ where } } -impl +impl CreateBuilder< E, CodeHash, @@ -374,6 +400,7 @@ impl Args, Salt, RetType, + ContractStorage, ContractRef, > where @@ -392,6 +419,7 @@ where Args, Salt, RetType, + ContractStorage, ContractRef, > { CreateBuilder { @@ -406,7 +434,7 @@ where } } -impl +impl CreateBuilder< E, CodeHash, @@ -415,6 +443,7 @@ impl Unset>, Salt, RetType, + ContractStorage, ContractRef, > where @@ -433,6 +462,7 @@ where Set>, Salt, RetType, + ContractStorage, ContractRef, > { CreateBuilder { @@ -447,7 +477,7 @@ where } } -impl +impl CreateBuilder< E, CodeHash, @@ -456,6 +486,7 @@ impl Args, Unset, RetType, + ContractStorage, ContractRef, > where @@ -474,6 +505,7 @@ where Args, Set, RetType, + ContractStorage, ContractRef, > where @@ -491,7 +523,7 @@ where } } -impl +impl CreateBuilder< E, CodeHash, @@ -500,6 +532,7 @@ impl Args, Salt, Unset>, + ContractStorage, ContractRef, > where @@ -525,6 +558,7 @@ where Args, Salt, Set>, + ContractStorage, ContractRef, > { CreateBuilder { @@ -539,7 +573,7 @@ where } } -impl +impl CreateBuilder< E, Set, @@ -548,6 +582,7 @@ impl Set>, Set, Set>, + ContractStorage, ContractRef, > where @@ -556,7 +591,9 @@ where { /// Finalizes the create builder, allowing it to instantiate a contract. #[inline] - pub fn params(self) -> CreateParams { + pub fn params( + self, + ) -> CreateParams { CreateParams { code_hash: self.code_hash.value(), gas_limit: self.gas_limit.unwrap_or_else(|| 0), @@ -569,7 +606,7 @@ where } } -impl +impl CreateBuilder< E, Set, @@ -578,6 +615,7 @@ impl Set>, Set, Set>, + ContractStorage, ContractRef, > where @@ -585,7 +623,7 @@ where GasLimit: Unwrap, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType: InstantiateResult, + RetType: InstantiateResult, ContractRef: FromAccountId, { /// Instantiates the contract and returns its account ID back to the caller. @@ -598,7 +636,8 @@ where #[inline] pub fn instantiate( self, - ) -> Result<>::Output, Error> { + ) -> Result<>::Output, Error> + { self.params().instantiate() } @@ -614,7 +653,7 @@ where self, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, Error, > { diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 440cc5b1032..158f0fa88e0 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -17,10 +17,18 @@ use crate::{ EnvBackend, TypedEnvBackend, }, + call::{ + utils::InstantiateResult, + FromAccountId, + }, Result as EnvResult, }; use cfg_if::cfg_if; -use ink_primitives::ConstructorResult; +use ink_engine::ext; +use ink_primitives::{ + ConstructorResult, + LangError, +}; pub trait OnInstance: EnvBackend + TypedEnvBackend { fn on_instance(f: F) -> R @@ -42,65 +50,118 @@ cfg_if! { } } -// The `Result` type used to represent the programmer defined contract output. -type ContractResult = core::result::Result; - // We only use this function when 1) compiling to Wasm 2) compiling for tests. #[cfg_attr(all(feature = "std", not(test)), allow(dead_code))] -pub(crate) fn decode_fallible_constructor_reverted_return_value( +pub(crate) fn decode_instantiate_result( + instantiate_result: Result<(), ext::Error>, + out_address: &mut I, out_return_value: &mut I, -) -> EnvResult>> +) -> EnvResult< + ConstructorResult<>::Output>, +> where I: scale::Input, E: crate::Environment, - ContractError: scale::Decode, + R: InstantiateResult, + ContractRef: FromAccountId, { - let out: ConstructorResult> = - scale::Decode::decode(out_return_value)?; - - match out { - ConstructorResult::Ok(ContractResult::Ok(())) => { - // Since the contract reverted we don't expect an `Ok` return value from the - // constructor, otherwise we'd be in the `AccountId` decoding branch. - // - // While we could handle this more gracefully, e.g through a `LangError`, we're going to - // be defensive for now and trap. - panic!( - "The callee reverted, but did not encode an error in the output buffer." - ) + match instantiate_result { + Ok(()) => { + let account_id = scale::Decode::decode(out_address)?; + let contract_ref = + >::from_account_id(account_id); + let output = >::ok(contract_ref); + Ok(Ok(output)) } - ConstructorResult::Ok(ContractResult::Err(contract_error)) => { - Ok(ConstructorResult::Ok(ContractResult::Err(contract_error))) + Err(ext::Error::CalleeReverted) => { + let constructor_result_variant = out_return_value.read_byte()?; + match constructor_result_variant { + // 0 == `ConstructorResult::Ok` variant + 0 => { + if >::IS_RESULT { + let result_variant = out_return_value.read_byte()?; + match result_variant { + // 0 == `Ok` variant + 0 => panic!("The callee reverted, but did not encode an error in the output buffer."), + // 1 == `Err` variant + 1 => { + let contract_err = <>::Error + as scale::Decode>::decode(out_return_value)?; + let err = >::err(contract_err); + Ok(Ok(err)) + } + _ => panic!("Invalid inner constructor Result encoding, expected 0 or 1 as the first byte") + } + } else { + panic!("The callee reverted, but did not encode an error in the output buffer.") + } + } + // 1 == `ConstructorResult::Err` variant + 1 => { + let lang_err = ::decode(out_return_value)?; + Ok(Err(lang_err)) + } + _ => panic!("Invalid outer constructor Result encoding, expected 0 or 1 as the first byte") + } } - ConstructorResult::Err(lang_error) => Ok(ConstructorResult::Err(lang_error)), + Err(actual_error) => Err(actual_error.into()), } } #[cfg(test)] mod fallible_constructor_reverted_tests { use super::*; + use crate::Environment; use scale::Encode; + // The `Result` type used to represent the programmer defined contract output. + type ContractResult = Result; + #[derive(scale::Encode, scale::Decode)] struct ContractError(String); + struct TestContractRef(::AccountId); + + impl FromAccountId for TestContractRef { + fn from_account_id(account_id: ::AccountId) -> Self { + Self(account_id) + } + } + fn encode_and_decode_return_value( return_value: ConstructorResult>, - ) -> EnvResult>> - { + ) -> EnvResult< + ConstructorResult< + Result, ContractError>, + >, + > { + let out_address = Vec::new(); let encoded_return_value = return_value.encode(); - decode_return_value(&mut &encoded_return_value[..]) + decode_return_value_fallible( + &mut &out_address[..], + &mut &encoded_return_value[..], + ) } - fn decode_return_value( - input: &mut I, - ) -> EnvResult>> - { - decode_fallible_constructor_reverted_return_value::< + fn decode_return_value_fallible( + out_address: &mut I, + out_return_value: &mut I, + ) -> EnvResult< + ConstructorResult< + Result, ContractError>, + >, + > { + decode_instantiate_result::< I, crate::DefaultEnvironment, - ContractError, - >(input) + Result<(), ContractError>, + (), + TestContractRef, + >( + Err(ext::Error::CalleeReverted), + out_address, + out_return_value, + ) } #[test] @@ -144,9 +205,13 @@ mod fallible_constructor_reverted_tests { #[test] fn invalid_bytes_in_output_buffer_fail_decoding() { + let out_address = Vec::new(); let invalid_encoded_return_value = vec![69]; - let decoded_result = decode_return_value(&mut &invalid_encoded_return_value[..]); + let decoded_result = decode_return_value_fallible( + &mut &out_address[..], + &mut &invalid_encoded_return_value[..], + ); assert!(matches!(decoded_result, Err(crate::Error::Decode(_)))) } diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 7e0a641205c..01301be38e0 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -471,19 +471,19 @@ impl TypedEnvBackend for EnvInstance { ) } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId, { let _code_hash = params.code_hash(); diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index c7c297959b3..1a3e057af03 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -484,7 +484,11 @@ impl TypedEnvBackend for EnvInstance { fn instantiate_contract( &mut self, params: &CreateParams, - ) -> Result>::Output>> + ) -> Result< + ink_primitives::ConstructorResult< + ::Output, + >, + > where E: Environment, Args: scale::Encode, @@ -504,7 +508,7 @@ impl TypedEnvBackend for EnvInstance { let salt = params.salt_bytes().as_ref(); let out_return_value = &mut scoped.take_rest(); - let instantiate_result = ext::instantiate( + let instantiate_result = out_addressext::instantiate( enc_code_hash, gas_limit, enc_endowment, @@ -514,19 +518,11 @@ impl TypedEnvBackend for EnvInstance { salt, ); - match instantiate_result { - Ok(()) => { - let account_id = scale::Decode::decode(&mut &out_address[..])?; - let contract_ref = >::from_account_id(account_id); - let output = >::output(contract_ref); - Ok(ink_primitives::ConstructorResult::Ok(output)) - } - Err(ext::Error::CalleeReverted) => { - todo!("custom decoding based on InstantiateResult") - // if InstantiateResult::IS_RESULT, attempt to decode Result manually by first byte - } - Err(actual_error) => Err(actual_error.into()), - } + crate::engine::decode_instantiate_result::<_, E, RetType, ContractError>( + instantiate_result, + &mut &out_address[..], + &mut &out_return_value[..], + ) } // fn instantiate_fallible_contract( 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 894818ea5dd..45c3f1f4d89 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -407,6 +407,7 @@ impl ContractRef<'_> { .output() .map(quote::ToTokens::to_token_stream) .unwrap_or_else(|| quote::quote! { Self }); + let storage_ident = self.contract.module().storage().ident(); quote_spanned!(span => #( #attrs )* #[inline] @@ -421,9 +422,10 @@ impl ContractRef<'_> { ::ink::env::call::utils::Set<::ink::env::call::ExecutionInput<#arg_list>>, ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, + #storage_ident, Self, > { - ::ink::env::call::build_create::() + ::ink::env::call::build_create::() .exec_input( ::ink::env::call::ExecutionInput::new( ::ink::env::call::Selector::new([ #( #selector_bytes ),* ]) diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 23d39d4851e..f9293d608d4 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -16,12 +16,12 @@ use crate::ChainExtensionInstance; use core::marker::PhantomData; use ink_env::{ call::{ + utils::InstantiateResult, Call, CallParams, CreateParams, DelegateCall, FromAccountId, - utils::InstantiateResult, }, hash::{ CryptoHash, @@ -480,17 +480,23 @@ where /// # Note /// /// For more details visit: [`ink_env::instantiate_contract`] - pub fn instantiate_contract( + pub fn instantiate_contract( self, - params: &CreateParams, - ) -> Result>::Output>> + params: &CreateParams, + ) -> Result< + ink_primitives::ConstructorResult< + >::Output, + >, + > where Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId, { - ink_env::instantiate_contract::(params) + ink_env::instantiate_contract::( + params, + ) } /// Invokes a contract message and returns its result. From bb5042ebecea920bd77bc3dde24a249b55bb8a65 Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 16 Jan 2023 00:18:07 +0000 Subject: [PATCH 147/206] Remove commented out instantiate_fallible_contract --- crates/env/src/engine/on_chain/impls.rs | 54 ------------------------- 1 file changed, 54 deletions(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 1a3e057af03..43d552f87cd 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -525,60 +525,6 @@ impl TypedEnvBackend for EnvInstance { ) } - // fn instantiate_fallible_contract( - // &mut self, - // params: &CreateParams, - // ) -> Result< - // ink_primitives::ConstructorResult< - // core::result::Result, - // >, - // > - // where - // E: Environment, - // Args: scale::Encode, - // Salt: AsRef<[u8]>, - // { - // let mut scoped = self.scoped_buffer(); - // let gas_limit = params.gas_limit(); - // let enc_code_hash = scoped.take_encoded(params.code_hash()); - // let enc_endowment = scoped.take_encoded(params.endowment()); - // let enc_input = scoped.take_encoded(params.exec_input()); - // // We support `AccountId` types with an encoding that requires up to - // // 1024 bytes. Beyond that limit ink! contracts will trap for now. - // // In the default configuration encoded `AccountId` require 32 bytes. - // let out_address = &mut scoped.take(1024); - // let salt = params.salt_bytes().as_ref(); - // let out_return_value = &mut scoped.take_rest(); - // - // let instantiate_result = ext::instantiate( - // enc_code_hash, - // gas_limit, - // enc_endowment, - // enc_input, - // out_address, - // out_return_value, - // salt, - // ); - // - // // todo: < - // - // match instantiate_result { - // Ok(()) => { - // let account_id: E::AccountId = - // scale::Decode::decode(&mut &out_address[..])?; - // Ok(ink_primitives::ConstructorResult::Ok(Ok(account_id))) - // } - // Err(ext::Error::CalleeReverted) => { - // crate::engine::decode_fallible_constructor_reverted_return_value::< - // _, - // E, - // ContractError, - // >(&mut &out_return_value[..]) - // } - // Err(actual_error) => Err(actual_error.into()), - // } - // } - fn terminate_contract(&mut self, beneficiary: E::AccountId) -> ! where E: Environment, From 528cfe0c9fe5f414ff5e3a6467e47b492b8f7aff Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 16 Jan 2023 13:43:00 +0000 Subject: [PATCH 148/206] Convert to env Error in helper --- crates/env/src/engine/mod.rs | 13 ++++++++----- crates/env/src/engine/on_chain/impls.rs | 6 +++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 158f0fa88e0..7fbd11fb1ae 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -21,10 +21,10 @@ use crate::{ utils::InstantiateResult, FromAccountId, }, + Error as EnvError, Result as EnvResult, }; use cfg_if::cfg_if; -use ink_engine::ext; use ink_primitives::{ ConstructorResult, LangError, @@ -53,7 +53,7 @@ cfg_if! { // We only use this function when 1) compiling to Wasm 2) compiling for tests. #[cfg_attr(all(feature = "std", not(test)), allow(dead_code))] pub(crate) fn decode_instantiate_result( - instantiate_result: Result<(), ext::Error>, + instantiate_result: EnvResult<()>, out_address: &mut I, out_return_value: &mut I, ) -> EnvResult< @@ -73,7 +73,7 @@ where let output = >::ok(contract_ref); Ok(Ok(output)) } - Err(ext::Error::CalleeReverted) => { + Err(EnvError::CalleeReverted) => { let constructor_result_variant = out_return_value.read_byte()?; match constructor_result_variant { // 0 == `ConstructorResult::Ok` variant @@ -111,7 +111,10 @@ where #[cfg(test)] mod fallible_constructor_reverted_tests { use super::*; - use crate::Environment; + use crate::{ + Error, + Environment, + }; use scale::Encode; // The `Result` type used to represent the programmer defined contract output. @@ -158,7 +161,7 @@ mod fallible_constructor_reverted_tests { (), TestContractRef, >( - Err(ext::Error::CalleeReverted), + Err(Error::CalleeReverted), out_address, out_return_value, ) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 43d552f87cd..dc3299564e7 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -25,6 +25,7 @@ use crate::{ CallParams, CreateParams, DelegateCall, + FromAccountId, }, hash::{ Blake2x128, @@ -42,7 +43,6 @@ use crate::{ EnvBackend, Environment, Error, - FromAccountId, FromLittleEndian, Result, ReturnFlags, @@ -508,7 +508,7 @@ impl TypedEnvBackend for EnvInstance { let salt = params.salt_bytes().as_ref(); let out_return_value = &mut scoped.take_rest(); - let instantiate_result = out_addressext::instantiate( + let instantiate_result = ext::instantiate( enc_code_hash, gas_limit, enc_endowment, @@ -519,7 +519,7 @@ impl TypedEnvBackend for EnvInstance { ); crate::engine::decode_instantiate_result::<_, E, RetType, ContractError>( - instantiate_result, + instantiate_result.map_err(Into::into), &mut &out_address[..], &mut &out_return_value[..], ) From 7b4c5e9612522b02e48da7c29dd56b9e54f05b46 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 16 Jan 2023 16:32:27 +0000 Subject: [PATCH 149/206] Return Decode errors in case of invalid Result first byte --- crates/env/src/engine/mod.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 7fbd11fb1ae..0627ce5e041 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -22,6 +22,7 @@ use crate::{ FromAccountId, }, Error as EnvError, + Error, Result as EnvResult, }; use cfg_if::cfg_if; @@ -90,7 +91,7 @@ where let err = >::err(contract_err); Ok(Ok(err)) } - _ => panic!("Invalid inner constructor Result encoding, expected 0 or 1 as the first byte") + _ => Err(Error::Decode("Invalid inner constructor Result encoding, expected 0 or 1 as the first byte".into())) } } else { panic!("The callee reverted, but did not encode an error in the output buffer.") @@ -101,7 +102,7 @@ where let lang_err = ::decode(out_return_value)?; Ok(Err(lang_err)) } - _ => panic!("Invalid outer constructor Result encoding, expected 0 or 1 as the first byte") + _ => Err(Error::Decode("Invalid outer constructor Result encoding, expected 0 or 1 as the first byte".into())) } } Err(actual_error) => Err(actual_error.into()), @@ -109,11 +110,11 @@ where } #[cfg(test)] -mod fallible_constructor_reverted_tests { +mod decode_instantiate_result_tests { use super::*; use crate::{ - Error, Environment, + Error, }; use scale::Encode; @@ -160,11 +161,7 @@ mod fallible_constructor_reverted_tests { Result<(), ContractError>, (), TestContractRef, - >( - Err(Error::CalleeReverted), - out_address, - out_return_value, - ) + >(Err(Error::CalleeReverted), out_address, out_return_value) } #[test] From 4de38f5b2d7a7080424c459c647fdba4018fdf70 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 16 Jan 2023 16:40:04 +0000 Subject: [PATCH 150/206] Fix impls::instantiate_contract --- crates/env/src/engine/on_chain/impls.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index dc3299564e7..28b5baa09db 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -481,19 +481,19 @@ impl TypedEnvBackend for EnvInstance { } } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult< - ::Output, + >::Output, >, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType: InstantiateResult, + RetType: InstantiateResult, ContractRef: FromAccountId, { let mut scoped = self.scoped_buffer(); @@ -518,7 +518,7 @@ impl TypedEnvBackend for EnvInstance { salt, ); - crate::engine::decode_instantiate_result::<_, E, RetType, ContractError>( + crate::engine::decode_instantiate_result::<_, E, RetType, ContractStorage, ContractRef>( instantiate_result.map_err(Into::into), &mut &out_address[..], &mut &out_return_value[..], From 09545fe56bfb6a5acfd337e2dc877044d2bd2b1c Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 17 Jan 2023 18:24:37 +0000 Subject: [PATCH 151/206] Remove ContractStorage generic parameter --- crates/env/src/api.rs | 21 ++--- crates/env/src/backend.rs | 10 +- crates/env/src/call/common.rs | 20 ++-- crates/env/src/call/create_builder.rs | 91 +++++-------------- crates/env/src/engine/mod.rs | 19 ++-- crates/env/src/engine/off_chain/impls.rs | 10 +- crates/env/src/engine/on_chain/impls.rs | 10 +- .../generator/as_dependency/contract_ref.rs | 3 +- crates/ink/src/env_access.rs | 4 +- crates/ink/src/reflect/contract.rs | 11 +++ 10 files changed, 77 insertions(+), 122 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index b2247560fc1..add87d2dfff 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -325,29 +325,22 @@ where /// - If the instantiation process runs out of gas. /// - If given insufficient endowment. /// - If the returned account ID failed to decode properly. -pub fn instantiate_contract( - params: &CreateParams, +pub fn instantiate_contract( + params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult< - >::Output, - >, + ink_primitives::ConstructorResult<>::Output>, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId, { ::on_instance(|instance| { - TypedEnvBackend::instantiate_contract::< - E, - Args, - Salt, - R, - ContractStorage, - ContractRef, - >(instance, params) + TypedEnvBackend::instantiate_contract::( + instance, params, + ) }) } diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 032f6ae9b07..799e1e66845 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -441,19 +441,17 @@ pub trait TypedEnvBackend: EnvBackend { /// # Note /// /// For more details visit: [`instantiate_contract`][`crate::instantiate_contract`] - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult< - >::Output, - >, + ink_primitives::ConstructorResult<>::Output>, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId; /// Terminates a smart contract. diff --git a/crates/env/src/call/common.rs b/crates/env/src/call/common.rs index 9b9ab2d2f02..d17d06de031 100644 --- a/crates/env/src/call/common.rs +++ b/crates/env/src/call/common.rs @@ -57,48 +57,48 @@ pub trait InstantiateResult: private::Sealed { const IS_RESULT: bool = false; /// Reflects the output type of the dispatchable ink! constructor. - type Output; + type Output; /// The error type of the constructor return type. type Error: scale::Decode; /// Construct a success value of the `Output` type. - fn ok(value: O) -> Self::Output; + fn ok(value: C) -> Self::Output; /// Construct an error value of the `Output` type. - fn err(err: Self::Error) -> Self::Output; + fn err(err: Self::Error) -> Self::Output; } impl private::Sealed for T {} impl InstantiateResult for C { - type Output = O; + type Output = C; type Error = (); - fn ok(value: O) -> Self::Output { + fn ok(value: C) -> Self::Output { value } - fn err(_err: Self::Error) -> Self::Output { + fn err(_err: Self::Error) -> Self::Output { // todo! unreachable!() } } -impl InstantiateResult for Result +impl InstantiateResult for core::result::Result where E: scale::Decode, { const IS_RESULT: bool = true; - type Output = Result; + type Output = core::result::Result; type Error = E; - fn ok(value: O) -> Self::Output { + fn ok(value: C) -> Self::Output { Ok(value) } - fn err(err: Self::Error) -> Self::Output { + fn err(err: Self::Error) -> Self::Output { Err(err) } } diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 0cc86085cba..f5533c6be16 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -53,7 +53,7 @@ where /// Builds up contract instantiations. #[derive(Debug)] -pub struct CreateParams +pub struct CreateParams where E: Environment, { @@ -68,13 +68,12 @@ where /// The salt for determining the hash for the contract account ID. salt_bytes: Salt, /// The return type of the target contracts constructor method. - _return_type: ReturnType<(R, ContractStorage)>, + _return_type: ReturnType, /// Phantom for ContractRef: todo! _contract_ref: PhantomData, } -impl - CreateParams +impl CreateParams where E: Environment, { @@ -103,8 +102,7 @@ where } } -impl - CreateParams +impl CreateParams where E: Environment, Salt: AsRef<[u8]>, @@ -116,13 +114,12 @@ where } } -impl - CreateParams +impl CreateParams where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId, { /// Instantiates the contract and returns its account ID back to the caller. @@ -135,7 +132,7 @@ where #[inline] pub fn instantiate( &self, - ) -> Result<>::Output, crate::Error> { + ) -> Result<>::Output, crate::Error> { crate::instantiate_contract(self) .unwrap_or_else(|env_error| { panic!("Cross-contract instantiation failed with {:?}", env_error) @@ -160,9 +157,7 @@ where pub fn try_instantiate( &self, ) -> Result< - ink_primitives::ConstructorResult< - >::Output, - >, + ink_primitives::ConstructorResult<>::Output>, crate::Error, > { crate::instantiate_contract(self) @@ -178,7 +173,6 @@ pub struct CreateBuilder< Args, Salt, RetType, - ContractStorage, ContractRef, > where E: Environment, @@ -189,7 +183,7 @@ pub struct CreateBuilder< exec_input: Args, salt: Salt, return_type: RetType, - _phantom: PhantomData (E, ContractStorage, ContractRef)>, + _phantom: PhantomData (E, ContractRef)>, } /// Returns a new [`CreateBuilder`] to build up the parameters to a cross-contract instantiation. @@ -280,7 +274,7 @@ pub struct CreateBuilder< /// /// Note the usage of the [`CreateBuilder::instantiate_fallible`] method. #[allow(clippy::type_complexity)] -pub fn build_create() -> CreateBuilder< +pub fn build_create() -> CreateBuilder< E, Unset, Unset, @@ -288,7 +282,6 @@ pub fn build_create() -> CreateBuilder< Unset>, Unset, Set>, - ContractStorage, ContractRef, > where @@ -305,7 +298,7 @@ where } } -impl +impl CreateBuilder< E, Unset, @@ -314,7 +307,6 @@ impl Args, Salt, RetType, - ContractStorage, ContractRef, > where @@ -333,7 +325,6 @@ where Args, Salt, RetType, - ContractStorage, ContractRef, > { CreateBuilder { @@ -348,18 +339,8 @@ where } } -impl - CreateBuilder< - E, - CodeHash, - Unset, - Endowment, - Args, - Salt, - RetType, - ContractStorage, - ContractRef, - > +impl + CreateBuilder, Endowment, Args, Salt, RetType, ContractRef> where E: Environment, { @@ -368,17 +349,8 @@ where pub fn gas_limit( self, gas_limit: u64, - ) -> CreateBuilder< - E, - CodeHash, - Set, - Endowment, - Args, - Salt, - RetType, - ContractStorage, - ContractRef, - > { + ) -> CreateBuilder, Endowment, Args, Salt, RetType, ContractRef> + { CreateBuilder { code_hash: self.code_hash, gas_limit: Set(gas_limit), @@ -391,7 +363,7 @@ where } } -impl +impl CreateBuilder< E, CodeHash, @@ -400,7 +372,6 @@ impl Args, Salt, RetType, - ContractStorage, ContractRef, > where @@ -419,7 +390,6 @@ where Args, Salt, RetType, - ContractStorage, ContractRef, > { CreateBuilder { @@ -434,7 +404,7 @@ where } } -impl +impl CreateBuilder< E, CodeHash, @@ -443,7 +413,6 @@ impl>, Salt, RetType, - ContractStorage, ContractRef, > where @@ -462,7 +431,6 @@ where Set>, Salt, RetType, - ContractStorage, ContractRef, > { CreateBuilder { @@ -477,7 +445,7 @@ where } } -impl +impl CreateBuilder< E, CodeHash, @@ -486,7 +454,6 @@ impl, RetType, - ContractStorage, ContractRef, > where @@ -505,7 +472,6 @@ where Args, Set, RetType, - ContractStorage, ContractRef, > where @@ -523,7 +489,7 @@ where } } -impl +impl CreateBuilder< E, CodeHash, @@ -532,7 +498,6 @@ impl Args, Salt, Unset>, - ContractStorage, ContractRef, > where @@ -558,7 +523,6 @@ where Args, Salt, Set>, - ContractStorage, ContractRef, > { CreateBuilder { @@ -573,7 +537,7 @@ where } } -impl +impl CreateBuilder< E, Set, @@ -582,7 +546,6 @@ impl Set>, Set, Set>, - ContractStorage, ContractRef, > where @@ -591,9 +554,7 @@ where { /// Finalizes the create builder, allowing it to instantiate a contract. #[inline] - pub fn params( - self, - ) -> CreateParams { + pub fn params(self) -> CreateParams { CreateParams { code_hash: self.code_hash.value(), gas_limit: self.gas_limit.unwrap_or_else(|| 0), @@ -606,7 +567,7 @@ where } } -impl +impl CreateBuilder< E, Set, @@ -615,7 +576,6 @@ impl Set>, Set, Set>, - ContractStorage, ContractRef, > where @@ -623,7 +583,7 @@ where GasLimit: Unwrap, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType: InstantiateResult, + RetType: InstantiateResult, ContractRef: FromAccountId, { /// Instantiates the contract and returns its account ID back to the caller. @@ -636,8 +596,7 @@ where #[inline] pub fn instantiate( self, - ) -> Result<>::Output, Error> - { + ) -> Result<>::Output, Error> { self.params().instantiate() } @@ -653,7 +612,7 @@ where self, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, Error, > { diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 0627ce5e041..d237933e427 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -53,17 +53,15 @@ cfg_if! { // We only use this function when 1) compiling to Wasm 2) compiling for tests. #[cfg_attr(all(feature = "std", not(test)), allow(dead_code))] -pub(crate) fn decode_instantiate_result( +pub(crate) fn decode_instantiate_result( instantiate_result: EnvResult<()>, out_address: &mut I, out_return_value: &mut I, -) -> EnvResult< - ConstructorResult<>::Output>, -> +) -> EnvResult>::Output>> where I: scale::Input, E: crate::Environment, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId, { match instantiate_result { @@ -71,7 +69,7 @@ where let account_id = scale::Decode::decode(out_address)?; let contract_ref = >::from_account_id(account_id); - let output = >::ok(contract_ref); + let output = >::ok(contract_ref); Ok(Ok(output)) } Err(EnvError::CalleeReverted) => { @@ -79,16 +77,16 @@ where match constructor_result_variant { // 0 == `ConstructorResult::Ok` variant 0 => { - if >::IS_RESULT { + if >::IS_RESULT { let result_variant = out_return_value.read_byte()?; match result_variant { // 0 == `Ok` variant 0 => panic!("The callee reverted, but did not encode an error in the output buffer."), // 1 == `Err` variant 1 => { - let contract_err = <>::Error + let contract_err = <>::Error as scale::Decode>::decode(out_return_value)?; - let err = >::err(contract_err); + let err = >::err(contract_err); Ok(Ok(err)) } _ => Err(Error::Decode("Invalid inner constructor Result encoding, expected 0 or 1 as the first byte".into())) @@ -158,8 +156,7 @@ mod decode_instantiate_result_tests { decode_instantiate_result::< I, crate::DefaultEnvironment, - Result<(), ContractError>, - (), + Result, ContractError>, TestContractRef, >(Err(Error::CalleeReverted), out_address, out_return_value) } diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 01301be38e0..06acc48dc8e 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -471,19 +471,17 @@ impl TypedEnvBackend for EnvInstance { ) } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult< - >::Output, - >, + ink_primitives::ConstructorResult<>::Output>, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId, { let _code_hash = params.code_hash(); diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 28b5baa09db..f565159ae5e 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -481,19 +481,19 @@ impl TypedEnvBackend for EnvInstance { } } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType: InstantiateResult, + RetType: InstantiateResult, ContractRef: FromAccountId, { let mut scoped = self.scoped_buffer(); @@ -518,7 +518,7 @@ impl TypedEnvBackend for EnvInstance { salt, ); - crate::engine::decode_instantiate_result::<_, E, RetType, ContractStorage, ContractRef>( + crate::engine::decode_instantiate_result::<_, E, RetType, ContractRef>( instantiate_result.map_err(Into::into), &mut &out_address[..], &mut &out_return_value[..], 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 45c3f1f4d89..b719fb7b774 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -422,10 +422,9 @@ impl ContractRef<'_> { ::ink::env::call::utils::Set<::ink::env::call::ExecutionInput<#arg_list>>, ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, - #storage_ident, Self, > { - ::ink::env::call::build_create::() + ::ink::env::call::build_create::() .exec_input( ::ink::env::call::ExecutionInput::new( ::ink::env::call::Selector::new([ #( #selector_bytes ),* ]) diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index f9293d608d4..c410c8fccc6 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -485,13 +485,13 @@ where params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, > where Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: InstantiateResult, ContractRef: FromAccountId, { ink_env::instantiate_contract::( diff --git a/crates/ink/src/reflect/contract.rs b/crates/ink/src/reflect/contract.rs index 3488980a3cf..a10da63ea24 100644 --- a/crates/ink/src/reflect/contract.rs +++ b/crates/ink/src/reflect/contract.rs @@ -177,8 +177,19 @@ pub trait ContractEnv { /// // are of the same type. /// const _: IsSameType<::Type> = /// >::new(); +/// const _: IsSameType< as ContractReference>::Type> = +/// >>::new(); /// ``` pub trait ContractReference { /// The generated contract reference type. type Type; } + +/// Blanket impl for [`ContractRef`] for mapping to the equivalent [`Result`] +/// type. Enables handling constructors which return a `Result`. +impl ContractReference for core::result::Result +where + C: ContractReference, +{ + type Type = core::result::Result<::Type, E>; +} From 2ef624d5311545823dbda6345b1c535fb7c7a03c Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 17 Jan 2023 21:26:00 +0000 Subject: [PATCH 152/206] Fix env access --- crates/ink/src/env_access.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index c410c8fccc6..c1ae9ec9c8b 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -480,12 +480,12 @@ where /// # Note /// /// For more details visit: [`ink_env::instantiate_contract`] - pub fn instantiate_contract( + pub fn instantiate_contract( self, - params: &CreateParams, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, > where @@ -494,7 +494,7 @@ where R: InstantiateResult, ContractRef: FromAccountId, { - ink_env::instantiate_contract::( + ink_env::instantiate_contract::( params, ) } From 02f97b132e6cd68e0e98a6683404b7d605187c99 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 17 Jan 2023 22:01:41 +0000 Subject: [PATCH 153/206] Use generated constructor ref, introduces update_selector --- crates/env/src/call/create_builder.rs | 9 ++++++ crates/env/src/call/execution_input.rs | 10 ++++++ .../generator/as_dependency/contract_ref.rs | 1 - crates/ink/src/env_access.rs | 8 ++--- .../call-builder/lib.rs | 31 +++++++++---------- 5 files changed, 35 insertions(+), 24 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index f5533c6be16..efff00c04c8 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -23,6 +23,7 @@ use crate::{ Unwrap, }, ExecutionInput, + Selector, }, Environment, Error, @@ -100,6 +101,14 @@ where pub fn exec_input(&self) -> &ExecutionInput { &self.exec_input } + + /// Modify the selector. + /// + /// Useful when using the [`CreateParams`] generated as part of the + /// contract ref, but using a custom selector. + pub fn update_selector(&mut self, selector: Selector) { + self.exec_input.update_selector(selector) + } } impl CreateParams diff --git a/crates/env/src/call/execution_input.rs b/crates/env/src/call/execution_input.rs index fba340ebf1c..8f3f79dd171 100644 --- a/crates/env/src/call/execution_input.rs +++ b/crates/env/src/call/execution_input.rs @@ -63,6 +63,16 @@ impl ExecutionInput, Rest>> { } } +impl ExecutionInput { + /// Modify the selector. + /// + /// Useful when using the [`ExecutionInput`] generated as part of the + /// contract ref, but using a custom selector. + pub fn update_selector(&mut self, selector: Selector) { + self.selector = selector; + } +} + /// An argument list. /// /// This type is constructed mainly at compile type via type constructions 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 b719fb7b774..894818ea5dd 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -407,7 +407,6 @@ impl ContractRef<'_> { .output() .map(quote::ToTokens::to_token_stream) .unwrap_or_else(|| quote::quote! { Self }); - let storage_ident = self.contract.module().storage().ident(); quote_spanned!(span => #( #attrs )* #[inline] diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index c1ae9ec9c8b..6ac81a53f1a 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -484,9 +484,7 @@ where self, params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult< - >::Output, - >, + ink_primitives::ConstructorResult<>::Output>, > where Args: scale::Encode, @@ -494,9 +492,7 @@ where R: InstantiateResult, ContractRef: FromAccountId, { - ink_env::instantiate_contract::( - params, - ) + ink_env::instantiate_contract::(params) } /// Invokes a contract message and returns its result. diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 6b4638d01a1..fd2b80d35e6 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -17,10 +17,10 @@ #[ink::contract] mod call_builder { + use constructors_return_value::ConstructorsReturnValueRef; use ink::env::{ call::{ build_call, - build_create, Call, ExecutionInput, Selector, @@ -99,16 +99,16 @@ mod call_builder { selector: [u8; 4], init_value: bool, ) -> Option { - let result = build_create::() + let mut params = ConstructorsReturnValueRef::new(init_value) .code_hash(code_hash) .gas_limit(0) .endowment(0) - .exec_input( - ExecutionInput::new(Selector::new(selector)).push_arg(init_value), - ) .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) - .returns::() - .params() + .params(); + + params.update_selector(Selector::new(selector)); + + let result = params .try_instantiate() .expect("Error from the Contracts pallet."); @@ -140,20 +140,17 @@ mod call_builder { ink::LangError, >, > { - let lang_result = build_create::() + let mut params = ConstructorsReturnValueRef::try_new(init_value) .code_hash(code_hash) .gas_limit(0) .endowment(0) - .exec_input( - ExecutionInput::new(Selector::new(selector)).push_arg(init_value), - ) .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) - .returns::>() - .params() - .try_instantiate_fallible() + .params(); + + params.update_selector(Selector::new(selector)); + + let lang_result = params + .try_instantiate() .expect("Error from the Contracts pallet."); Some(lang_result.map(|contract_result| { From 39b45b0efc71e12161f21b75ff50c99da0063570 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 17 Jan 2023 22:07:51 +0000 Subject: [PATCH 154/206] Fix e2e --- crates/e2e/src/builders.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/e2e/src/builders.rs b/crates/e2e/src/builders.rs index 1089b67692d..8d23ff7fd65 100644 --- a/crates/e2e/src/builders.rs +++ b/crates/e2e/src/builders.rs @@ -39,8 +39,7 @@ pub type CreateBuilderPartial = CreateBuilder< Unset<::Balance>, Set>, Unset, - Set>, - R, // todo ContractStorage param? + Set>, R, >; From dc2f7bb2b90242c70c046db70b8df286813e1969 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 17 Jan 2023 22:42:27 +0000 Subject: [PATCH 155/206] Remove commented out code --- crates/env/src/call/common.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/crates/env/src/call/common.rs b/crates/env/src/call/common.rs index d17d06de031..46a7e0cb23f 100644 --- a/crates/env/src/call/common.rs +++ b/crates/env/src/call/common.rs @@ -172,16 +172,3 @@ impl Unwrap for Set { self.value() } } - -// #[cfg(test)] -// mod tests { -// use super::*; -// -// #[test] -// fn instantiate_result_types() { -// static_assertions::assert_type_eq_all!( -// Result<(), u8>, -// as InstantiateResult<()>> -// ); -// } -// } From 39ab13f69129c22c56d29a01a562123cc3f593ae Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 18 Jan 2023 09:52:19 +0000 Subject: [PATCH 156/206] Typos --- .../constructors-return-value/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 018df58ddf9..111b1daa2c3 100644 --- a/examples/lang-err-integration-tests/constructors-return-value/lib.rs +++ b/examples/lang-err-integration-tests/constructors-return-value/lib.rs @@ -34,7 +34,7 @@ pub mod constructors_return_value { } } - /// A constructor which reverts and fills the output buffer with an erronenously encoded + /// A constructor which reverts and fills the output buffer with an erroneously encoded /// return value. #[ink(constructor)] pub fn revert_new(_init_value: bool) -> Self { @@ -44,7 +44,7 @@ pub mod constructors_return_value { ) } - /// A constructor which reverts and fills the output buffer with an erronenously encoded + /// A constructor which reverts and fills the output buffer with an erroneously encoded /// return value. #[ink(constructor)] pub fn try_revert_new(init_value: bool) -> Result { From 60e7e903ff639c11a40dbcd38384184e957eb312 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 18 Jan 2023 10:09:20 +0000 Subject: [PATCH 157/206] Clippy --- crates/env/src/engine/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index d237933e427..a89d2692c0a 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -103,7 +103,7 @@ where _ => Err(Error::Decode("Invalid outer constructor Result encoding, expected 0 or 1 as the first byte".into())) } } - Err(actual_error) => Err(actual_error.into()), + Err(actual_error) => Err(actual_error), } } From 43c2fe055391ff953c5af9fcc98e6dacb867214c Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 18 Jan 2023 10:35:58 +0000 Subject: [PATCH 158/206] Rename some instantiate_fallible --- crates/env/src/call/create_builder.rs | 7 ++----- examples/lang-err-integration-tests/contract-ref/lib.rs | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index efff00c04c8..d1b4ff47c4b 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -242,8 +242,7 @@ pub struct CreateBuilder< /// ) /// .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) /// .returns::() -/// .params() -/// .instantiate(); +/// .instantiate() /// ``` /// /// ## Example 2: Handles Result from Fallible Constructor @@ -276,9 +275,7 @@ pub struct CreateBuilder< /// ) /// .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) /// .returns::>() -/// .params() -/// .instantiate_fallible() -/// .expect("Constructor should've run without errors."); +/// .instantiate(); /// ``` /// /// Note the usage of the [`CreateBuilder::instantiate_fallible`] method. diff --git a/examples/lang-err-integration-tests/contract-ref/lib.rs b/examples/lang-err-integration-tests/contract-ref/lib.rs index b38d3ff3dd1..a6dac8aee35 100755 --- a/examples/lang-err-integration-tests/contract-ref/lib.rs +++ b/examples/lang-err-integration-tests/contract-ref/lib.rs @@ -29,7 +29,7 @@ mod contract_ref { .endowment(0) .code_hash(flipper_code_hash) .salt_bytes(salt) - .instantiate_fallible() + .instantiate() .unwrap_or_else(|error| { panic!( "Received an error from the Flipper constructor while instantiating \ From bf3055c93c3dcef78c171bc5190be5748de4e45c Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 18 Jan 2023 11:23:59 +0000 Subject: [PATCH 159/206] Restore `returns` method --- crates/env/src/call/create_builder.rs | 6 +++--- .../ink/codegen/src/generator/as_dependency/contract_ref.rs | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index d1b4ff47c4b..d3a5e188568 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -280,14 +280,14 @@ pub struct CreateBuilder< /// /// Note the usage of the [`CreateBuilder::instantiate_fallible`] method. #[allow(clippy::type_complexity)] -pub fn build_create() -> CreateBuilder< +pub fn build_create() -> CreateBuilder< E, Unset, Unset, Unset, Unset>, Unset, - Set>, + Unset>, ContractRef, > where @@ -299,7 +299,7 @@ where endowment: Default::default(), exec_input: Default::default(), salt: Default::default(), - return_type: Set(Default::default()), + return_type: Default::default(), _phantom: Default::default(), } } 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 894818ea5dd..ed5d7630cec 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -423,7 +423,7 @@ impl ContractRef<'_> { ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, Self, > { - ::ink::env::call::build_create::() + ::ink::env::call::build_create::() .exec_input( ::ink::env::call::ExecutionInput::new( ::ink::env::call::Selector::new([ #( #selector_bytes ),* ]) @@ -432,6 +432,7 @@ impl ContractRef<'_> { .push_arg(#input_bindings) )* ) + .returns::<#ret_type>() } ) } From 322ab260bcada4358de6ef5373b5c7740a6075be Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 19 Jan 2023 11:15:54 +0000 Subject: [PATCH 160/206] Remove ContractReference Result impl --- crates/ink/src/reflect/contract.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/crates/ink/src/reflect/contract.rs b/crates/ink/src/reflect/contract.rs index a10da63ea24..3488980a3cf 100644 --- a/crates/ink/src/reflect/contract.rs +++ b/crates/ink/src/reflect/contract.rs @@ -177,19 +177,8 @@ pub trait ContractEnv { /// // are of the same type. /// const _: IsSameType<::Type> = /// >::new(); -/// const _: IsSameType< as ContractReference>::Type> = -/// >>::new(); /// ``` pub trait ContractReference { /// The generated contract reference type. type Type; } - -/// Blanket impl for [`ContractRef`] for mapping to the equivalent [`Result`] -/// type. Enables handling constructors which return a `Result`. -impl ContractReference for core::result::Result -where - C: ContractReference, -{ - type Type = core::result::Result<::Type, E>; -} From e61a12b29f2514059851ff08410f75deb2ced71e Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 19 Jan 2023 18:16:49 +0000 Subject: [PATCH 161/206] WIP implementing ConstructorReturnType --- crates/env/src/api.rs | 6 +- crates/env/src/backend.rs | 6 +- crates/env/src/call/common.rs | 65 -------- crates/env/src/call/create_builder.rs | 155 +++++++++++++----- crates/env/src/call/mod.rs | 2 +- crates/env/src/engine/mod.rs | 18 +- crates/env/src/engine/off_chain/impls.rs | 6 +- .../generator/as_dependency/contract_ref.rs | 10 ++ .../constructors-return-value/lib.rs | 2 +- 9 files changed, 142 insertions(+), 128 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index add87d2dfff..a32adb93764 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -21,10 +21,10 @@ use crate::{ TypedEnvBackend, }, call::{ - utils::InstantiateResult, Call, CallParams, CreateParams, + ConstructorReturnType, DelegateCall, FromAccountId, }, @@ -328,13 +328,13 @@ where pub fn instantiate_contract( params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult<>::Output>, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: ConstructorReturnType, ContractRef: FromAccountId, { ::on_instance(|instance| { diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 799e1e66845..a8b0d256c02 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -14,9 +14,9 @@ use crate::{ call::{ - utils::InstantiateResult, Call, CallParams, + ConstructorReturnType, CreateParams, DelegateCall, FromAccountId, @@ -445,13 +445,13 @@ pub trait TypedEnvBackend: EnvBackend { &mut self, params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult<>::Output>, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: ConstructorReturnType, ContractRef: FromAccountId; /// Terminates a smart contract. diff --git a/crates/env/src/call/common.rs b/crates/env/src/call/common.rs index 46a7e0cb23f..e1cc4171a2d 100644 --- a/crates/env/src/call/common.rs +++ b/crates/env/src/call/common.rs @@ -38,71 +38,6 @@ impl Default for ReturnType { } } -mod private { - /// Seals the implementation of `ConstructorReturnType`. - pub trait Sealed {} -} - -/// Guards against using invalid contract initializer types. -/// -/// # Note -/// -/// Currently the only allowed types are `()` and `Result<(), E>` -/// where `E` is some unspecified error type. -/// If the contract initializer returns `Result::Err` the utility -/// method that is used to initialize an ink! smart contract will -/// revert the state of the contract instantiation. -pub trait InstantiateResult: private::Sealed { - /// Is `true` if `Self` is `Result`. - const IS_RESULT: bool = false; - - /// Reflects the output type of the dispatchable ink! constructor. - type Output; - - /// The error type of the constructor return type. - type Error: scale::Decode; - - /// Construct a success value of the `Output` type. - fn ok(value: C) -> Self::Output; - - /// Construct an error value of the `Output` type. - fn err(err: Self::Error) -> Self::Output; -} - -impl private::Sealed for T {} - -impl InstantiateResult for C { - type Output = C; - type Error = (); - - fn ok(value: C) -> Self::Output { - value - } - - fn err(_err: Self::Error) -> Self::Output { - // todo! - unreachable!() - } -} - -impl InstantiateResult for core::result::Result -where - E: scale::Decode, -{ - const IS_RESULT: bool = true; - - type Output = core::result::Result; - type Error = E; - - fn ok(value: C) -> Self::Output { - Ok(value) - } - - fn err(err: Self::Error) -> Self::Output { - Err(err) - } -} - /// A parameter that has been set to some value. #[derive(Debug, Copy, Clone)] pub struct Set(pub T); diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index d3a5e188568..60421826d69 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -16,7 +16,6 @@ use crate::{ call::{ utils::{ EmptyArgumentList, - InstantiateResult, ReturnType, Set, Unset, @@ -52,9 +51,74 @@ where fn from_account_id(account_id: ::AccountId) -> Self; } +/// todo! +pub trait ConstructorReturnType { + /// Is `true` if `Self` is `Result`. + const IS_RESULT: bool = false; + + /// The type of the contract returned from a constructor. + /// If a constructor returns `Self`, then `Contract = Self` + /// If a constructor returns a `Result`, then `Contract = Self`. + type Contract; + + /// The actual return type of the constructor. + /// If a constructor returns `Self`, then `Output = Self` + /// If a constructor returns a `Result`, then `Output = Result`. + type Output; + + /// The error type of the constructor return type. + type Error: scale::Decode; + + /// Construct a success value of the `Output` type. + fn ok(value: C) -> Self::Output; + + /// Construct an error value of the `Output` type. + fn err(err: Self::Error) -> Self::Output; +} + +impl ConstructorReturnType for C +where + C: FromAccountId, +{ + type Contract = C; + type Output = C; + type Error = (); + + fn ok(value: C) -> Self::Output { + value + } + + fn err(_err: Self::Error) -> Self::Output { + // todo! + unreachable!() + } +} + +impl ConstructorReturnType for core::result::Result +where + C: FromAccountId, + E: scale::Decode, +{ + const IS_RESULT: bool = true; + + type Contract = C; + type Output = core::result::Result; + type Error = E; + + fn ok(value: C) -> Self::Output { + Ok(value) + } + + fn err(err: Self::Error) -> Self::Output { + Err(err) + } +} + +// pub type InstantiateOutput = <>::Type as Instantiate + /// Builds up contract instantiations. #[derive(Debug)] -pub struct CreateParams +pub struct CreateParams where E: Environment, { @@ -70,11 +134,11 @@ where salt_bytes: Salt, /// The return type of the target contracts constructor method. _return_type: ReturnType, - /// Phantom for ContractRef: todo! - _contract_ref: PhantomData, + /// The type of the reference to the contract returned from the constructor. + _phantom: PhantomData ContractRef>, } -impl CreateParams +impl CreateParams where E: Environment, { @@ -111,7 +175,7 @@ where } } -impl CreateParams +impl CreateParams where E: Environment, Salt: AsRef<[u8]>, @@ -123,13 +187,13 @@ where } } -impl CreateParams +impl CreateParams where E: Environment, + ContractRef: FromAccountId, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, - ContractRef: FromAccountId, + R: ConstructorReturnType, { /// Instantiates the contract and returns its account ID back to the caller. /// @@ -141,7 +205,7 @@ where #[inline] pub fn instantiate( &self, - ) -> Result<>::Output, crate::Error> { + ) -> Result<>::Output, crate::Error> { crate::instantiate_contract(self) .unwrap_or_else(|env_error| { panic!("Cross-contract instantiation failed with {:?}", env_error) @@ -166,7 +230,9 @@ where pub fn try_instantiate( &self, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult< + >::Output, + >, crate::Error, > { crate::instantiate_contract(self) @@ -176,13 +242,13 @@ where /// Builds up contract instantiations. pub struct CreateBuilder< E, + ContractRef, CodeHash, GasLimit, Endowment, Args, Salt, RetType, - ContractRef, > where E: Environment, { @@ -282,16 +348,17 @@ pub struct CreateBuilder< #[allow(clippy::type_complexity)] pub fn build_create() -> CreateBuilder< E, + ContractRef, Unset, Unset, Unset, Unset>, Unset, Unset>, - ContractRef, > where E: Environment, + ContractRef: FromAccountId, { CreateBuilder { code_hash: Default::default(), @@ -304,16 +371,16 @@ where } } -impl +impl CreateBuilder< E, + ContractRef, Unset, GasLimit, Endowment, Args, Salt, RetType, - ContractRef, > where E: Environment, @@ -325,13 +392,13 @@ where code_hash: E::Hash, ) -> CreateBuilder< E, + ContractRef, Set, GasLimit, Endowment, Args, Salt, RetType, - ContractRef, > { CreateBuilder { code_hash: Set(code_hash), @@ -345,8 +412,8 @@ where } } -impl - CreateBuilder, Endowment, Args, Salt, RetType, ContractRef> +impl + CreateBuilder, Endowment, Args, Salt, RetType> where E: Environment, { @@ -355,7 +422,7 @@ where pub fn gas_limit( self, gas_limit: u64, - ) -> CreateBuilder, Endowment, Args, Salt, RetType, ContractRef> + ) -> CreateBuilder, Endowment, Args, Salt, RetType> { CreateBuilder { code_hash: self.code_hash, @@ -369,16 +436,16 @@ where } } -impl +impl CreateBuilder< E, + ContractRef, CodeHash, GasLimit, Unset, Args, Salt, RetType, - ContractRef, > where E: Environment, @@ -390,13 +457,13 @@ where endowment: E::Balance, ) -> CreateBuilder< E, + ContractRef, CodeHash, GasLimit, Set, Args, Salt, RetType, - ContractRef, > { CreateBuilder { code_hash: self.code_hash, @@ -410,16 +477,16 @@ where } } -impl +impl CreateBuilder< E, + ContractRef, CodeHash, GasLimit, Endowment, Unset>, Salt, RetType, - ContractRef, > where E: Environment, @@ -431,13 +498,13 @@ where exec_input: ExecutionInput, ) -> CreateBuilder< E, + ContractRef, CodeHash, GasLimit, Endowment, Set>, Salt, RetType, - ContractRef, > { CreateBuilder { code_hash: self.code_hash, @@ -451,16 +518,16 @@ where } } -impl +impl CreateBuilder< E, + ContractRef, CodeHash, GasLimit, Endowment, Args, Unset, RetType, - ContractRef, > where E: Environment, @@ -472,13 +539,13 @@ where salt: Salt, ) -> CreateBuilder< E, + ContractRef, CodeHash, GasLimit, Endowment, Args, Set, RetType, - ContractRef, > where Salt: AsRef<[u8]>, @@ -495,16 +562,16 @@ where } } -impl +impl CreateBuilder< E, + ContractRef, CodeHash, GasLimit, Endowment, Args, Salt, Unset>, - ContractRef, > where E: Environment, @@ -523,14 +590,18 @@ where self, ) -> CreateBuilder< E, + ContractRef, CodeHash, GasLimit, Endowment, Args, Salt, Set>, - ContractRef, - > { + > + where + ContractRef: FromAccountId, + R: ConstructorReturnType, + { CreateBuilder { code_hash: self.code_hash, gas_limit: self.gas_limit, @@ -543,16 +614,16 @@ where } } -impl +impl CreateBuilder< E, + ContractRef, Set, GasLimit, Set, Set>, Set, Set>, - ContractRef, > where E: Environment, @@ -560,7 +631,7 @@ where { /// Finalizes the create builder, allowing it to instantiate a contract. #[inline] - pub fn params(self) -> CreateParams { + pub fn params(self) -> CreateParams { CreateParams { code_hash: self.code_hash.value(), gas_limit: self.gas_limit.unwrap_or_else(|| 0), @@ -568,29 +639,29 @@ where exec_input: self.exec_input.value(), salt_bytes: self.salt.value(), _return_type: Default::default(), - _contract_ref: Default::default(), + _phantom: Default::default(), } } } -impl +impl CreateBuilder< E, + ContractRef, Set, GasLimit, Set, Set>, Set, Set>, - ContractRef, > where E: Environment, + ContractRef: FromAccountId, GasLimit: Unwrap, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType: InstantiateResult, - ContractRef: FromAccountId, + RetType: ConstructorReturnType, { /// Instantiates the contract and returns its account ID back to the caller. /// @@ -602,7 +673,7 @@ where #[inline] pub fn instantiate( self, - ) -> Result<>::Output, Error> { + ) -> Result<>::Output, Error> { self.params().instantiate() } @@ -618,7 +689,7 @@ where self, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, Error, > { diff --git a/crates/env/src/call/mod.rs b/crates/env/src/call/mod.rs index 971d0cc4d15..7d170eab2ab 100644 --- a/crates/env/src/call/mod.rs +++ b/crates/env/src/call/mod.rs @@ -24,7 +24,6 @@ mod selector; pub mod utils { pub use super::{ common::{ - InstantiateResult, ReturnType, Set, Unset, @@ -54,6 +53,7 @@ pub use self::{ CreateBuilder, CreateParams, FromAccountId, + ConstructorReturnType, }, execution_input::ExecutionInput, selector::Selector, diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index a89d2692c0a..fe08c6a1544 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -17,10 +17,7 @@ use crate::{ EnvBackend, TypedEnvBackend, }, - call::{ - utils::InstantiateResult, - FromAccountId, - }, + call::FromAccountId, Error as EnvError, Error, Result as EnvResult, @@ -30,6 +27,7 @@ use ink_primitives::{ ConstructorResult, LangError, }; +use crate::call::ConstructorReturnType; pub trait OnInstance: EnvBackend + TypedEnvBackend { fn on_instance(f: F) -> R @@ -57,11 +55,11 @@ pub(crate) fn decode_instantiate_result( instantiate_result: EnvResult<()>, out_address: &mut I, out_return_value: &mut I, -) -> EnvResult>::Output>> +) -> EnvResult>::Output>> where I: scale::Input, E: crate::Environment, - R: InstantiateResult, + R: ConstructorReturnType, ContractRef: FromAccountId, { match instantiate_result { @@ -69,7 +67,7 @@ where let account_id = scale::Decode::decode(out_address)?; let contract_ref = >::from_account_id(account_id); - let output = >::ok(contract_ref); + let output = >::ok(contract_ref); Ok(Ok(output)) } Err(EnvError::CalleeReverted) => { @@ -77,16 +75,16 @@ where match constructor_result_variant { // 0 == `ConstructorResult::Ok` variant 0 => { - if >::IS_RESULT { + if >::IS_RESULT { let result_variant = out_return_value.read_byte()?; match result_variant { // 0 == `Ok` variant 0 => panic!("The callee reverted, but did not encode an error in the output buffer."), // 1 == `Err` variant 1 => { - let contract_err = <>::Error + let contract_err = <>::Error as scale::Decode>::decode(out_return_value)?; - let err = >::err(contract_err); + let err = >::err(contract_err); Ok(Ok(err)) } _ => Err(Error::Decode("Invalid inner constructor Result encoding, expected 0 or 1 as the first byte".into())) diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 06acc48dc8e..bb17e0e5536 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -15,9 +15,9 @@ use super::EnvInstance; use crate::{ call::{ - utils::InstantiateResult, Call, CallParams, + ConstructorReturnType, CreateParams, DelegateCall, FromAccountId, @@ -475,13 +475,13 @@ impl TypedEnvBackend for EnvInstance { &mut self, params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult<>::Output>, > where E: Environment, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, + R: ConstructorReturnType, ContractRef: FromAccountId, { let _code_hash = params.code_hash(); 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 ed5d7630cec..26935e693f7 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -109,6 +109,16 @@ impl ContractRef<'_> { type Type = #ref_ident; } + impl ::ink::env::call::ConstructorReturnType for #storage_ident { + type ContractRef = #ref_ident; + type Type = #ref_ident; + } + + impl ::ink::env::call::ConstructorReturnType for ::core::result::Result<#storage_ident, E> { + type ContractRef = #ref_ident; + type Type = ::core::result::Result<#ref_ident, E>; + } + impl ::ink::reflect::ContractEnv for #ref_ident { type Env = <#storage_ident as ::ink::reflect::ContractEnv>::Env; } 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 111b1daa2c3..d088a6e348d 100644 --- a/examples/lang-err-integration-tests/constructors-return-value/lib.rs +++ b/examples/lang-err-integration-tests/constructors-return-value/lib.rs @@ -26,7 +26,7 @@ pub mod constructors_return_value { /// Fallible constructor #[ink(constructor)] - pub fn try_new(succeed: bool) -> Result { + pub fn try_new(succeed: bool) -> Result { if succeed { Ok(Self::new(true)) } else { From 62052a6c256e09639ad7ee7eb8553fa45b2a4f61 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 19 Jan 2023 21:16:01 +0000 Subject: [PATCH 162/206] Reorder ContractRef parameter, move ContractRef and ContractEnv trait to env crate --- crates/env/Cargo.toml | 3 + crates/env/src/api.rs | 8 +- crates/env/src/backend.rs | 8 +- crates/env/src/call/create_builder.rs | 11 +- crates/env/src/contract.rs | 134 +++++++++++++++++ crates/env/src/engine/mod.rs | 26 ++-- crates/env/src/engine/off_chain/impls.rs | 6 +- crates/env/src/lib.rs | 5 + .../generator/as_dependency/call_builder.rs | 4 +- .../generator/as_dependency/contract_ref.rs | 18 +-- crates/ink/codegen/src/generator/dispatch.rs | 14 +- crates/ink/codegen/src/generator/env.rs | 14 +- crates/ink/codegen/src/generator/events.rs | 2 +- .../ink/codegen/src/generator/item_impls.rs | 4 +- crates/ink/codegen/src/generator/metadata.rs | 4 +- crates/ink/codegen/src/generator/storage.rs | 4 +- .../src/generator/trait_def/call_builder.rs | 2 +- .../src/generator/trait_def/call_forwarder.rs | 2 +- .../src/generator/trait_def/definition.rs | 2 +- crates/ink/src/env_access.rs | 14 +- crates/ink/src/reflect/contract.rs | 137 +----------------- crates/ink/src/reflect/mod.rs | 6 +- crates/ink/src/reflect/trait_def/registry.rs | 2 +- .../ui/trait_def/pass/using-env-types.rs | 2 +- examples/multisig/lib.rs | 4 +- 25 files changed, 218 insertions(+), 218 deletions(-) create mode 100644 crates/env/src/contract.rs diff --git a/crates/env/Cargo.toml b/crates/env/Cargo.toml index c6ef99cf836..bacc9ba4af4 100644 --- a/crates/env/Cargo.toml +++ b/crates/env/Cargo.toml @@ -49,6 +49,9 @@ secp256k1 = { version = "0.26.0", features = ["recovery", "global-context"], opt # Never use this crate outside the off-chain environment! scale-info = { version = "2.3", default-features = false, features = ["derive"], optional = true } +[dev-dependencies] +ink = { path = "../ink" } + [features] default = ["std"] std = [ diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index a32adb93764..71539ef6534 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -325,20 +325,20 @@ where /// - If the instantiation process runs out of gas. /// - If given insufficient endowment. /// - If the returned account ID failed to decode properly. -pub fn instantiate_contract( - params: &CreateParams, +pub fn instantiate_contract( + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult<>::Output>, > where E: Environment, + ContractRef: FromAccountId, Args: scale::Encode, Salt: AsRef<[u8]>, R: ConstructorReturnType, - ContractRef: FromAccountId, { ::on_instance(|instance| { - TypedEnvBackend::instantiate_contract::( + TypedEnvBackend::instantiate_contract::( instance, params, ) }) diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index a8b0d256c02..db8e85cc15d 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -441,18 +441,18 @@ pub trait TypedEnvBackend: EnvBackend { /// # Note /// /// For more details visit: [`instantiate_contract`][`crate::instantiate_contract`] - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult<>::Output>, > where E: Environment, + ContractRef: FromAccountId, Args: scale::Encode, Salt: AsRef<[u8]>, - R: ConstructorReturnType, - ContractRef: FromAccountId; + R: ConstructorReturnType; /// Terminates a smart contract. /// diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 60421826d69..53a00d0ffef 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -24,6 +24,7 @@ use crate::{ ExecutionInput, Selector, }, + ContractEnv, Environment, Error, }; @@ -76,9 +77,9 @@ pub trait ConstructorReturnType { fn err(err: Self::Error) -> Self::Output; } -impl ConstructorReturnType for C +impl ConstructorReturnType for C where - C: FromAccountId, + C: ContractEnv + FromAccountId<::Env>, { type Contract = C; type Output = C; @@ -94,9 +95,9 @@ where } } -impl ConstructorReturnType for core::result::Result +impl ConstructorReturnType for core::result::Result where - C: FromAccountId, + C: ContractEnv + FromAccountId<::Env>, E: scale::Decode, { const IS_RESULT: bool = true; @@ -599,7 +600,7 @@ where Set>, > where - ContractRef: FromAccountId, + ContractRef: FromAccountId, R: ConstructorReturnType, { CreateBuilder { diff --git a/crates/env/src/contract.rs b/crates/env/src/contract.rs new file mode 100644 index 00000000000..9a7b168da02 --- /dev/null +++ b/crates/env/src/contract.rs @@ -0,0 +1,134 @@ +/// Stores the used host environment type of the ink! smart contract. +/// +/// # Note +/// +/// The used host environment can be altered using the `env` configuration +/// parameter in the `#[ink::contract]` parameters. For example if the user +/// wanted to use an environment type definition called `MyEnvironment` they +/// issue the ink! smart contract as follows: +/// +/// ```no_compile +/// #[ink::contract(env = MyEnvironment)] +/// ``` +/// +/// # Usage: Default Environment +/// +/// ``` +/// +/// #[ink::contract] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor() -> Self { Self {} } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// +/// use contract::Contract; +/// +/// # use ink::env::ContractEnv; +/// # use ink::codegen::utils::IsSameType; +/// +/// // The following line only compiles successfully if both +/// // `ink_env::DefaultEnvironment` and `::Env` +/// // are of the same type. +/// const _: IsSameType<::Env> = +/// >::new(); +/// ``` +/// +/// # Usage: Custom Environment +/// +/// ``` +/// # use ink_env::{Environment, DefaultEnvironment}; +/// +/// pub struct CustomEnvironment {} +/// +/// impl Environment for CustomEnvironment { +/// const MAX_EVENT_TOPICS: usize = 4; +/// +/// type AccountId = ::AccountId; +/// type Balance = u64; +/// type Hash = ::Hash; +/// type BlockNumber = u32; +/// type Timestamp = u64; +/// type ChainExtension = ::ChainExtension; +/// } +/// +/// #[ink::contract(env = super::CustomEnvironment)] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor() -> Self { Self {} } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// +/// use contract::Contract; +/// # use ink::env::ContractEnv; +/// # use ink::codegen::utils::IsSameType; +/// +/// // The following line only compiles successfully if both +/// // `CustomEnvironment` and `::Env` +/// // are of the same type. +/// const _: IsSameType<::Env> = +/// >::new(); +/// +/// fn main() {} +/// ``` +pub trait ContractEnv { + /// The environment type. + type Env: crate::Environment; +} + +/// Refers to the generated ink! smart contract reference type. +/// +/// # Note +/// +/// Given an ink! storage struct with identifier `Contract` the ink! codegen produces +/// the ink! root type `Contract` and the ink! reference type `ContractRef`. +/// +/// This trait exists so that users can avoid using a generated identifier to refer to +/// the generated reference type of the ink! smart contract. +/// +/// # Usage +/// +/// ``` +/// +/// #[ink::contract] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor() -> Self { Self {} } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// +/// use contract::{Contract, ContractRef}; +/// # use ink::codegen::utils::IsSameType; +/// # use ink::env::ContractReference; +/// +/// // The following line only compiles successfully if both +/// // `ContractReference` and `::Type` +/// // are of the same type. +/// const _: IsSameType<::Type> = +/// >::new(); +/// ``` +pub trait ContractReference { + /// The generated contract reference type. + type Type; +} \ No newline at end of file diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index fe08c6a1544..8baf2dcb004 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -51,7 +51,7 @@ cfg_if! { // We only use this function when 1) compiling to Wasm 2) compiling for tests. #[cfg_attr(all(feature = "std", not(test)), allow(dead_code))] -pub(crate) fn decode_instantiate_result( +pub(crate) fn decode_instantiate_result( instantiate_result: EnvResult<()>, out_address: &mut I, out_return_value: &mut I, @@ -59,8 +59,8 @@ pub(crate) fn decode_instantiate_result( where I: scale::Input, E: crate::Environment, - R: ConstructorReturnType, ContractRef: FromAccountId, + R: ConstructorReturnType, { match instantiate_result { Ok(()) => { @@ -109,6 +109,7 @@ where mod decode_instantiate_result_tests { use super::*; use crate::{ + DefaultEnvironment, Environment, Error, }; @@ -120,10 +121,15 @@ mod decode_instantiate_result_tests { #[derive(scale::Encode, scale::Decode)] struct ContractError(String); - struct TestContractRef(::AccountId); + type AccountId = ::AccountId; + struct TestContractRef(AccountId); + + impl crate::ContractEnv for TestContractRef { + type Env = DefaultEnvironment; + } - impl FromAccountId for TestContractRef { - fn from_account_id(account_id: ::AccountId) -> Self { + impl FromAccountId for TestContractRef { + fn from_account_id(account_id: AccountId) -> Self { Self(account_id) } } @@ -132,7 +138,7 @@ mod decode_instantiate_result_tests { return_value: ConstructorResult>, ) -> EnvResult< ConstructorResult< - Result, ContractError>, + Result, >, > { let out_address = Vec::new(); @@ -148,14 +154,14 @@ mod decode_instantiate_result_tests { out_return_value: &mut I, ) -> EnvResult< ConstructorResult< - Result, ContractError>, + Result, >, > { decode_instantiate_result::< I, - crate::DefaultEnvironment, - Result, ContractError>, - TestContractRef, + DefaultEnvironment, + TestContractRef, + Result, >(Err(Error::CalleeReverted), out_address, out_return_value) } diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index bb17e0e5536..65c727e91c4 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -471,18 +471,18 @@ impl TypedEnvBackend for EnvInstance { ) } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult<>::Output>, > where E: Environment, + ContractRef: FromAccountId, Args: scale::Encode, Salt: AsRef<[u8]>, R: ConstructorReturnType, - ContractRef: FromAccountId, { let _code_hash = params.code_hash(); let _gas_limit = params.gas_limit(); diff --git a/crates/env/src/lib.rs b/crates/env/src/lib.rs index e9d9be7dcf1..2c56eba77fe 100644 --- a/crates/env/src/lib.rs +++ b/crates/env/src/lib.rs @@ -73,6 +73,7 @@ mod arithmetic; mod backend; pub mod call; pub mod chain_extension; +mod contract; mod engine; mod error; pub mod hash; @@ -97,6 +98,10 @@ pub use self::{ CallFlags, ReturnFlags, }, + contract::{ + ContractEnv, + ContractReference, + }, error::{ Error, Result, 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 e85e52b0ee3..06ce61e4425 100644 --- a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs @@ -104,8 +104,8 @@ impl CallBuilder<'_> { type Type = #cb_ident; } - impl ::ink::reflect::ContractEnv for #cb_ident { - type Env = <#storage_ident as ::ink::reflect::ContractEnv>::Env; + impl ::ink::env::ContractEnv for #cb_ident { + type Env = <#storage_ident as ::ink::env::ContractEnv>::Env; } }; ) 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 26935e693f7..70582a17d64 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -105,22 +105,12 @@ impl ContractRef<'_> { } const _: () = { - impl ::ink::reflect::ContractReference for #storage_ident { + impl ::ink::env::ContractReference for #storage_ident { type Type = #ref_ident; } - impl ::ink::env::call::ConstructorReturnType for #storage_ident { - type ContractRef = #ref_ident; - type Type = #ref_ident; - } - - impl ::ink::env::call::ConstructorReturnType for ::core::result::Result<#storage_ident, E> { - type ContractRef = #ref_ident; - type Type = ::core::result::Result<#ref_ident, E>; - } - - impl ::ink::reflect::ContractEnv for #ref_ident { - type Env = <#storage_ident as ::ink::reflect::ContractEnv>::Env; + impl ::ink::env::ContractEnv for #ref_ident { + type Env = <#storage_ident as ::ink::env::ContractEnv>::Env; } }; ) @@ -425,13 +415,13 @@ impl ContractRef<'_> { #( #input_bindings : #input_types ),* ) -> ::ink::env::call::CreateBuilder< Environment, + Self, ::ink::env::call::utils::Unset, ::ink::env::call::utils::Unset, ::ink::env::call::utils::Unset, ::ink::env::call::utils::Set<::ink::env::call::ExecutionInput<#arg_list>>, ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, - Self, > { ::ink::env::call::build_create::() .exec_input( diff --git a/crates/ink/codegen/src/generator/dispatch.rs b/crates/ink/codegen/src/generator/dispatch.rs index 4246d982103..e7c896dcc43 100644 --- a/crates/ink/codegen/src/generator/dispatch.rs +++ b/crates/ink/codegen/src/generator/dispatch.rs @@ -171,7 +171,7 @@ impl Dispatch<'_> { quote_spanned!(span=> { ::core::primitive::u32::from_be_bytes( - <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::reflect::ContractEnv>::Env> + <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::env::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink::reflect::TraitMessageInfo<#local_id>>::SELECTOR ) @@ -352,12 +352,12 @@ impl Dispatch<'_> { let mutates = message.receiver().is_ref_mut(); let local_id = message.local_id().hex_padded_suffixed(); let payable = quote! {{ - <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::reflect::ContractEnv>::Env> + <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::env::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink::reflect::TraitMessageInfo<#local_id>>::PAYABLE }}; let selector = quote! {{ - <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::reflect::ContractEnv>::Env> + <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::env::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink::reflect::TraitMessageInfo<#local_id>>::SELECTOR }}; @@ -416,7 +416,7 @@ impl Dispatch<'_> { #[allow(clippy::nonminimal_bool)] fn deploy() { if !#any_constructor_accept_payment { - ::ink::codegen::deny_payment::<<#storage_ident as ::ink::reflect::ContractEnv>::Env>() + ::ink::codegen::deny_payment::<<#storage_ident as ::ink::env::ContractEnv>::Env>() .unwrap_or_else(|error| ::core::panic!("{}", error)) } @@ -454,7 +454,7 @@ impl Dispatch<'_> { #[allow(clippy::nonminimal_bool)] fn call() { if !#any_message_accept_payment { - ::ink::codegen::deny_payment::<<#storage_ident as ::ink::reflect::ContractEnv>::Env>() + ::ink::codegen::deny_payment::<<#storage_ident as ::ink::env::ContractEnv>::Env>() .unwrap_or_else(|error| ::core::panic!("{}", error)) } @@ -618,7 +618,7 @@ impl Dispatch<'_> { Self::#constructor_ident(input) => { if #any_constructor_accept_payment && #deny_payment { ::ink::codegen::deny_payment::< - <#storage_ident as ::ink::reflect::ContractEnv>::Env>()?; + <#storage_ident as ::ink::env::ContractEnv>::Env>()?; } let result: #constructor_output = #constructor_callable(input); @@ -822,7 +822,7 @@ impl Dispatch<'_> { Self::#message_ident(input) => { if #any_message_accept_payment && #deny_payment { ::ink::codegen::deny_payment::< - <#storage_ident as ::ink::reflect::ContractEnv>::Env>()?; + <#storage_ident as ::ink::env::ContractEnv>::Env>()?; } let result: #message_output = #message_callable(&mut contract, input); diff --git a/crates/ink/codegen/src/generator/env.rs b/crates/ink/codegen/src/generator/env.rs index a9ebd428731..31361cd9cbd 100644 --- a/crates/ink/codegen/src/generator/env.rs +++ b/crates/ink/codegen/src/generator/env.rs @@ -28,17 +28,17 @@ impl GenerateCode for Env<'_> { let env = self.contract.config().env(); let storage_ident = self.contract.module().storage().ident(); quote! { - impl ::ink::reflect::ContractEnv for #storage_ident { + impl ::ink::env::ContractEnv for #storage_ident { type Env = #env; } - type Environment = <#storage_ident as ::ink::reflect::ContractEnv>::Env; + type Environment = <#storage_ident as ::ink::env::ContractEnv>::Env; - type AccountId = <<#storage_ident as ::ink::reflect::ContractEnv>::Env as ::ink::env::Environment>::AccountId; - type Balance = <<#storage_ident as ::ink::reflect::ContractEnv>::Env as ::ink::env::Environment>::Balance; - type Hash = <<#storage_ident as ::ink::reflect::ContractEnv>::Env as ::ink::env::Environment>::Hash; - type Timestamp = <<#storage_ident as ::ink::reflect::ContractEnv>::Env as ::ink::env::Environment>::Timestamp; - type BlockNumber = <<#storage_ident as ::ink::reflect::ContractEnv>::Env as ::ink::env::Environment>::BlockNumber; + type AccountId = <<#storage_ident as ::ink::env::ContractEnv>::Env as ::ink::env::Environment>::AccountId; + type Balance = <<#storage_ident as ::ink::env::ContractEnv>::Env as ::ink::env::Environment>::Balance; + type Hash = <<#storage_ident as ::ink::env::ContractEnv>::Env as ::ink::env::Environment>::Hash; + type Timestamp = <<#storage_ident as ::ink::env::ContractEnv>::Env as ::ink::env::Environment>::Timestamp; + type BlockNumber = <<#storage_ident as ::ink::env::ContractEnv>::Env as ::ink::env::Environment>::BlockNumber; } } } diff --git a/crates/ink/codegen/src/generator/events.rs b/crates/ink/codegen/src/generator/events.rs index 62344eab8fb..1dd1613b49d 100644 --- a/crates/ink/codegen/src/generator/events.rs +++ b/crates/ink/codegen/src/generator/events.rs @@ -153,7 +153,7 @@ impl<'a> Events<'a> { let event_ident = event.ident(); let len_topics = event.fields().filter(|event| event.is_topic).count(); let max_len_topics = quote_spanned!(span=> - <<#storage_ident as ::ink::reflect::ContractEnv>::Env + <<#storage_ident as ::ink::env::ContractEnv>::Env as ::ink::env::Environment>::MAX_EVENT_TOPICS ); quote_spanned!(span=> diff --git a/crates/ink/codegen/src/generator/item_impls.rs b/crates/ink/codegen/src/generator/item_impls.rs index 673c6fe9779..819d452bd4d 100644 --- a/crates/ink/codegen/src/generator/item_impls.rs +++ b/crates/ink/codegen/src/generator/item_impls.rs @@ -91,7 +91,7 @@ impl ItemImpls<'_> { let message_guard_payable = message.is_payable().then(|| { quote_spanned!(message_span=> const _: ::ink::codegen::TraitMessagePayable<{ - <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::reflect::ContractEnv>::Env> + <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::env::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink::reflect::TraitMessageInfo<#message_local_id>>::PAYABLE }> = ::ink::codegen::TraitMessagePayable::; @@ -102,7 +102,7 @@ impl ItemImpls<'_> { quote_spanned!(message_span=> const _: ::ink::codegen::TraitMessageSelector<{ ::core::primitive::u32::from_be_bytes( - <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::reflect::ContractEnv>::Env> + <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::env::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink::reflect::TraitMessageInfo<#message_local_id>>::SELECTOR ) diff --git a/crates/ink/codegen/src/generator/metadata.rs b/crates/ink/codegen/src/generator/metadata.rs index 57e1b03a16f..717f0c35705 100644 --- a/crates/ink/codegen/src/generator/metadata.rs +++ b/crates/ink/codegen/src/generator/metadata.rs @@ -288,12 +288,12 @@ impl Metadata<'_> { let mutates = message.receiver().is_ref_mut(); let local_id = message.local_id().hex_padded_suffixed(); let is_payable = quote! {{ - <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::reflect::ContractEnv>::Env> + <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::env::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink::reflect::TraitMessageInfo<#local_id>>::PAYABLE }}; let selector = quote! {{ - <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::reflect::ContractEnv>::Env> + <<::ink::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink::env::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink::reflect::TraitMessageInfo<#local_id>>::SELECTOR }}; diff --git a/crates/ink/codegen/src/generator/storage.rs b/crates/ink/codegen/src/generator/storage.rs index dcc38a3b0f5..90d05f970b3 100644 --- a/crates/ink/codegen/src/generator/storage.rs +++ b/crates/ink/codegen/src/generator/storage.rs @@ -62,7 +62,7 @@ impl Storage<'_> { const _: () = { impl<'a> ::ink::codegen::Env for &'a #storage_ident { type EnvAccess = ::ink::EnvAccess< - 'a, <#storage_ident as ::ink::reflect::ContractEnv>::Env>; + 'a, <#storage_ident as ::ink::env::ContractEnv>::Env>; fn env(self) -> Self::EnvAccess { <::EnvAccess @@ -72,7 +72,7 @@ impl Storage<'_> { impl<'a> ::ink::codegen::StaticEnv for #storage_ident { type EnvAccess = ::ink::EnvAccess< - 'static, <#storage_ident as ::ink::reflect::ContractEnv>::Env>; + 'static, <#storage_ident as ::ink::env::ContractEnv>::Env>; fn env() -> Self::EnvAccess { <::EnvAccess diff --git a/crates/ink/codegen/src/generator/trait_def/call_builder.rs b/crates/ink/codegen/src/generator/trait_def/call_builder.rs index 4cfa4a716b7..34221367b36 100644 --- a/crates/ink/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/ink/codegen/src/generator/trait_def/call_builder.rs @@ -247,7 +247,7 @@ impl CallBuilder<'_> { let builder_ident = self.ident(); let message_impls = self.generate_ink_trait_impl_messages(); quote_spanned!(span=> - impl ::ink::reflect::ContractEnv for #builder_ident + impl ::ink::env::ContractEnv for #builder_ident where E: ::ink::env::Environment, { diff --git a/crates/ink/codegen/src/generator/trait_def/call_forwarder.rs b/crates/ink/codegen/src/generator/trait_def/call_forwarder.rs index 8fd6fc85995..9eebbce3e60 100644 --- a/crates/ink/codegen/src/generator/trait_def/call_forwarder.rs +++ b/crates/ink/codegen/src/generator/trait_def/call_forwarder.rs @@ -274,7 +274,7 @@ impl CallForwarder<'_> { let forwarder_ident = self.ident(); let message_impls = self.generate_ink_trait_impl_messages(); quote_spanned!(span=> - impl ::ink::reflect::ContractEnv for #forwarder_ident + impl ::ink::env::ContractEnv for #forwarder_ident where E: ::ink::env::Environment, { diff --git a/crates/ink/codegen/src/generator/trait_def/definition.rs b/crates/ink/codegen/src/generator/trait_def/definition.rs index f29de733f72..ea50c1b6d92 100644 --- a/crates/ink/codegen/src/generator/trait_def/definition.rs +++ b/crates/ink/codegen/src/generator/trait_def/definition.rs @@ -59,7 +59,7 @@ impl TraitDefinition<'_> { .map(Self::generate_for_message); quote_spanned!(span => #(#attrs)* - pub trait #ident: ::ink::reflect::ContractEnv { + pub trait #ident: ::ink::env::ContractEnv { /// Holds general and global information about the trait. #[doc(hidden)] #[allow(non_camel_case_types)] diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 6ac81a53f1a..50d75f7afa0 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -16,10 +16,10 @@ use crate::ChainExtensionInstance; use core::marker::PhantomData; use ink_env::{ call::{ - utils::InstantiateResult, Call, CallParams, CreateParams, + ConstructorReturnType, DelegateCall, FromAccountId, }, @@ -480,19 +480,19 @@ where /// # Note /// /// For more details visit: [`ink_env::instantiate_contract`] - pub fn instantiate_contract( + pub fn instantiate_contract( self, - params: &CreateParams, + params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult<>::Output>, > where + ContractRef: FromAccountId, Args: scale::Encode, Salt: AsRef<[u8]>, - R: InstantiateResult, - ContractRef: FromAccountId, + R: ConstructorReturnType, { - ink_env::instantiate_contract::(params) + ink_env::instantiate_contract::(params) } /// Invokes a contract message and returns its result. diff --git a/crates/ink/src/reflect/contract.rs b/crates/ink/src/reflect/contract.rs index 3488980a3cf..2e5854c4d74 100644 --- a/crates/ink/src/reflect/contract.rs +++ b/crates/ink/src/reflect/contract.rs @@ -46,139 +46,4 @@ pub trait ContractName { /// The name of the ink! smart contract. const NAME: &'static str; -} - -/// Stores the used host environment type of the ink! smart contract. -/// -/// # Note -/// -/// The used host environment can be altered using the `env` configuration -/// parameter in the `#[ink::contract]` parameters. For example if the user -/// wanted to use an environment type definition called `MyEnvironment` they -/// issue the ink! smart contract as follows: -/// -/// ```no_compile -/// #[ink::contract(env = MyEnvironment)] -/// ``` -/// -/// # Usage: Default Environment -/// -/// ``` -/// -/// #[ink::contract] -/// pub mod contract { -/// #[ink(storage)] -/// pub struct Contract {} -/// -/// impl Contract { -/// #[ink(constructor)] -/// pub fn constructor() -> Self { Self {} } -/// -/// #[ink(message)] -/// pub fn message(&self) {} -/// } -/// } -/// -/// use contract::Contract; -/// -/// # use ink::reflect::ContractEnv; -/// # use ink::codegen::utils::IsSameType; -/// -/// // The following line only compiles successfully if both -/// // `ink_env::DefaultEnvironment` and `::Env` -/// // are of the same type. -/// const _: IsSameType<::Env> = -/// >::new(); -/// ``` -/// -/// # Usage: Custom Environment -/// -/// ``` -/// # use ink_env::{Environment, DefaultEnvironment}; -/// -/// pub struct CustomEnvironment {} -/// -/// impl Environment for CustomEnvironment { -/// const MAX_EVENT_TOPICS: usize = 4; -/// -/// type AccountId = ::AccountId; -/// type Balance = u64; -/// type Hash = ::Hash; -/// type BlockNumber = u32; -/// type Timestamp = u64; -/// type ChainExtension = ::ChainExtension; -/// } -/// -/// #[ink::contract(env = super::CustomEnvironment)] -/// pub mod contract { -/// #[ink(storage)] -/// pub struct Contract {} -/// -/// impl Contract { -/// #[ink(constructor)] -/// pub fn constructor() -> Self { Self {} } -/// -/// #[ink(message)] -/// pub fn message(&self) {} -/// } -/// } -/// -/// use contract::Contract; -/// # use ink::reflect::ContractEnv; -/// # use ink::codegen::utils::IsSameType; -/// -/// // The following line only compiles successfully if both -/// // `CustomEnvironment` and `::Env` -/// // are of the same type. -/// const _: IsSameType<::Env> = -/// >::new(); -/// -/// fn main() {} -/// ``` -pub trait ContractEnv { - /// The environment type. - type Env: ::ink_env::Environment; -} - -/// Refers to the generated ink! smart contract reference type. -/// -/// # Note -/// -/// Given an ink! storage struct with identifier `Contract` the ink! codegen produces -/// the ink! root type `Contract` and the ink! reference type `ContractRef`. -/// -/// This trait exists so that users can avoid using a generated identifier to refer to -/// the generated reference type of the ink! smart contract. -/// -/// # Usage -/// -/// ``` -/// -/// #[ink::contract] -/// pub mod contract { -/// #[ink(storage)] -/// pub struct Contract {} -/// -/// impl Contract { -/// #[ink(constructor)] -/// pub fn constructor() -> Self { Self {} } -/// -/// #[ink(message)] -/// pub fn message(&self) {} -/// } -/// } -/// -/// use contract::{Contract, ContractRef}; -/// # use ink::codegen::utils::IsSameType; -/// # use ink::reflect::ContractReference; -/// -/// // The following line only compiles successfully if both -/// // `ContractReference` and `::Type` -/// // are of the same type. -/// const _: IsSameType<::Type> = -/// >::new(); -/// ``` -pub trait ContractReference { - /// The generated contract reference type. - type Type; -} +} \ No newline at end of file diff --git a/crates/ink/src/reflect/mod.rs b/crates/ink/src/reflect/mod.rs index 65f15f2e6db..0ebdb294f24 100644 --- a/crates/ink/src/reflect/mod.rs +++ b/crates/ink/src/reflect/mod.rs @@ -29,11 +29,7 @@ mod event; mod trait_def; pub use self::{ - contract::{ - ContractEnv, - ContractName, - ContractReference, - }, + contract::ContractName, dispatch::{ ConstructorOutput, ConstructorOutputValue, diff --git a/crates/ink/src/reflect/trait_def/registry.rs b/crates/ink/src/reflect/trait_def/registry.rs index 005d8eb1cc4..75044073f33 100644 --- a/crates/ink/src/reflect/trait_def/registry.rs +++ b/crates/ink/src/reflect/trait_def/registry.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::reflect::ContractEnv; +use ink_env::ContractEnv; use core::marker::PhantomData; /// Type that is guaranteed by ink! to implement all ink! trait definitions. diff --git a/crates/ink/tests/ui/trait_def/pass/using-env-types.rs b/crates/ink/tests/ui/trait_def/pass/using-env-types.rs index 2822af913e4..e1f913f3099 100644 --- a/crates/ink/tests/ui/trait_def/pass/using-env-types.rs +++ b/crates/ink/tests/ui/trait_def/pass/using-env-types.rs @@ -1,4 +1,4 @@ -use ink::reflect::ContractEnv; +use ink::env::ContractEnv; use ink_env::Environment; #[ink::trait_definition] diff --git a/examples/multisig/lib.rs b/examples/multisig/lib.rs index ea3b814e273..250db845d3c 100755 --- a/examples/multisig/lib.rs +++ b/examples/multisig/lib.rs @@ -535,7 +535,7 @@ mod multisig { self.ensure_confirmed(trans_id); let t = self.take_transaction(trans_id).expect(WRONG_TRANSACTION_ID); assert!(self.env().transferred_value() == t.transferred_value); - let result = build_call::<::Env>() + let result = build_call::<::Env>() .call_type( Call::new() .callee(t.callee) @@ -573,7 +573,7 @@ mod multisig { ) -> Result, Error> { self.ensure_confirmed(trans_id); let t = self.take_transaction(trans_id).expect(WRONG_TRANSACTION_ID); - let result = build_call::<::Env>() + let result = build_call::<::Env>() .call_type( Call::new() .callee(t.callee) From 2ed509365a462669e13c29b84f67e00ed64a2728 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 19 Jan 2023 22:19:55 +0000 Subject: [PATCH 163/206] Fmt and fix --- crates/env/src/api.rs | 2 +- crates/env/src/backend.rs | 4 +++- crates/env/src/call/mod.rs | 2 +- crates/env/src/contract.rs | 6 +++--- crates/env/src/engine/mod.rs | 18 ++++++------------ crates/env/src/engine/off_chain/impls.rs | 4 +++- crates/env/src/engine/on_chain/impls.rs | 14 +++++++------- crates/ink/src/env_access.rs | 6 ++++-- crates/ink/src/reflect/contract.rs | 2 +- crates/ink/src/reflect/trait_def/registry.rs | 2 +- 10 files changed, 30 insertions(+), 30 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 71539ef6534..cb0d25d1812 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -23,8 +23,8 @@ use crate::{ call::{ Call, CallParams, - CreateParams, ConstructorReturnType, + CreateParams, DelegateCall, FromAccountId, }, diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index db8e85cc15d..93503d1b3ae 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -445,7 +445,9 @@ pub trait TypedEnvBackend: EnvBackend { &mut self, params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult< + >::Output, + >, > where E: Environment, diff --git a/crates/env/src/call/mod.rs b/crates/env/src/call/mod.rs index 7d170eab2ab..f5fd923cef7 100644 --- a/crates/env/src/call/mod.rs +++ b/crates/env/src/call/mod.rs @@ -50,10 +50,10 @@ pub use self::{ create_builder::{ build_create, state, + ConstructorReturnType, CreateBuilder, CreateParams, FromAccountId, - ConstructorReturnType, }, execution_input::ExecutionInput, selector::Selector, diff --git a/crates/env/src/contract.rs b/crates/env/src/contract.rs index 9a7b168da02..4eef18fa49b 100644 --- a/crates/env/src/contract.rs +++ b/crates/env/src/contract.rs @@ -14,7 +14,7 @@ /// # Usage: Default Environment /// /// ``` -/// +/// /// #[ink::contract] /// pub mod contract { /// #[ink(storage)] @@ -103,7 +103,7 @@ pub trait ContractEnv { /// # Usage /// /// ``` -/// +/// /// #[ink::contract] /// pub mod contract { /// #[ink(storage)] @@ -131,4 +131,4 @@ pub trait ContractEnv { pub trait ContractReference { /// The generated contract reference type. type Type; -} \ No newline at end of file +} diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 8baf2dcb004..aa2d0e5ba61 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -17,7 +17,10 @@ use crate::{ EnvBackend, TypedEnvBackend, }, - call::FromAccountId, + call::{ + ConstructorReturnType, + FromAccountId, + }, Error as EnvError, Error, Result as EnvResult, @@ -27,7 +30,6 @@ use ink_primitives::{ ConstructorResult, LangError, }; -use crate::call::ConstructorReturnType; pub trait OnInstance: EnvBackend + TypedEnvBackend { fn on_instance(f: F) -> R @@ -136,11 +138,7 @@ mod decode_instantiate_result_tests { fn encode_and_decode_return_value( return_value: ConstructorResult>, - ) -> EnvResult< - ConstructorResult< - Result, - >, - > { + ) -> EnvResult>> { let out_address = Vec::new(); let encoded_return_value = return_value.encode(); decode_return_value_fallible( @@ -152,11 +150,7 @@ mod decode_instantiate_result_tests { fn decode_return_value_fallible( out_address: &mut I, out_return_value: &mut I, - ) -> EnvResult< - ConstructorResult< - Result, - >, - > { + ) -> EnvResult>> { decode_instantiate_result::< I, DefaultEnvironment, diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 65c727e91c4..8e4f4e8f115 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -475,7 +475,9 @@ impl TypedEnvBackend for EnvInstance { &mut self, params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult< + >::Output, + >, > where E: Environment, diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index f565159ae5e..fec97b6ddf3 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -20,9 +20,9 @@ use super::{ }; use crate::{ call::{ - utils::InstantiateResult, Call, CallParams, + ConstructorReturnType, CreateParams, DelegateCall, FromAccountId, @@ -481,20 +481,20 @@ impl TypedEnvBackend for EnvInstance { } } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult< - >::Output, + >::Output, >, > where E: Environment, + ContractRef: FromAccountId, Args: scale::Encode, Salt: AsRef<[u8]>, - RetType: InstantiateResult, - ContractRef: FromAccountId, + RetType: ConstructorReturnType, { let mut scoped = self.scoped_buffer(); let gas_limit = params.gas_limit(); @@ -518,7 +518,7 @@ impl TypedEnvBackend for EnvInstance { salt, ); - crate::engine::decode_instantiate_result::<_, E, RetType, ContractRef>( + crate::engine::decode_instantiate_result::<_, E, ContractRef, RetType>( instantiate_result.map_err(Into::into), &mut &out_address[..], &mut &out_return_value[..], diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 50d75f7afa0..6e6683a93e2 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -18,8 +18,8 @@ use ink_env::{ call::{ Call, CallParams, - CreateParams, ConstructorReturnType, + CreateParams, DelegateCall, FromAccountId, }, @@ -484,7 +484,9 @@ where self, params: &CreateParams, ) -> Result< - ink_primitives::ConstructorResult<>::Output>, + ink_primitives::ConstructorResult< + >::Output, + >, > where ContractRef: FromAccountId, diff --git a/crates/ink/src/reflect/contract.rs b/crates/ink/src/reflect/contract.rs index 2e5854c4d74..5c81a4f82e1 100644 --- a/crates/ink/src/reflect/contract.rs +++ b/crates/ink/src/reflect/contract.rs @@ -46,4 +46,4 @@ pub trait ContractName { /// The name of the ink! smart contract. const NAME: &'static str; -} \ No newline at end of file +} diff --git a/crates/ink/src/reflect/trait_def/registry.rs b/crates/ink/src/reflect/trait_def/registry.rs index 75044073f33..933b70324c8 100644 --- a/crates/ink/src/reflect/trait_def/registry.rs +++ b/crates/ink/src/reflect/trait_def/registry.rs @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use ink_env::ContractEnv; use core::marker::PhantomData; +use ink_env::ContractEnv; /// Type that is guaranteed by ink! to implement all ink! trait definitions. /// From df4a067f4da930c9b3b9e6b4ede435a8b6067e89 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 19 Jan 2023 22:23:39 +0000 Subject: [PATCH 164/206] Remove E param from build_create --- crates/env/src/call/create_builder.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 53a00d0ffef..cb6cd5b3345 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -347,19 +347,18 @@ pub struct CreateBuilder< /// /// Note the usage of the [`CreateBuilder::instantiate_fallible`] method. #[allow(clippy::type_complexity)] -pub fn build_create() -> CreateBuilder< - E, +pub fn build_create() -> CreateBuilder< + ::Env, ContractRef, - Unset, + Unset<<::Env as Environment>::Hash>, Unset, - Unset, + Unset<<::Env as Environment>::Balance>, Unset>, Unset, Unset>, > where - E: Environment, - ContractRef: FromAccountId, + ContractRef: ContractEnv, { CreateBuilder { code_hash: Default::default(), From 0e69431da85860d3f3374e48ed60473fef7b49cd Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 10:18:00 +0000 Subject: [PATCH 165/206] Fix up build_create --- crates/env/src/call/create_builder.rs | 4 ++-- .../ink/codegen/src/generator/as_dependency/contract_ref.rs | 2 +- crates/ink/src/env_access.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index cb6cd5b3345..1adaac9504e 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -297,7 +297,7 @@ pub struct CreateBuilder< /// # impl FromAccountId for MyContract { /// # fn from_account_id(account_id: AccountId) -> Self { Self } /// # } -/// let my_contract: MyContract = build_create::() +/// let my_contract: MyContract = build_create::() /// .code_hash(Hash::from([0x42; 32])) /// .gas_limit(4000) /// .endowment(25) @@ -330,7 +330,7 @@ pub struct CreateBuilder< /// # #[derive(scale::Encode, scale::Decode, Debug)] /// # #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] /// # pub struct ConstructorError; -/// let my_contract: MyContract = build_create::() +/// let my_contract: MyContract = build_create::() /// .code_hash(Hash::from([0x42; 32])) /// .gas_limit(4000) /// .endowment(25) 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 70582a17d64..36ace3db4d3 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -423,7 +423,7 @@ impl ContractRef<'_> { ::ink::env::call::utils::Unset<::ink::env::call::state::Salt>, ::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>, > { - ::ink::env::call::build_create::() + ::ink::env::call::build_create::() .exec_input( ::ink::env::call::ExecutionInput::new( ::ink::env::call::Selector::new([ #( #selector_bytes ),* ]) diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 6e6683a93e2..4e9ac49d20a 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -446,7 +446,7 @@ where /// /// Instantiates another contract. /// #[ink(message)] /// pub fn instantiate_contract(&self) -> AccountId { - /// let create_params = build_create::() + /// let create_params = build_create::() /// .code_hash(Hash::from([0x42; 32])) /// .gas_limit(4000) /// .endowment(25) From e8feae91af6da7b6c169925de259a9f435618d96 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 10:37:02 +0000 Subject: [PATCH 166/206] Fix up e2e creat builder --- crates/e2e/src/builders.rs | 13 ++++++++----- crates/e2e/src/client.rs | 12 ++++++------ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/crates/e2e/src/builders.rs b/crates/e2e/src/builders.rs index 8d23ff7fd65..4a9f468722c 100644 --- a/crates/e2e/src/builders.rs +++ b/crates/e2e/src/builders.rs @@ -32,21 +32,24 @@ use scale::Encode; /// The type returned from `ContractRef` constructors, partially initialized with the execution /// input arguments. -pub type CreateBuilderPartial = CreateBuilder< +pub type CreateBuilderPartial = CreateBuilder< E, + ContractRef, Unset<::Hash>, Unset, Unset<::Balance>, Set>, Unset, Set>, - R, >; /// Get the encoded constructor arguments from the partially initialized `CreateBuilder` -pub fn constructor_exec_input( - builder: CreateBuilderPartial, -) -> Vec { +pub fn constructor_exec_input( + builder: CreateBuilderPartial, +) -> Vec +where + E: Environment +{ // set all the other properties to default values, we only require the `exec_input`. builder .endowment(0u32.into()) diff --git a/crates/e2e/src/client.rs b/crates/e2e/src/client.rs index d6bc75a80b1..d38433e6e4c 100644 --- a/crates/e2e/src/client.rs +++ b/crates/e2e/src/client.rs @@ -350,11 +350,11 @@ where /// Calling this function multiple times is idempotent, the contract is /// newly instantiated each time using a unique salt. No existing contract /// instance is reused! - pub async fn instantiate( + pub async fn instantiate( &mut self, contract_name: &str, signer: &Signer, - constructor: CreateBuilderPartial, + constructor: CreateBuilderPartial, value: E::Balance, storage_deposit_limit: Option, ) -> Result, Error> @@ -374,11 +374,11 @@ where } /// Dry run contract instantiation using the given constructor. - pub async fn instantiate_dry_run( + pub async fn instantiate_dry_run( &mut self, contract_name: &str, signer: &Signer, - constructor: CreateBuilderPartial, + constructor: CreateBuilderPartial, value: E::Balance, storage_deposit_limit: Option, ) -> ContractInstantiateResult @@ -406,11 +406,11 @@ where } /// Executes an `instantiate_with_code` call and captures the resulting events. - async fn exec_instantiate( + async fn exec_instantiate( &mut self, signer: &Signer, code: Vec, - constructor: CreateBuilderPartial, + constructor: CreateBuilderPartial, value: E::Balance, storage_deposit_limit: Option, ) -> Result, Error> From 22652588bbd5cbc6b46e88d0881ca3f415f4e1ec Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 11:22:17 +0000 Subject: [PATCH 167/206] Implement ContstructorReturnType for the storage_ident --- crates/env/src/call/create_builder.rs | 25 ++++++-------- .../generator/as_dependency/contract_ref.rs | 34 +++++++++++++++++++ 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 1adaac9504e..d1a481713fa 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -12,22 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{ - call::{ - utils::{ - EmptyArgumentList, - ReturnType, - Set, - Unset, - Unwrap, - }, - ExecutionInput, - Selector, +use crate::{call::{ + utils::{ + EmptyArgumentList, + ReturnType, + Set, + Unset, + Unwrap, }, - ContractEnv, - Environment, - Error, -}; + ExecutionInput, + Selector, +}, ContractEnv, Environment, Error}; use core::marker::PhantomData; pub mod state { 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 36ace3db4d3..cfe0ce0512e 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -109,6 +109,40 @@ impl ContractRef<'_> { type Type = #ref_ident; } + impl ::ink::env::call::ConstructorReturnType<#ref_ident> for #storage_ident { + type Contract = #ref_ident; + type Output = #ref_ident; + type Error = (); + + fn ok(value: #ref_ident) -> Self::Output { + value + } + + fn err(_err: Self::Error) -> Self::Output { + // todo! + unreachable!() + } + } + + impl ::ink::env::call::ConstructorReturnType<#ref_ident> for Result<#storage_ident, E> + where + E: ::scale::Decode + { + const IS_RESULT: bool = true; + + type Contract = #ref_ident; + type Output = ::core::result::Result<#ref_ident, E>; + type Error = E; + + fn ok(value: #ref_ident) -> Self::Output { + Ok(value) + } + + fn err(err: Self::Error) -> Self::Output { + Err(err) + } + } + impl ::ink::env::ContractEnv for #ref_ident { type Env = <#storage_ident as ::ink::env::ContractEnv>::Env; } From 10d7268868eb6d3cf185ac7e56007c8d9afb845b Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 11:23:35 +0000 Subject: [PATCH 168/206] Fmt --- crates/e2e/src/builders.rs | 2 +- crates/env/src/call/create_builder.rs | 25 +++++++++++++++---------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/crates/e2e/src/builders.rs b/crates/e2e/src/builders.rs index 4a9f468722c..f0ae3b36eaf 100644 --- a/crates/e2e/src/builders.rs +++ b/crates/e2e/src/builders.rs @@ -48,7 +48,7 @@ pub fn constructor_exec_input( builder: CreateBuilderPartial, ) -> Vec where - E: Environment + E: Environment, { // set all the other properties to default values, we only require the `exec_input`. builder diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index d1a481713fa..1adaac9504e 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -12,17 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{call::{ - utils::{ - EmptyArgumentList, - ReturnType, - Set, - Unset, - Unwrap, +use crate::{ + call::{ + utils::{ + EmptyArgumentList, + ReturnType, + Set, + Unset, + Unwrap, + }, + ExecutionInput, + Selector, }, - ExecutionInput, - Selector, -}, ContractEnv, Environment, Error}; + ContractEnv, + Environment, + Error, +}; use core::marker::PhantomData; pub mod state { From ea65c4737b75207d74b227fb653fa4a54d58f23d Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 11:43:10 +0000 Subject: [PATCH 169/206] Fix envaccess test --- crates/ink/src/env_access.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 4e9ac49d20a..89cbcf82556 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -445,7 +445,7 @@ where /// /// /// Instantiates another contract. /// #[ink(message)] - /// pub fn instantiate_contract(&self) -> AccountId { + /// pub fn instantiate_contract(&self) -> MyContractRef { /// let create_params = build_create::() /// .code_hash(Hash::from([0x42; 32])) /// .gas_limit(4000) From 258c27b81a51e3aa00706ce603ab9e6eb322adc6 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 11:49:08 +0000 Subject: [PATCH 170/206] Fully qualify Result in macro --- crates/ink/codegen/src/generator/as_dependency/contract_ref.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 cfe0ce0512e..496dc7cb944 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -124,7 +124,8 @@ impl ContractRef<'_> { } } - impl ::ink::env::call::ConstructorReturnType<#ref_ident> for Result<#storage_ident, E> + impl ::ink::env::call::ConstructorReturnType<#ref_ident> + for ::core::result::Result<#storage_ident, E> where E: ::scale::Decode { From 08dc991a252c675fb20e93a39099bed39d6db189 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 11:55:44 +0000 Subject: [PATCH 171/206] More fully qualify Result in macro --- .../ink/codegen/src/generator/as_dependency/contract_ref.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 496dc7cb944..85f66a4b665 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -136,11 +136,11 @@ impl ContractRef<'_> { type Error = E; fn ok(value: #ref_ident) -> Self::Output { - Ok(value) + ::core::result::Result::Ok(value) } fn err(err: Self::Error) -> Self::Output { - Err(err) + ::core::result::Result::Err(err) } } From 4be979d2d74ee33c23190b3fc0ac7edb34527e59 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 15:48:48 +0000 Subject: [PATCH 172/206] Fix up build_create examples --- crates/env/src/call/create_builder.rs | 61 ++++++++++++++++++--------- 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 1adaac9504e..3e55fe5b6af 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -291,13 +291,23 @@ pub struct CreateBuilder< /// # call::{build_create, Selector, ExecutionInput, FromAccountId} /// # }; /// # type Hash = ::Hash; -/// # type AccountId = ::AccountId; -/// # type Salt = &'static [u8]; -/// # struct MyContract; -/// # impl FromAccountId for MyContract { -/// # fn from_account_id(account_id: AccountId) -> Self { Self } -/// # } -/// let my_contract: MyContract = build_create::() +/// +/// #[ink::contract] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct MyContract {} +/// +/// impl MyContract { +/// #[ink(constructor)] +/// pub fn constructor() -> Self { Self {} } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// use contract::MyContractRef; +/// +/// let my_contract: MyContractRef = build_create::() /// .code_hash(Hash::from([0x42; 32])) /// .gas_limit(4000) /// .endowment(25) @@ -308,7 +318,7 @@ pub struct CreateBuilder< /// .push_arg(&[0x10u8; 32]) /// ) /// .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) -/// .returns::() +/// .returns::() /// .instantiate() /// ``` /// @@ -321,16 +331,29 @@ pub struct CreateBuilder< /// # call::{build_create, Selector, ExecutionInput, FromAccountId} /// # }; /// # type Hash = ::Hash; -/// # type AccountId = ::AccountId; -/// # type Salt = &'static [u8]; -/// # struct MyContract; -/// # impl FromAccountId for MyContract { -/// # fn from_account_id(account_id: AccountId) -> Self { Self } -/// # } -/// # #[derive(scale::Encode, scale::Decode, Debug)] -/// # #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -/// # pub struct ConstructorError; -/// let my_contract: MyContract = build_create::() +/// +/// #[ink::contract] +/// pub mod contract { +/// #[derive(scale::Encode, scale::Decode, Debug)] +/// #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +/// pub struct ConstructorError; +/// +/// #[ink(storage)] +/// pub struct MyContract {} +/// +/// impl MyContract { +/// #[ink(constructor)] +/// pub fn constructor() -> Result { +/// Ok(Self {}) +/// } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// use contract::{MyContractRef, ConstructorError}; +/// +/// let my_contract: MyContractRef = build_create::() /// .code_hash(Hash::from([0x42; 32])) /// .gas_limit(4000) /// .endowment(25) @@ -341,7 +364,7 @@ pub struct CreateBuilder< /// .push_arg(&[0x10u8; 32]) /// ) /// .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) -/// .returns::>() +/// .returns::>() /// .instantiate(); /// ``` /// From 0994c67cd26947ba8da907945d84c934c2de4db8 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 15:57:53 +0000 Subject: [PATCH 173/206] Add test for different combos of Self and struct name --- ...onstructor-return-result-cross-contract.rs | 118 ++++++++++++++++++ .../constructors-return-value/lib.rs | 2 +- 2 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs diff --git a/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs b/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs new file mode 100644 index 00000000000..f10199778d1 --- /dev/null +++ b/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs @@ -0,0 +1,118 @@ +#[ink::contract] +mod contract_callee { + #[ink(storage)] + pub struct Callee {} + + #[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)] + #[cfg_attr(feature = "std", derive(::scale_info::TypeInfo))] + pub enum Error { + Foo, + } + + impl Callee { + #[ink(constructor)] + pub fn new_self() -> Self { + Self { } + } + + #[ink(constructor)] + pub fn new_storage_name() -> Callee { + Callee { } + } + + #[ink(constructor)] + pub fn new_result_self() -> Result { + Ok(Self { }) + } + + #[ink(constructor)] + pub fn new_result_storage_name() -> Result { + Ok(Callee { }) + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +// #[ink::contract] +// mod contract_caller { +// use super::contract_callee::{CalleeRef, Error}; +// +// #[ink(storage)] +// pub struct Caller {} +// +// impl Caller { +// #[ink(constructor)] +// pub fn new() -> Self { +// Self { } +// } +// +// #[ink(message)] +// pub fn invoke_callee_constructors(&self) { +// let _: Result = CalleeRef::new_result_self() +// .code_hash(Hash::from([0x42; 32])) +// .gas_limit(4000) +// .endowment(25) +// .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) +// .instantiate() +// .unwrap(); +// +// // let _: Result = CalleeRef::new_result_storage_name().instantiate(); +// // +// // let _: CalleeRef = CalleeRef::new_self().instantiate(); +// // +// // let _: CalleeRef = CalleeRef::new_storage_name().instantiate(); +// } +// } +// } + +fn main() { + use contract_callee::{CalleeRef, Error}; + + // fn new_self() -> Self + let _: fn() -> CalleeRef = || { + CalleeRef::new_self() + .code_hash(ink_primitives::Clear::CLEAR_HASH) + .gas_limit(4000) + .endowment(25) + .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) + .instantiate() + .unwrap() + }; + + // fn new_storage_name() -> Callee + let _: fn() -> CalleeRef = || { + CalleeRef::new_storage_name() + .code_hash(ink_primitives::Clear::CLEAR_HASH) + .gas_limit(4000) + .endowment(25) + .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) + .instantiate() + .unwrap() + }; + + // fn new_result_self() -> Result + let _: fn() -> Result = || { + CalleeRef::new_result_self() + .code_hash(ink_primitives::Clear::CLEAR_HASH) + .gas_limit(4000) + .endowment(25) + .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) + .instantiate() + .unwrap() + }; + + // fn new_result_storage_name() -> Result + let _: fn() -> Result = || { + CalleeRef::new_result_self() + .code_hash(ink_primitives::Clear::CLEAR_HASH) + .gas_limit(4000) + .endowment(25) + .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) + .instantiate() + .unwrap() + }; +} + + 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 d088a6e348d..111b1daa2c3 100644 --- a/examples/lang-err-integration-tests/constructors-return-value/lib.rs +++ b/examples/lang-err-integration-tests/constructors-return-value/lib.rs @@ -26,7 +26,7 @@ pub mod constructors_return_value { /// Fallible constructor #[ink(constructor)] - pub fn try_new(succeed: bool) -> Result { + pub fn try_new(succeed: bool) -> Result { if succeed { Ok(Self::new(true)) } else { From f1f49307408455993a984381cd1a0f5b2b4d3607 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 16:07:47 +0000 Subject: [PATCH 174/206] Fix ui test --- ...ructor-return-result-non-codec-error.stderr | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/crates/ink/tests/ui/contract/fail/constructor-return-result-non-codec-error.stderr b/crates/ink/tests/ui/contract/fail/constructor-return-result-non-codec-error.stderr index 19d2d86df6d..0fcf8ce9f45 100644 --- a/crates/ink/tests/ui/contract/fail/constructor-return-result-non-codec-error.stderr +++ b/crates/ink/tests/ui/contract/fail/constructor-return-result-non-codec-error.stderr @@ -11,6 +11,24 @@ note: required by a bound in `return_value` | R: scale::Encode, | ^^^^^^^^^^^^^ required by this bound in `return_value` +error[E0277]: the trait bound `contract::Error: WrapperTypeDecode` is not satisfied + --> tests/ui/contract/fail/constructor-return-result-non-codec-error.rs:13:9 + | +13 | pub fn constructor() -> Result { + | ^^^ the trait `WrapperTypeDecode` is not implemented for `contract::Error` + | + = help: the following other types implement trait `WrapperTypeDecode`: + Arc + Box + Rc + = note: required for `contract::Error` to implement `parity_scale_codec::Decode` + = note: required for `Result` to implement `ConstructorReturnType` +note: required by a bound in `CreateBuilder::>>::returns` + --> $WORKSPACE/crates/env/src/call/create_builder.rs + | + | R: ConstructorReturnType, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `CreateBuilder::>>::returns` + error[E0277]: the trait bound `contract::Error: TypeInfo` is not satisfied --> tests/ui/contract/fail/constructor-return-result-non-codec-error.rs:4:16 | From 12f51dc7bd14732a9f5b154441c8a45ee9afabb7 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 16:10:00 +0000 Subject: [PATCH 175/206] Fmt --- .../constructor-return-result-cross-contract.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs b/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs index f10199778d1..dee9e13a3c7 100644 --- a/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs +++ b/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs @@ -12,22 +12,22 @@ mod contract_callee { impl Callee { #[ink(constructor)] pub fn new_self() -> Self { - Self { } + Self {} } #[ink(constructor)] pub fn new_storage_name() -> Callee { - Callee { } + Callee {} } #[ink(constructor)] pub fn new_result_self() -> Result { - Ok(Self { }) + Ok(Self {}) } #[ink(constructor)] pub fn new_result_storage_name() -> Result { - Ok(Callee { }) + Ok(Callee {}) } #[ink(message)] @@ -68,7 +68,10 @@ mod contract_callee { // } fn main() { - use contract_callee::{CalleeRef, Error}; + use contract_callee::{ + CalleeRef, + Error, + }; // fn new_self() -> Self let _: fn() -> CalleeRef = || { @@ -114,5 +117,3 @@ fn main() { .unwrap() }; } - - From 1bceab30c3c34f81a794288488b1c3528b434d2a Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 16:20:45 +0000 Subject: [PATCH 176/206] Remove unused assoc type --- crates/env/src/call/create_builder.rs | 7 ------- .../codegen/src/generator/as_dependency/contract_ref.rs | 2 -- 2 files changed, 9 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 3e55fe5b6af..b51a60a7afa 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -57,11 +57,6 @@ pub trait ConstructorReturnType { /// Is `true` if `Self` is `Result`. const IS_RESULT: bool = false; - /// The type of the contract returned from a constructor. - /// If a constructor returns `Self`, then `Contract = Self` - /// If a constructor returns a `Result`, then `Contract = Self`. - type Contract; - /// The actual return type of the constructor. /// If a constructor returns `Self`, then `Output = Self` /// If a constructor returns a `Result`, then `Output = Result`. @@ -81,7 +76,6 @@ impl ConstructorReturnType for C where C: ContractEnv + FromAccountId<::Env>, { - type Contract = C; type Output = C; type Error = (); @@ -102,7 +96,6 @@ where { const IS_RESULT: bool = true; - type Contract = C; type Output = core::result::Result; type Error = E; 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 85f66a4b665..4ad55cb795b 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -110,7 +110,6 @@ impl ContractRef<'_> { } impl ::ink::env::call::ConstructorReturnType<#ref_ident> for #storage_ident { - type Contract = #ref_ident; type Output = #ref_ident; type Error = (); @@ -131,7 +130,6 @@ impl ContractRef<'_> { { const IS_RESULT: bool = true; - type Contract = #ref_ident; type Output = ::core::result::Result<#ref_ident, E>; type Error = E; From 8e0a9ef7d47216db13482abd79824dfed11084cd Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 16:36:54 +0000 Subject: [PATCH 177/206] Change error fn to return Option --- crates/env/src/call/create_builder.rs | 17 +++++++---------- crates/env/src/engine/mod.rs | 5 ++++- .../src/generator/as_dependency/contract_ref.rs | 9 ++------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index b51a60a7afa..531897cc3f9 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -69,7 +69,11 @@ pub trait ConstructorReturnType { fn ok(value: C) -> Self::Output; /// Construct an error value of the `Output` type. - fn err(err: Self::Error) -> Self::Output; + /// + /// `Result` impls should return `Some(Err(err))`, otherwise default to `None`. + fn err(_err: Self::Error) -> Option { + None + } } impl ConstructorReturnType for C @@ -82,11 +86,6 @@ where fn ok(value: C) -> Self::Output { value } - - fn err(_err: Self::Error) -> Self::Output { - // todo! - unreachable!() - } } impl ConstructorReturnType for core::result::Result @@ -103,13 +102,11 @@ where Ok(value) } - fn err(err: Self::Error) -> Self::Output { - Err(err) + fn err(err: Self::Error) -> Option { + Some(Err(err)) } } -// pub type InstantiateOutput = <>::Type as Instantiate - /// Builds up contract instantiations. #[derive(Debug)] pub struct CreateParams diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index aa2d0e5ba61..4fbebde8fa8 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -86,7 +86,10 @@ where 1 => { let contract_err = <>::Error as scale::Decode>::decode(out_return_value)?; - let err = >::err(contract_err); + let err = >::err(contract_err) + .unwrap_or_else(|| { + panic!("Expected an error instance for return type where IS_RESULT == true") + }); Ok(Ok(err)) } _ => Err(Error::Decode("Invalid inner constructor Result encoding, expected 0 or 1 as the first byte".into())) 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 4ad55cb795b..42537d034d9 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -116,11 +116,6 @@ impl ContractRef<'_> { fn ok(value: #ref_ident) -> Self::Output { value } - - fn err(_err: Self::Error) -> Self::Output { - // todo! - unreachable!() - } } impl ::ink::env::call::ConstructorReturnType<#ref_ident> @@ -137,8 +132,8 @@ impl ContractRef<'_> { ::core::result::Result::Ok(value) } - fn err(err: Self::Error) -> Self::Output { - ::core::result::Result::Err(err) + fn err(err: Self::Error) -> ::core::option::Option { + ::core::option::Option::Some(::core::result::Result::Err(err)) } } From aea12380341e315edad4aab5ffe95fddf8562504 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 16:49:33 +0000 Subject: [PATCH 178/206] Remove commented out code --- ...onstructor-return-result-cross-contract.rs | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs b/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs index dee9e13a3c7..c16b31cd2a4 100644 --- a/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs +++ b/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs @@ -35,38 +35,6 @@ mod contract_callee { } } -// #[ink::contract] -// mod contract_caller { -// use super::contract_callee::{CalleeRef, Error}; -// -// #[ink(storage)] -// pub struct Caller {} -// -// impl Caller { -// #[ink(constructor)] -// pub fn new() -> Self { -// Self { } -// } -// -// #[ink(message)] -// pub fn invoke_callee_constructors(&self) { -// let _: Result = CalleeRef::new_result_self() -// .code_hash(Hash::from([0x42; 32])) -// .gas_limit(4000) -// .endowment(25) -// .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) -// .instantiate() -// .unwrap(); -// -// // let _: Result = CalleeRef::new_result_storage_name().instantiate(); -// // -// // let _: CalleeRef = CalleeRef::new_self().instantiate(); -// // -// // let _: CalleeRef = CalleeRef::new_storage_name().instantiate(); -// } -// } -// } - fn main() { use contract_callee::{ CalleeRef, From 163fa6b61838e93bc19c589691aa18b9350d165e Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 17:24:35 +0000 Subject: [PATCH 179/206] Fmt --- crates/env/src/engine/mod.rs | 77 ++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 30 deletions(-) diff --git a/crates/env/src/engine/mod.rs b/crates/env/src/engine/mod.rs index 4fbebde8fa8..f75a32c4aed 100644 --- a/crates/env/src/engine/mod.rs +++ b/crates/env/src/engine/mod.rs @@ -73,40 +73,57 @@ where Ok(Ok(output)) } Err(EnvError::CalleeReverted) => { - let constructor_result_variant = out_return_value.read_byte()?; - match constructor_result_variant { - // 0 == `ConstructorResult::Ok` variant - 0 => { - if >::IS_RESULT { - let result_variant = out_return_value.read_byte()?; - match result_variant { - // 0 == `Ok` variant - 0 => panic!("The callee reverted, but did not encode an error in the output buffer."), - // 1 == `Err` variant - 1 => { - let contract_err = <>::Error - as scale::Decode>::decode(out_return_value)?; - let err = >::err(contract_err) - .unwrap_or_else(|| { - panic!("Expected an error instance for return type where IS_RESULT == true") - }); - Ok(Ok(err)) - } - _ => Err(Error::Decode("Invalid inner constructor Result encoding, expected 0 or 1 as the first byte".into())) - } - } else { - panic!("The callee reverted, but did not encode an error in the output buffer.") + decode_instantiate_err::(out_return_value) + } + Err(actual_error) => Err(actual_error), + } +} + +#[cfg_attr(all(feature = "std", not(test)), allow(dead_code))] +fn decode_instantiate_err( + out_return_value: &mut I, +) -> EnvResult>::Output>> +where + I: scale::Input, + E: crate::Environment, + ContractRef: FromAccountId, + R: ConstructorReturnType, +{ + let constructor_result_variant = out_return_value.read_byte()?; + match constructor_result_variant { + // 0 == `ConstructorResult::Ok` variant + 0 => { + if >::IS_RESULT { + let result_variant = out_return_value.read_byte()?; + match result_variant { + // 0 == `Ok` variant + 0 => panic!("The callee reverted, but did not encode an error in the output buffer."), + // 1 == `Err` variant + 1 => { + let contract_err = <>::Error + as scale::Decode>::decode(out_return_value)?; + let err = >::err(contract_err) + .unwrap_or_else(|| { + panic!("Expected an error instance for return type where IS_RESULT == true") + }); + Ok(Ok(err)) } + _ => Err(Error::Decode( + "Invalid inner constructor Result encoding, expected 0 or 1 as the first byte".into()) + ) } - // 1 == `ConstructorResult::Err` variant - 1 => { - let lang_err = ::decode(out_return_value)?; - Ok(Err(lang_err)) - } - _ => Err(Error::Decode("Invalid outer constructor Result encoding, expected 0 or 1 as the first byte".into())) + } else { + panic!("The callee reverted, but did not encode an error in the output buffer.") } } - Err(actual_error) => Err(actual_error), + // 1 == `ConstructorResult::Err` variant + 1 => { + let lang_err = ::decode(out_return_value)?; + Ok(Err(lang_err)) + } + _ => Err(Error::Decode( + "Invalid outer constructor Result encoding, expected 0 or 1 as the first byte".into()) + ) } } From 1dd00d6b3f4f85819a2867e703ca3524d18ec0c0 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 17:51:37 +0000 Subject: [PATCH 180/206] ConstructorReturnType comments --- crates/env/src/call/create_builder.rs | 56 ++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 531897cc3f9..7eb71b429d2 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -52,7 +52,55 @@ where fn from_account_id(account_id: ::AccountId) -> Self; } -/// todo! +/// Represents any type that can be returned from an `ink!` constructor. The following contract +/// implements the four different return type signatures implementing this trait: +/// +/// - `Self` +/// - `Result` +/// - `Contract` +/// - `Result` +/// +/// ```rust +/// #[ink::contract] +/// mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// #[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)] +/// #[cfg_attr(feature = "std", derive(::scale_info::TypeInfo))] +/// pub enum Error { +/// Foo, +/// } +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn new_self() -> Self { +/// Self {} +/// } +/// +/// #[ink(constructor)] +/// pub fn new_storage_name() -> Contract { +/// Contract {} +/// } +/// +/// #[ink(constructor)] +/// pub fn new_result_self() -> Result { +/// Ok(Self {}) +/// } +/// +/// #[ink(constructor)] +/// pub fn new_result_storage_name() -> Result { +/// Ok(Contract {}) +/// } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// ``` +/// +/// These constructor return signatures are then used by the contract ref codegen for the +/// [`CreateBuilder::returns`] type parameter. pub trait ConstructorReturnType { /// Is `true` if `Self` is `Result`. const IS_RESULT: bool = false; @@ -76,6 +124,10 @@ pub trait ConstructorReturnType { } } +/// Blanket impl for contract ref types, generated for cross-contract calls. +/// +/// In the context of a contract ref inherent, `Self` from a constructor return +/// type will become the type of the contract ref's type. impl ConstructorReturnType for C where C: ContractEnv + FromAccountId<::Env>, @@ -88,6 +140,8 @@ where } } +/// Blanket impl for a `Result` return type. `Self` in the context +/// of a contract ref inherent becomes the contract refs type. impl ConstructorReturnType for core::result::Result where C: ContractEnv + FromAccountId<::Env>, From 327967da0cf841d2e93317e540d855eb762ce70c Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 20 Jan 2023 09:27:48 -0800 Subject: [PATCH 181/206] Fix `contract-ref` E2E test compilation From 0bb7a8d098cdd1bf0d82115c109aba325ee3906c Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 17:55:53 +0000 Subject: [PATCH 182/206] Fix up return types after merge --- crates/env/src/call/create_builder.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 7eb71b429d2..6f08bb64e87 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -65,34 +65,34 @@ where /// mod contract { /// #[ink(storage)] /// pub struct Contract {} -/// +/// /// #[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)] /// #[cfg_attr(feature = "std", derive(::scale_info::TypeInfo))] /// pub enum Error { /// Foo, /// } -/// +/// /// impl Contract { /// #[ink(constructor)] /// pub fn new_self() -> Self { /// Self {} /// } -/// +/// /// #[ink(constructor)] /// pub fn new_storage_name() -> Contract { /// Contract {} /// } -/// +/// /// #[ink(constructor)] /// pub fn new_result_self() -> Result { /// Ok(Self {}) /// } -/// +/// /// #[ink(constructor)] /// pub fn new_result_storage_name() -> Result { /// Ok(Contract {}) /// } -/// +/// /// #[ink(message)] /// pub fn message(&self) {} /// } @@ -248,9 +248,7 @@ where /// [`ink::primitives::LangError`][`ink_primitives::LangError`]. If you want to handle those /// use the [`try_instantiate`][`CreateParams::try_instantiate`] method instead. #[inline] - pub fn instantiate( - &self, - ) -> Result<>::Output, crate::Error> { + pub fn instantiate(&self) -> >::Output { crate::instantiate_contract(self) .unwrap_or_else(|env_error| { panic!("Cross-contract instantiation failed with {:?}", env_error) From 75ab4e66f6af552594074b07ecaa5cde56c532c9 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 17:57:27 +0000 Subject: [PATCH 183/206] Fmt --- crates/env/src/call/create_builder.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 6f08bb64e87..13fdd3a61b7 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -736,9 +736,7 @@ where /// [`ink::primitives::LangError`][`ink_primitives::LangError`]. If you want to handle those /// use the [`try_instantiate`][`CreateBuilder::try_instantiate`] method instead. #[inline] - pub fn instantiate( - self, - ) -> Result<>::Output, Error> { + pub fn instantiate(self) -> >::Output { self.params().instantiate() } From 77a5baba93e129e2b251e8122fd440c2c29d38f8 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 17:58:24 +0000 Subject: [PATCH 184/206] Clippy From 7d03708a2cad79f31b87367f5d01dd1e7e60dc29 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 18:14:24 +0000 Subject: [PATCH 185/206] Fix create_builder tests --- crates/env/src/call/create_builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 13fdd3a61b7..b63e70ea491 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -361,7 +361,7 @@ pub struct CreateBuilder< /// ) /// .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) /// .returns::() -/// .instantiate() +/// .instantiate(); /// ``` /// /// ## Example 2: Handles Result from Fallible Constructor From ca47caf78f371bfd45dfba9114079c8dd411eb3b Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sat, 21 Jan 2023 11:22:03 -0800 Subject: [PATCH 186/206] Fix cross-contract compile test --- .../contract/pass/constructor-return-result-cross-contract.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs b/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs index c16b31cd2a4..984c053d8b6 100644 --- a/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs +++ b/crates/ink/tests/ui/contract/pass/constructor-return-result-cross-contract.rs @@ -49,7 +49,6 @@ fn main() { .endowment(25) .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) .instantiate() - .unwrap() }; // fn new_storage_name() -> Callee @@ -60,7 +59,6 @@ fn main() { .endowment(25) .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) .instantiate() - .unwrap() }; // fn new_result_self() -> Result @@ -71,7 +69,6 @@ fn main() { .endowment(25) .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) .instantiate() - .unwrap() }; // fn new_result_storage_name() -> Result @@ -82,6 +79,5 @@ fn main() { .endowment(25) .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) .instantiate() - .unwrap() }; } From 2cc8a2288884dee06b333b8ded93c9bdb138f209 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sat, 21 Jan 2023 11:25:05 -0800 Subject: [PATCH 187/206] Clean up some comments --- crates/env/src/call/create_builder.rs | 14 +++++++------- crates/env/src/call/execution_input.rs | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index b63e70ea491..3b1902e6d34 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -99,7 +99,7 @@ where /// } /// ``` /// -/// These constructor return signatures are then used by the contract ref codegen for the +/// These constructor return signatures are then used by the `ContractRef` codegen for the /// [`CreateBuilder::returns`] type parameter. pub trait ConstructorReturnType { /// Is `true` if `Self` is `Result`. @@ -124,10 +124,10 @@ pub trait ConstructorReturnType { } } -/// Blanket impl for contract ref types, generated for cross-contract calls. +/// Blanket implementation for `ContractRef` types, generated for cross-contract calls. /// -/// In the context of a contract ref inherent, `Self` from a constructor return -/// type will become the type of the contract ref's type. +/// In the context of a `ContractRef` inherent, `Self` from a constructor return +/// type will become the type of the `ContractRef`'s type. impl ConstructorReturnType for C where C: ContractEnv + FromAccountId<::Env>, @@ -140,8 +140,8 @@ where } } -/// Blanket impl for a `Result` return type. `Self` in the context -/// of a contract ref inherent becomes the contract refs type. +/// Blanket implementation for a `Result` return type. `Self` in the context +/// of a `ContractRef` inherent becomes the `ContractRef`s type. impl ConstructorReturnType for core::result::Result where C: ContractEnv + FromAccountId<::Env>, @@ -214,7 +214,7 @@ where /// Modify the selector. /// /// Useful when using the [`CreateParams`] generated as part of the - /// contract ref, but using a custom selector. + /// `ContractRef`, but using a custom selector. pub fn update_selector(&mut self, selector: Selector) { self.exec_input.update_selector(selector) } diff --git a/crates/env/src/call/execution_input.rs b/crates/env/src/call/execution_input.rs index 8f3f79dd171..fb491468522 100644 --- a/crates/env/src/call/execution_input.rs +++ b/crates/env/src/call/execution_input.rs @@ -67,7 +67,7 @@ impl ExecutionInput { /// Modify the selector. /// /// Useful when using the [`ExecutionInput`] generated as part of the - /// contract ref, but using a custom selector. + /// `ContractRef`, but using a custom selector. pub fn update_selector(&mut self, selector: Selector) { self.selector = selector; } From fa0436aeb057157d80436f1af7c9eaf7c1af8c50 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sat, 21 Jan 2023 11:28:17 -0800 Subject: [PATCH 188/206] Remove outdated doc --- crates/env/src/call/create_builder.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 3b1902e6d34..fe759f25351 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -409,8 +409,6 @@ pub struct CreateBuilder< /// .returns::>() /// .instantiate(); /// ``` -/// -/// Note the usage of the [`CreateBuilder::instantiate_fallible`] method. #[allow(clippy::type_complexity)] pub fn build_create() -> CreateBuilder< ::Env, From 016b10233ab5b9cbea208bce3dfcafbabaeab725 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sat, 21 Jan 2023 11:31:17 -0800 Subject: [PATCH 189/206] Update comment --- crates/env/src/call/create_builder.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index fe759f25351..e2fa7bb7afc 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -106,8 +106,8 @@ pub trait ConstructorReturnType { const IS_RESULT: bool = false; /// The actual return type of the constructor. - /// If a constructor returns `Self`, then `Output = Self` - /// If a constructor returns a `Result`, then `Output = Result`. + /// - If a constructor returns `Self`, then `Output = Self` + /// - If a constructor returns a `Result`, then `Output = Result` type Output; /// The error type of the constructor return type. From 96550723c84ee0da2c07e31bf656ec2a932c3a06 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sat, 21 Jan 2023 11:31:38 -0800 Subject: [PATCH 190/206] Another comment fix --- crates/env/src/call/create_builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index e2fa7bb7afc..2f4ed0df4c8 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -177,7 +177,7 @@ where exec_input: ExecutionInput, /// The salt for determining the hash for the contract account ID. salt_bytes: Salt, - /// The return type of the target contracts constructor method. + /// The return type of the target contract's constructor method. _return_type: ReturnType, /// The type of the reference to the contract returned from the constructor. _phantom: PhantomData ContractRef>, From 7aecb5f0a3f738406d813f9c298a85e75a352c8c Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 20 Jan 2023 16:27:00 -0800 Subject: [PATCH 191/206] Wrap long line From 6f920333ee3b69d689fd0ec13d030de3ada8f3f9 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 20 Jan 2023 16:45:18 -0800 Subject: [PATCH 192/206] Remove TODO From 498c640012b7b1dab90a7e4bfa596f134c1ece90 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sat, 21 Jan 2023 11:56:40 -0800 Subject: [PATCH 193/206] Bump `contract-metadata` Fixes some inconsistent errors between Clippy and `rustc` --- crates/e2e/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/e2e/Cargo.toml b/crates/e2e/Cargo.toml index 397a2d098ee..252765b6cb0 100644 --- a/crates/e2e/Cargo.toml +++ b/crates/e2e/Cargo.toml @@ -21,7 +21,7 @@ ink = { version = "4.0.0-beta", path = "../ink" } ink_env = { version = "4.0.0-beta", path = "../env" } ink_primitives = { version = "4.0.0-beta", path = "../primitives" } -contract-metadata = { version = "2.0.0-beta.1" } +contract-metadata = { version = "2.0.0-rc" } impl-serde = { version = "0.3.1", default-features = false } jsonrpsee = { version = "0.16.0", features = ["ws-client"] } serde = { version = "1.0.137", default-features = false, features = ["derive"] } From 8e60ec21a5a569d244d0cfee0d0e71d9c3367ff4 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 23 Jan 2023 17:43:11 -0800 Subject: [PATCH 194/206] Fix `CreateBuilder` compilation --- crates/env/src/call/create_builder.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 2f4ed0df4c8..0d7c3f47e58 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -253,7 +253,6 @@ where .unwrap_or_else(|env_error| { panic!("Cross-contract instantiation failed with {:?}", env_error) }) - .map(FromAccountId::from_account_id) .unwrap_or_else(|lang_error| { panic!( "Received a `LangError` while instantiating: {:?}", From a9c0223c16a3d6cba6c05b4a0139211e9ee32466 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 23 Jan 2023 17:46:27 -0800 Subject: [PATCH 195/206] Fix one of the doc tests --- crates/env/src/call/create_builder.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 0d7c3f47e58..54e9cd143b9 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -406,7 +406,8 @@ pub struct CreateBuilder< /// ) /// .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) /// .returns::>() -/// .instantiate(); +/// .instantiate() +/// .expect("Constructor should have executed succesfully."); /// ``` #[allow(clippy::type_complexity)] pub fn build_create() -> CreateBuilder< From db1a808e7a8165b2e1a0f286dfe4e78fbdcdae5e Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 23 Jan 2023 18:13:07 -0800 Subject: [PATCH 196/206] Clean up doc tests a bit --- crates/env/src/call/create_builder.rs | 80 +++++++++++++-------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 54e9cd143b9..b7fcc2646e7 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -118,7 +118,7 @@ pub trait ConstructorReturnType { /// Construct an error value of the `Output` type. /// - /// `Result` impls should return `Some(Err(err))`, otherwise default to `None`. + /// `Result` implementations should return `Some(Err(err))`, otherwise default to `None`. fn err(_err: Self::Error) -> Option { None } @@ -332,28 +332,27 @@ pub struct CreateBuilder< /// # call::{build_create, Selector, ExecutionInput, FromAccountId} /// # }; /// # type Hash = ::Hash; -/// -/// #[ink::contract] -/// pub mod contract { -/// #[ink(storage)] -/// pub struct MyContract {} -/// -/// impl MyContract { -/// #[ink(constructor)] -/// pub fn constructor() -> Self { Self {} } -/// -/// #[ink(message)] -/// pub fn message(&self) {} -/// } -/// } -/// use contract::MyContractRef; -/// +/// # +/// # #[ink::contract] +/// # pub mod contract { +/// # #[ink(storage)] +/// # pub struct MyContract {} +/// # +/// # impl MyContract { +/// # #[ink(constructor)] +/// # pub fn my_constructor() -> Self { Self {} } +/// # +/// # #[ink(message)] +/// # pub fn message(&self) {} +/// # } +/// # } +/// # use contract::MyContractRef; /// let my_contract: MyContractRef = build_create::() /// .code_hash(Hash::from([0x42; 32])) /// .gas_limit(4000) /// .endowment(25) /// .exec_input( -/// ExecutionInput::new(Selector::new([0xDE, 0xAD, 0xBE, 0xEF])) +/// ExecutionInput::new(Selector::new(ink::selector_bytes!("my_constructor"))) /// .push_arg(42) /// .push_arg(true) /// .push_arg(&[0x10u8; 32]) @@ -372,34 +371,33 @@ pub struct CreateBuilder< /// # call::{build_create, Selector, ExecutionInput, FromAccountId} /// # }; /// # type Hash = ::Hash; -/// -/// #[ink::contract] -/// pub mod contract { -/// #[derive(scale::Encode, scale::Decode, Debug)] -/// #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -/// pub struct ConstructorError; -/// -/// #[ink(storage)] -/// pub struct MyContract {} -/// -/// impl MyContract { -/// #[ink(constructor)] -/// pub fn constructor() -> Result { -/// Ok(Self {}) -/// } -/// -/// #[ink(message)] -/// pub fn message(&self) {} -/// } -/// } -/// use contract::{MyContractRef, ConstructorError}; -/// +/// # +/// # #[ink::contract] +/// # pub mod contract { +/// # #[derive(scale::Encode, scale::Decode, Debug)] +/// # #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +/// # pub struct ConstructorError; +/// # +/// # #[ink(storage)] +/// # pub struct MyContract {} +/// # +/// # impl MyContract { +/// # #[ink(constructor)] +/// # pub fn my_constructor() -> Result { +/// # Ok(Self {}) +/// # } +/// # +/// # #[ink(message)] +/// # pub fn message(&self) {} +/// # } +/// # } +/// # use contract::{MyContractRef, ConstructorError}; /// let my_contract: MyContractRef = build_create::() /// .code_hash(Hash::from([0x42; 32])) /// .gas_limit(4000) /// .endowment(25) /// .exec_input( -/// ExecutionInput::new(Selector::new([0xDE, 0xAD, 0xBE, 0xEF])) +/// ExecutionInput::new(Selector::new(ink::selector_bytes!("my_constructor"))) /// .push_arg(42) /// .push_arg(true) /// .push_arg(&[0x10u8; 32]) From 810e0aa276f4d324fb1100936efa68b945390f7f Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 24 Jan 2023 11:11:21 +0000 Subject: [PATCH 197/206] WIP create accounts --- crates/e2e/src/client.rs | 8 ++++++++ crates/e2e/src/xts.rs | 43 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/crates/e2e/src/client.rs b/crates/e2e/src/client.rs index d38433e6e4c..ad0064649fe 100644 --- a/crates/e2e/src/client.rs +++ b/crates/e2e/src/client.rs @@ -44,6 +44,7 @@ use std::{ fmt::Debug, path::Path, }; +use sp_core::Pair; use subxt::{ blocks::ExtrinsicEvents, events::EventDetails, @@ -342,6 +343,13 @@ where } } + /// Generate a new keypair and fund with the given amount from the origin account. + pub async fn create_and_fund_account(&self, origin: &Signer, amount: E::Balance) -> Signer { + let (pair, _, _) = ::generate_with_phrase(None); + let _ = self.api.transfer_balance(origin, pair.public().into_account(), amount).await; + pair + } + /// This function extracts the metadata of the contract at the file path /// `target/ink/$contract_name.contract`. /// diff --git a/crates/e2e/src/xts.rs b/crates/e2e/src/xts.rs index 9fea3e270f2..a31f1120d83 100644 --- a/crates/e2e/src/xts.rs +++ b/crates/e2e/src/xts.rs @@ -189,6 +189,49 @@ where } } + #[allow(clippy::too_many_arguments)] + pub async fn transfer_balance( + &self, + origin: &Signer, + dest: C::AccountId, + value: E::Balance, + ) -> ExtrinsicEvents { + let call = subxt::tx::StaticTxPayload::new( + "Balances", + "transfer", + (dest, value), + Default::default(), + ).unvalidated(); + + self.client + .tx() + .sign_and_submit_then_watch_default(&call, origin) + .await + .map(|tx_progress| { + log_info(&format!( + "signed and submitted tx with hash {:?}", + tx_progress.extrinsic_hash() + )); + tx_progress + }) + .unwrap_or_else(|err| { + panic!( + "error on call `sign_and_submit_then_watch_default`: {:?}", + err + ); + }) + .wait_for_in_block() + .await + .unwrap_or_else(|err| { + panic!("error on call `wait_for_in_block`: {:?}", err); + }) + .fetch_events() + .await + .unwrap_or_else(|err| { + panic!("error on call `fetch_events`: {:?}", err); + }) + } + /// Dry runs the instantiation of the given `code`. pub async fn instantiate_with_code_dry_run( &self, From 5aff43c649272a3f4977fe8349791c69b1fe28d6 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 24 Jan 2023 15:30:31 +0000 Subject: [PATCH 198/206] Try transfer balance --- crates/e2e/src/client.rs | 46 ++++++++++++++++++++++++++++++++++------ crates/e2e/src/xts.rs | 46 +++++++++++++++------------------------- 2 files changed, 57 insertions(+), 35 deletions(-) diff --git a/crates/e2e/src/client.rs b/crates/e2e/src/client.rs index ad0064649fe..5a58cd7b3fc 100644 --- a/crates/e2e/src/client.rs +++ b/crates/e2e/src/client.rs @@ -35,6 +35,7 @@ use contract_metadata::ContractMetadata; use ink_env::Environment; use ink_primitives::MessageResult; +use sp_core::Pair; use sp_runtime::traits::{ IdentifyAccount, Verify, @@ -44,7 +45,6 @@ use std::{ fmt::Debug, path::Path, }; -use sp_core::Pair; use subxt::{ blocks::ExtrinsicEvents, events::EventDetails, @@ -56,7 +56,10 @@ use subxt::{ ValueDef, }, }, - tx::ExtrinsicParams, + tx::{ + ExtrinsicParams, + PairSigner, + }, }; /// Result of a contract instantiation. @@ -344,10 +347,41 @@ where } /// Generate a new keypair and fund with the given amount from the origin account. - pub async fn create_and_fund_account(&self, origin: &Signer, amount: E::Balance) -> Signer { - let (pair, _, _) = ::generate_with_phrase(None); - let _ = self.api.transfer_balance(origin, pair.public().into_account(), amount).await; - pair + /// + /// Because many tests may execute this in parallel, transfers may fail due to a race condition + /// with account nonces. Therefore this will reattempt transfers a number of times. + pub async fn create_and_fund_account( + &self, + origin: &Signer, + amount: E::Balance, + ) -> Signer + where + E::Balance: Clone, + C::AccountId: Clone + core::fmt::Display, + { + let (pair, _, _) = ::generate_with_phrase(None); + let account_id = + ::Signer::from(pair.public()).into_account(); + + for _ in 0..6 { + let transfer_result = self + .api + .try_transfer_balance(origin, account_id.clone(), amount.clone()) + .await; + match transfer_result { + Ok(_) => break, + Err(err) => { + log_info(&format!( + "transfer from {} to {} failed with {:?}", + origin.account_id(), + account_id, + err + )) + } + } + } + + PairSigner::new(pair) } /// This function extracts the metadata of the contract at the file path diff --git a/crates/e2e/src/xts.rs b/crates/e2e/src/xts.rs index a31f1120d83..d4261299754 100644 --- a/crates/e2e/src/xts.rs +++ b/crates/e2e/src/xts.rs @@ -189,47 +189,35 @@ where } } - #[allow(clippy::too_many_arguments)] - pub async fn transfer_balance( + /// Attempt to transfer the `value` from `origin` to `dest`. + /// + /// Returns `Ok` if on success, and a [`subxt::Error`] if the extrinsic is + /// invalid (e.g. out of date nonce) + pub async fn try_transfer_balance( &self, origin: &Signer, dest: C::AccountId, value: E::Balance, - ) -> ExtrinsicEvents { + ) -> Result<(), subxt::Error> { let call = subxt::tx::StaticTxPayload::new( "Balances", "transfer", (dest, value), Default::default(), - ).unvalidated(); + ) + .unvalidated(); - self.client + let tx_progress = self + .client .tx() .sign_and_submit_then_watch_default(&call, origin) - .await - .map(|tx_progress| { - log_info(&format!( - "signed and submitted tx with hash {:?}", - tx_progress.extrinsic_hash() - )); - tx_progress - }) - .unwrap_or_else(|err| { - panic!( - "error on call `sign_and_submit_then_watch_default`: {:?}", - err - ); - }) - .wait_for_in_block() - .await - .unwrap_or_else(|err| { - panic!("error on call `wait_for_in_block`: {:?}", err); - }) - .fetch_events() - .await - .unwrap_or_else(|err| { - panic!("error on call `fetch_events`: {:?}", err); - }) + .await?; + + tx_progress.wait_for_in_block().await.unwrap_or_else(|err| { + panic!("error on call `wait_for_in_block`: {:?}", err); + }); + + Ok(()) } /// Dry runs the instantiation of the given `code`. From 23130ec7d9c2aa32b76fcbf354f7e34cf987301d Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 24 Jan 2023 18:10:11 +0000 Subject: [PATCH 199/206] WIP try creating and funding account for single test. --- crates/e2e/src/client.rs | 21 ++++++----- crates/e2e/src/xts.rs | 37 ++++++++++++++++--- .../call-builder/lib.rs | 8 ++-- 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/crates/e2e/src/client.rs b/crates/e2e/src/client.rs index 5a58cd7b3fc..0a5fb224ca8 100644 --- a/crates/e2e/src/client.rs +++ b/crates/e2e/src/client.rs @@ -21,10 +21,6 @@ use super::{ log_error, log_info, sr25519, - xts::{ - Call, - InstantiateWithCode, - }, CodeUploadResult, ContractExecResult, ContractInstantiateResult, @@ -304,11 +300,8 @@ where E: Environment, E::AccountId: Debug, - E::Balance: Debug + scale::Encode + serde::Serialize, + E::Balance: Debug + scale::HasCompact + serde::Serialize, E::Hash: Debug + scale::Encode, - - Call: scale::Encode, - InstantiateWithCode: scale::Encode, { /// Creates a new [`Client`] instance. pub async fn new(url: &str, contracts: impl IntoIterator) -> Self { @@ -369,14 +362,22 @@ where .try_transfer_balance(origin, account_id.clone(), amount.clone()) .await; match transfer_result { - Ok(_) => break, + Ok(_) => { + log_info(&format!( + "transfer from {} to {} succeeded", + origin.account_id(), + account_id, + )); + break + } Err(err) => { log_info(&format!( "transfer from {} to {} failed with {:?}", origin.account_id(), account_id, err - )) + )); + tokio::time::sleep(std::time::Duration::from_secs(1)).await; } } } diff --git a/crates/e2e/src/xts.rs b/crates/e2e/src/xts.rs index d4261299754..34391d44ea4 100644 --- a/crates/e2e/src/xts.rs +++ b/crates/e2e/src/xts.rs @@ -45,6 +45,14 @@ use subxt::{ OnlineClient, }; +/// A raw call to `pallet-balances` `transfer`. +// #[derive(Debug, scale::Encode)] +// pub struct Transfer { +// dest: sp_runtime::MultiAddress, +// #[codec(compact)] +// value: B, +// } + /// A raw call to `pallet-contracts`'s `instantiate_with_code`. #[derive(Debug, scale::Encode, scale::Decode)] pub struct InstantiateWithCode { @@ -68,6 +76,25 @@ pub struct Call { data: Vec, } +/// A raw call to `pallet-contracts`'s `call`. +#[derive(Debug, scale::Encode, scale::Decode)] +pub struct Call2 { + dest: sp_runtime::MultiAddress, + #[codec(compact)] + value: B, + gas_limit: Weight, + storage_deposit_limit: Option, + data: Vec, +} + +/// A raw call to `pallet-contracts`'s `call`. +#[derive(Debug, scale::Encode, scale::Decode)] +pub struct Transfer { + dest: C::Address, + #[codec(compact)] + value: E::Balance, +} + #[derive( Debug, Clone, Copy, scale::Encode, scale::Decode, PartialEq, Eq, serde::Serialize, )] @@ -167,10 +194,7 @@ where sr25519::Signature: Into, E: Environment, - E::Balance: scale::Encode + serde::Serialize, - - Call: scale::Encode, - InstantiateWithCode: scale::Encode, + E::Balance: scale::HasCompact + serde::Serialize, { /// Creates a new [`ContractsApi`] instance. pub async fn new(client: OnlineClient, url: &str) -> Self { @@ -202,7 +226,10 @@ where let call = subxt::tx::StaticTxPayload::new( "Balances", "transfer", - (dest, value), + Transfer:: { + dest: dest.into(), + value, + }, Default::default(), ) .unvalidated(); diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index fd2b80d35e6..643e0f2f771 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -276,15 +276,17 @@ mod call_builder { async fn e2e_create_builder_works_with_valid_selector( mut client: ink_e2e::Client, ) -> E2EResult<()> { + let origin = client.create_and_fund_account(&ink_e2e::bob(), 1_000_000_000_000).await; + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::bob(), constructor, 0, None) + .instantiate("call_builder", &origin, constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::bob(), None) + .upload("constructors_return_value", &origin, None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -296,7 +298,7 @@ mod call_builder { contract.call_instantiate(code_hash, selector, init_value) }); let call_result = client - .call(&ink_e2e::bob(), call, 0, None) + .call(&origin, call, 0, None) .await .expect("Client failed to call `call_builder::call_instantiate`.") .return_value(); From e102f438e7d6be12fe9ab23ab8bff1292a59b069 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 24 Jan 2023 18:22:18 +0000 Subject: [PATCH 200/206] Update all tests to use create_and_fund_account --- .../call-builder/lib.rs | 70 ++++++++++++------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 643e0f2f771..7a018d8cc39 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -173,9 +173,11 @@ mod call_builder { async fn e2e_invalid_message_selector_can_be_handled( mut client: ink_e2e::Client, ) -> E2EResult<()> { + let origin = client.create_and_fund_account(&ink_e2e::alice(), 10_000_000_000_000).await; + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::alice(), constructor, 0, None) + .instantiate("call_builder", &origin, constructor, 0, None) .await .expect("instantiate failed") .account_id; @@ -184,7 +186,7 @@ mod call_builder { let flipper_acc_id = client .instantiate( "integration_flipper", - &ink_e2e::alice(), + &origin, flipper_constructor, 0, None, @@ -196,7 +198,7 @@ mod call_builder { let flipper_get = build_message::(flipper_acc_id) .call(|contract| contract.get()); let get_call_result = client - .call(&ink_e2e::alice(), flipper_get, 0, None) + .call(&origin, flipper_get, 0, None) .await .expect("Calling `flipper::get` failed"); let initial_value = get_call_result.return_value(); @@ -205,7 +207,7 @@ mod call_builder { let call = build_message::(contract_acc_id) .call(|contract| contract.call(flipper_acc_id, selector)); let call_result = client - .call(&ink_e2e::alice(), call, 0, None) + .call(&origin, call, 0, None) .await .expect("Calling `call_builder::call` failed"); @@ -219,7 +221,7 @@ mod call_builder { let flipper_get = build_message::(flipper_acc_id) .call(|contract| contract.get()); let get_call_result = client - .call(&ink_e2e::alice(), flipper_get, 0, None) + .call(&origin, flipper_get, 0, None) .await .expect("Calling `flipper::get` failed"); let flipped_value = get_call_result.return_value(); @@ -232,9 +234,11 @@ mod call_builder { async fn e2e_invalid_message_selector_panics_on_invoke( mut client: ink_e2e::Client, ) -> E2EResult<()> { + let origin = client.create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000).await; + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::ferdie(), constructor, 0, None) + .instantiate("call_builder", &origin, constructor, 0, None) .await .expect("instantiate failed") .account_id; @@ -243,7 +247,7 @@ mod call_builder { let flipper_acc_id = client .instantiate( "integration_flipper", - &ink_e2e::ferdie(), + &origin, flipper_constructor, 0, None, @@ -257,7 +261,7 @@ mod call_builder { let invalid_selector = [0x00, 0x00, 0x00, 0x00]; let call = build_message::(contract_acc_id) .call(|contract| contract.invoke(flipper_acc_id, invalid_selector)); - let call_result = client.call(&ink_e2e::ferdie(), call, 0, None).await; + let call_result = client.call(&origin, call, 0, None).await; assert!(call_result.is_err()); let contains_err_msg = match call_result.unwrap_err() { @@ -276,7 +280,7 @@ mod call_builder { async fn e2e_create_builder_works_with_valid_selector( mut client: ink_e2e::Client, ) -> E2EResult<()> { - let origin = client.create_and_fund_account(&ink_e2e::bob(), 1_000_000_000_000).await; + let origin = client.create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000).await; let constructor = CallBuilderTestRef::new(); let contract_acc_id = client @@ -315,15 +319,17 @@ mod call_builder { async fn e2e_create_builder_fails_with_invalid_selector( mut client: ink_e2e::Client, ) -> E2EResult<()> { + let origin = client.create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000).await; + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::charlie(), constructor, 0, None) + .instantiate("call_builder", &origin, constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::charlie(), None) + .upload("constructors_return_value", &origin, None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -335,7 +341,7 @@ mod call_builder { contract.call_instantiate(code_hash, selector, init_value) }); let call_result = client - .call(&ink_e2e::charlie(), call, 0, None) + .call(&origin, call, 0, None) .await .expect("Client failed to call `call_builder::call_instantiate`.") .return_value(); @@ -352,15 +358,17 @@ mod call_builder { async fn e2e_create_builder_with_infallible_revert_constructor_encodes_ok( mut client: ink_e2e::Client, ) -> E2EResult<()> { + let origin = client.create_and_fund_account(&ink_e2e::alice(), 10_000_000_000_000).await; + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::dave(), constructor, 0, None) + .instantiate("call_builder", &origin, constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::dave(), None) + .upload("constructors_return_value", &origin, None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -372,7 +380,7 @@ mod call_builder { contract.call_instantiate(code_hash, selector, init_value) }); - let call_result = client.call(&mut ink_e2e::dave(), call, 0, None).await; + let call_result = client.call(&origin, call, 0, None).await; assert!( call_result.is_err(), "Call execution should've failed, but didn't." @@ -396,15 +404,17 @@ mod call_builder { async fn e2e_create_builder_can_handle_fallible_constructor_success( mut client: ink_e2e::Client, ) -> E2EResult<()> { + let origin = client.create_and_fund_account(&ink_e2e::alice(), 10_000_000_000_000).await; + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::eve(), constructor, 0, None) + .instantiate("call_builder", &origin, constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::eve(), None) + .upload("constructors_return_value", &origin, None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -416,14 +426,14 @@ mod call_builder { contract.call_instantiate_fallible(code_hash, selector, init_value) }); let call_result = client - .call(&mut ink_e2e::eve(), call, 0, None) + .call(&origin, call, 0, None) .await .expect("Calling `call_builder::call_instantiate_fallible` failed") .return_value(); assert!( matches!(call_result, Some(Ok(_))), - "Call to falliable constructor failed, when it should have succeeded." + "Call to fallible constructor failed, when it should have succeeded." ); Ok(()) @@ -433,15 +443,17 @@ mod call_builder { async fn e2e_create_builder_can_handle_fallible_constructor_error( mut client: ink_e2e::Client, ) -> E2EResult<()> { + let origin = client.create_and_fund_account(&ink_e2e::alice(), 10_000_000_000_000).await; + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::ferdie(), constructor, 0, None) + .instantiate("call_builder", &origin, constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::ferdie(), None) + .upload("constructors_return_value", &origin, None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -477,15 +489,17 @@ mod call_builder { async fn e2e_create_builder_with_fallible_revert_constructor_encodes_ok( mut client: ink_e2e::Client, ) -> E2EResult<()> { + let origin = client.create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000).await; + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::alice(), constructor, 0, None) + .instantiate("call_builder", &origin, constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::alice(), None) + .upload("constructors_return_value", &origin, None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -496,7 +510,7 @@ mod call_builder { build_message::(contract_acc_id).call(|contract| { contract.call_instantiate_fallible(code_hash, selector, init_value) }); - let call_result = client.call(&mut ink_e2e::alice(), call, 0, None).await; + let call_result = client.call(&origin, call, 0, None).await; assert!( call_result.is_err(), @@ -522,15 +536,17 @@ mod call_builder { async fn e2e_create_builder_with_fallible_revert_constructor_encodes_err( mut client: ink_e2e::Client, ) -> E2EResult<()> { + let origin = client.create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000).await; + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::bob(), constructor, 0, None) + .instantiate("call_builder", &origin, constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::bob(), None) + .upload("constructors_return_value", &origin, None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -542,7 +558,7 @@ mod call_builder { contract.call_instantiate_fallible(code_hash, selector, init_value) }); let call_result = client - .call(&mut ink_e2e::bob(), call, 0, None) + .call(&origin, call, 0, None) .await .expect( "Client failed to call `call_builder::call_instantiate_fallible`.", From 7ad477babe39790fdda0c3cb58383f501e8bdf86 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 24 Jan 2023 18:32:39 +0000 Subject: [PATCH 201/206] Fix error --- .../call-builder/lib.rs | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index bcca01bbd0e..fbe029117c7 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -358,15 +358,17 @@ mod call_builder { async fn e2e_create_builder_with_infallible_revert_constructor_encodes_ok( mut client: ink_e2e::Client, ) -> E2EResult<()> { + let origin = client.create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000).await; + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::dave(), constructor, 0, None) + .instantiate("call_builder", &origin, constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::dave(), None) + .upload("constructors_return_value", &origin, None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -378,7 +380,7 @@ mod call_builder { contract.call_instantiate(code_hash, selector, init_value) }); - let call_result = client.call(&mut ink_e2e::dave(), call, 0, None).await; + let call_result = client.call(&origin, call, 0, None).await; assert!( call_result.is_err(), "Call execution should've failed, but didn't." @@ -402,15 +404,17 @@ mod call_builder { async fn e2e_create_builder_can_handle_fallible_constructor_success( mut client: ink_e2e::Client, ) -> E2EResult<()> { + let origin = client.create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000).await; + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::eve(), constructor, 0, None) + .instantiate("call_builder", &origin, constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::eve(), None) + .upload("constructors_return_value", &origin, None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -422,7 +426,7 @@ mod call_builder { contract.call_instantiate_fallible(code_hash, selector, init_value) }); let call_result = client - .call(&mut ink_e2e::eve(), call, 0, None) + .call(&origin, call, 0, None) .await .expect("Calling `call_builder::call_instantiate_fallible` failed") .return_value(); @@ -439,15 +443,17 @@ mod call_builder { async fn e2e_create_builder_can_handle_fallible_constructor_error( mut client: ink_e2e::Client, ) -> E2EResult<()> { + let origin = client.create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000).await; + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::ferdie(), constructor, 0, None) + .instantiate("call_builder", &origin, constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::ferdie(), None) + .upload("constructors_return_value", &origin, None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -459,7 +465,7 @@ mod call_builder { contract.call_instantiate_fallible(code_hash, selector, init_value) }); let call_result = client - .call(&mut ink_e2e::ferdie(), call, 0, None) + .call(&origin, call, 0, None) .await .expect("Calling `call_builder::call_instantiate_fallible` failed") .return_value(); @@ -483,15 +489,17 @@ mod call_builder { async fn e2e_create_builder_with_fallible_revert_constructor_encodes_ok( mut client: ink_e2e::Client, ) -> E2EResult<()> { + let origin = client.create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000).await; + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::alice(), constructor, 0, None) + .instantiate("call_builder", &origin, constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::alice(), None) + .upload("constructors_return_value", &origin, None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -502,7 +510,7 @@ mod call_builder { build_message::(contract_acc_id).call(|contract| { contract.call_instantiate_fallible(code_hash, selector, init_value) }); - let call_result = client.call(&mut ink_e2e::alice(), call, 0, None).await; + let call_result = client.call(&origin, call, 0, None).await; assert!( call_result.is_err(), @@ -528,15 +536,17 @@ mod call_builder { async fn e2e_create_builder_with_fallible_revert_constructor_encodes_err( mut client: ink_e2e::Client, ) -> E2EResult<()> { + let origin = client.create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000).await; + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client - .instantiate("call_builder", &ink_e2e::bob(), constructor, 0, None) + .instantiate("call_builder", &origin, constructor, 0, None) .await .expect("instantiate failed") .account_id; let code_hash = client - .upload("constructors_return_value", &ink_e2e::bob(), None) + .upload("constructors_return_value", &origin, None) .await .expect("upload `constructors_return_value` failed") .code_hash; @@ -548,7 +558,7 @@ mod call_builder { contract.call_instantiate_fallible(code_hash, selector, init_value) }); let call_result = client - .call(&mut ink_e2e::bob(), call, 0, None) + .call(&origin, call, 0, None) .await .expect( "Client failed to call `call_builder::call_instantiate_fallible`.", From 2f4df6475ae2d7fa294191c3a3f11775ac637fa1 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 24 Jan 2023 18:35:07 +0000 Subject: [PATCH 202/206] Fmt --- .../call-builder/lib.rs | 56 ++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index fbe029117c7..874138c29ed 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -173,7 +173,9 @@ mod call_builder { async fn e2e_invalid_message_selector_can_be_handled( mut client: ink_e2e::Client, ) -> E2EResult<()> { - let origin = client.create_and_fund_account(&ink_e2e::alice(), 10_000_000_000_000).await; + let origin = client + .create_and_fund_account(&ink_e2e::alice(), 10_000_000_000_000) + .await; let constructor = CallBuilderTestRef::new(); let contract_acc_id = client @@ -184,13 +186,7 @@ mod call_builder { let flipper_constructor = FlipperRef::new_default(); let flipper_acc_id = client - .instantiate( - "integration_flipper", - &origin, - flipper_constructor, - 0, - None, - ) + .instantiate("integration_flipper", &origin, flipper_constructor, 0, None) .await .expect("instantiate `flipper` failed") .account_id; @@ -234,7 +230,9 @@ mod call_builder { async fn e2e_invalid_message_selector_panics_on_invoke( mut client: ink_e2e::Client, ) -> E2EResult<()> { - let origin = client.create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000).await; + let origin = client + .create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000) + .await; let constructor = CallBuilderTestRef::new(); let contract_acc_id = client @@ -245,13 +243,7 @@ mod call_builder { let flipper_constructor = FlipperRef::new_default(); let flipper_acc_id = client - .instantiate( - "integration_flipper", - &origin, - flipper_constructor, - 0, - None, - ) + .instantiate("integration_flipper", &origin, flipper_constructor, 0, None) .await .expect("instantiate `flipper` failed") .account_id; @@ -280,7 +272,9 @@ mod call_builder { async fn e2e_create_builder_works_with_valid_selector( mut client: ink_e2e::Client, ) -> E2EResult<()> { - let origin = client.create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000).await; + let origin = client + .create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000) + .await; let constructor = CallBuilderTestRef::new(); let contract_acc_id = client @@ -319,7 +313,9 @@ mod call_builder { async fn e2e_create_builder_fails_with_invalid_selector( mut client: ink_e2e::Client, ) -> E2EResult<()> { - let origin = client.create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000).await; + let origin = client + .create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000) + .await; let constructor = CallBuilderTestRef::new(); let contract_acc_id = client @@ -358,7 +354,9 @@ mod call_builder { async fn e2e_create_builder_with_infallible_revert_constructor_encodes_ok( mut client: ink_e2e::Client, ) -> E2EResult<()> { - let origin = client.create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000).await; + let origin = client + .create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000) + .await; let constructor = CallBuilderTestRef::new(); let contract_acc_id = client @@ -404,7 +402,9 @@ mod call_builder { async fn e2e_create_builder_can_handle_fallible_constructor_success( mut client: ink_e2e::Client, ) -> E2EResult<()> { - let origin = client.create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000).await; + let origin = client + .create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000) + .await; let constructor = CallBuilderTestRef::new(); let contract_acc_id = client @@ -443,8 +443,10 @@ mod call_builder { async fn e2e_create_builder_can_handle_fallible_constructor_error( mut client: ink_e2e::Client, ) -> E2EResult<()> { - let origin = client.create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000).await; - + let origin = client + .create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000) + .await; + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client .instantiate("call_builder", &origin, constructor, 0, None) @@ -489,8 +491,10 @@ mod call_builder { async fn e2e_create_builder_with_fallible_revert_constructor_encodes_ok( mut client: ink_e2e::Client, ) -> E2EResult<()> { - let origin = client.create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000).await; - + let origin = client + .create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000) + .await; + let constructor = CallBuilderTestRef::new(); let contract_acc_id = client .instantiate("call_builder", &origin, constructor, 0, None) @@ -536,7 +540,9 @@ mod call_builder { async fn e2e_create_builder_with_fallible_revert_constructor_encodes_err( mut client: ink_e2e::Client, ) -> E2EResult<()> { - let origin = client.create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000).await; + let origin = client + .create_and_fund_account(&ink_e2e::bob(), 10_000_000_000_000) + .await; let constructor = CallBuilderTestRef::new(); let contract_acc_id = client From 7f8016b6fe492b33ab93b96d03d12c8c92f8dba4 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 24 Jan 2023 18:37:23 +0000 Subject: [PATCH 203/206] SP --- crates/e2e/src/client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/e2e/src/client.rs b/crates/e2e/src/client.rs index 0a5fb224ca8..1d7a53b2003 100644 --- a/crates/e2e/src/client.rs +++ b/crates/e2e/src/client.rs @@ -342,7 +342,7 @@ where /// Generate a new keypair and fund with the given amount from the origin account. /// /// Because many tests may execute this in parallel, transfers may fail due to a race condition - /// with account nonces. Therefore this will reattempt transfers a number of times. + /// with account indices. Therefore this will reattempt transfers a number of times. pub async fn create_and_fund_account( &self, origin: &Signer, From 6c2beb9753441664d92860cdba676a75ad2cdfa2 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 24 Jan 2023 18:42:20 +0000 Subject: [PATCH 204/206] Clippy --- crates/e2e/src/client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/e2e/src/client.rs b/crates/e2e/src/client.rs index 1d7a53b2003..5dd976b1917 100644 --- a/crates/e2e/src/client.rs +++ b/crates/e2e/src/client.rs @@ -359,7 +359,7 @@ where for _ in 0..6 { let transfer_result = self .api - .try_transfer_balance(origin, account_id.clone(), amount.clone()) + .try_transfer_balance(origin, account_id.clone(), amount) .await; match transfer_result { Ok(_) => { From b584734d5f8599d0d79e135ed753992d6ab1fb72 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 24 Jan 2023 18:57:07 +0000 Subject: [PATCH 205/206] Remove commented out code --- crates/e2e/src/xts.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/crates/e2e/src/xts.rs b/crates/e2e/src/xts.rs index 34391d44ea4..b09574bac97 100644 --- a/crates/e2e/src/xts.rs +++ b/crates/e2e/src/xts.rs @@ -45,14 +45,6 @@ use subxt::{ OnlineClient, }; -/// A raw call to `pallet-balances` `transfer`. -// #[derive(Debug, scale::Encode)] -// pub struct Transfer { -// dest: sp_runtime::MultiAddress, -// #[codec(compact)] -// value: B, -// } - /// A raw call to `pallet-contracts`'s `instantiate_with_code`. #[derive(Debug, scale::Encode, scale::Decode)] pub struct InstantiateWithCode { From 1159ab69e1eb5d71342ee1038da7cab57d012954 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 24 Jan 2023 18:57:53 +0000 Subject: [PATCH 206/206] Update crates/e2e/src/xts.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michael Müller --- crates/e2e/src/xts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/e2e/src/xts.rs b/crates/e2e/src/xts.rs index b09574bac97..eab05f73ae0 100644 --- a/crates/e2e/src/xts.rs +++ b/crates/e2e/src/xts.rs @@ -207,7 +207,7 @@ where /// Attempt to transfer the `value` from `origin` to `dest`. /// - /// Returns `Ok` if on success, and a [`subxt::Error`] if the extrinsic is + /// Returns `Ok` on success, and a [`subxt::Error`] if the extrinsic is /// invalid (e.g. out of date nonce) pub async fn try_transfer_balance( &self,