From 3758e09345cfdf32a3b2df0e54fcc11187e612eb Mon Sep 17 00:00:00 2001 From: andrew Date: Fri, 13 Jan 2023 17:56:43 +0000 Subject: [PATCH 01/58] 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 02/58] 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 03/58] 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 04/58] 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 05/58] 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 06/58] 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 07/58] 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 08/58] 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 09/58] 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 10/58] 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 11/58] 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 12/58] 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 13/58] 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 14/58] 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 15/58] 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 16/58] 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 17/58] 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 18/58] 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 19/58] 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 20/58] 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 21/58] 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 22/58] 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 23/58] 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 24/58] 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 25/58] 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 26/58] 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 27/58] 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 28/58] 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 29/58] 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 30/58] 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 31/58] 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 32/58] 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 33/58] 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 34/58] 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 35/58] 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 36/58] 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 37/58] 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 38/58] 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 39/58] 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 40/58] 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 41/58] 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 42/58] 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 43/58] 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 44/58] 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 45/58] 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 46/58] Clippy From 7d03708a2cad79f31b87367f5d01dd1e7e60dc29 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 20 Jan 2023 18:14:24 +0000 Subject: [PATCH 47/58] 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 48/58] 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 49/58] 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 50/58] 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 51/58] 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 52/58] 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 53/58] 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 54/58] 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 55/58] 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 56/58] 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 57/58] 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 58/58] 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])