From b84defe6097d85054114fd9891dbf905ce0c3ec9 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 21 Feb 2024 14:45:21 +0000 Subject: [PATCH 01/19] WIP Scaffolding for using instantiate_v2 --- crates/env/src/api.rs | 41 +- crates/env/src/backend.rs | 19 +- crates/env/src/call/create_builder.rs | 349 +++++++++++++----- crates/env/src/call/mod.rs | 2 + crates/env/src/engine/off_chain/impls.rs | 31 +- crates/env/src/engine/on_chain/impls.rs | 4 +- crates/ink/src/env_access.rs | 22 +- .../cross-contract-calls/e2e_tests.rs | 48 ++- integration-tests/cross-contract-calls/lib.rs | 39 +- 9 files changed, 457 insertions(+), 98 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index daac732e899..bab8c488f77 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -27,6 +27,8 @@ use crate::{ CreateParams, DelegateCall, FromAccountId, + LimitParamsV1, + LimitParamsV2, }, engine::{ EnvInstance, @@ -366,7 +368,7 @@ where /// - If given insufficient endowment. /// - If the returned account ID failed to decode properly. pub fn instantiate_contract( - params: &CreateParams, + params: &CreateParams, Args, Salt, R>, ) -> Result< ink_primitives::ConstructorResult<>::Output>, > @@ -384,6 +386,43 @@ where }) } +/// Instantiates another contract. +/// +/// # 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_contract_v1( + params: &CreateParams, +) -> Result< + ink_primitives::ConstructorResult<>::Output>, +> +where + E: Environment, + ContractRef: FromAccountId, + Args: scale::Encode, + Salt: AsRef<[u8]>, + R: ConstructorReturnType, +{ + ::on_instance(|instance| { + TypedEnvBackend::instantiate_contract_v1::( + 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 43597082b37..2316f9ee00d 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -21,6 +21,8 @@ use crate::{ CreateParams, DelegateCall, FromAccountId, + LimitParamsV1, + LimitParamsV2, }, event::Event, hash::{ @@ -345,7 +347,22 @@ pub trait TypedEnvBackend: EnvBackend { /// For more details visit: [`instantiate_contract`][`crate::instantiate_contract`] fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, Args, Salt, R>, + ) -> Result< + ink_primitives::ConstructorResult< + >::Output, + >, + > + where + E: Environment, + ContractRef: FromAccountId, + Args: scale::Encode, + Salt: AsRef<[u8]>, + R: ConstructorReturnType; + + fn instantiate_contract_v1( + &mut self, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult< >::Output, diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 2cfb62eb543..1ed1a0fbcd0 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -19,7 +19,6 @@ use crate::{ ReturnType, Set, Unset, - Unwrap, }, ExecutionInput, Selector, @@ -166,16 +165,34 @@ where } } +/// todo: [AJ] docs +#[derive(Debug)] +pub struct LimitParamsV1 { + gas_limit: u64, +} + +/// todo: [AJ] docs +#[derive(Debug)] +pub struct LimitParamsV2 +where + E: Environment, +{ + ref_time_limit: u64, + proof_time_limit: u64, + storage_deposit_limit: Option, +} + /// Builds up contract instantiations. #[derive(Debug)] -pub struct CreateParams +pub struct CreateParams where E: Environment, { /// The code hash of the created contract. code_hash: E::Hash, - /// The maximum gas costs allowed for the instantiation. - gas_limit: u64, + /// Parameters for weight and storage limits, differs for versions of the instantiate + /// host function. + limits: Limits, /// The endowment for the instantiated contract. endowment: E::Balance, /// The input data for the instantiation. @@ -188,7 +205,8 @@ where _phantom: PhantomData ContractRef>, } -impl CreateParams +impl + CreateParams where E: Environment, { @@ -198,12 +216,6 @@ where &self.code_hash } - /// The gas limit for the contract instantiation. - #[inline] - pub fn gas_limit(&self) -> u64 { - self.gas_limit - } - /// The endowment for the instantiated contract. #[inline] pub fn endowment(&self) -> &E::Balance { @@ -225,7 +237,44 @@ where } } -impl CreateParams +impl + CreateParams, Args, Salt, R> +where + E: Environment, +{ + /// todo: [AJ] docs + #[inline] + pub fn ref_time_limit(&self) -> u64 { + self.limits.ref_time_limit + } + + /// todo: [AJ] docs + #[inline] + pub fn proof_time_limit(&self) -> u64 { + self.limits.proof_time_limit + } + + /// todo: [AJ] docs + #[inline] + pub fn storage_deposit_limit(&self) -> Option<&E::Balance> { + self.limits.storage_deposit_limit.as_ref() + } +} + +impl + CreateParams +where + E: Environment, +{ + /// The gas limit for the contract instantiation. + #[inline] + pub fn gas_limit(&self) -> u64 { + self.limits.gas_limit + } +} + +impl + CreateParams where E: Environment, Salt: AsRef<[u8]>, @@ -237,7 +286,8 @@ where } } -impl CreateParams +impl + CreateParams, Args, Salt, R> where E: Environment, ContractRef: FromAccountId, @@ -278,28 +328,68 @@ where ink_primitives::ConstructorResult< >::Output, >, - crate::Error, + Error, > { crate::instantiate_contract(self) } } +impl + CreateParams +where + E: Environment, + ContractRef: FromAccountId, + Args: scale::Encode, + Salt: AsRef<[u8]>, + R: ConstructorReturnType, +{ + /// Instantiates the contract and returns its account ID 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`][`CreateParams::try_instantiate`] method + /// instead. + #[inline] + pub fn instantiate(&self) -> >::Output { + self.try_instantiate() + .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:?}") + }) + } + + /// Instantiates the contract and returns its account ID 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( + &self, + ) -> Result< + ink_primitives::ConstructorResult< + >::Output, + >, + Error, + > { + crate::instantiate_contract_v1(self) + } +} + /// Builds up contract instantiations. #[derive(Clone)] -pub struct CreateBuilder< - E, - ContractRef, - CodeHash, - GasLimit, - Endowment, - Args, - Salt, - RetType, -> where +pub struct CreateBuilder +where E: Environment, { code_hash: CodeHash, - gas_limit: GasLimit, + limits: Limits, endowment: Endowment, exec_input: Args, salt: Salt, @@ -415,7 +505,7 @@ pub fn build_create() -> CreateBuilder< ::Env, ContractRef, Unset<<::Env as Environment>::Hash>, - Unset, + Set::Env>>, Unset<<::Env as Environment>::Balance>, Unset>, Unset, @@ -426,7 +516,11 @@ where { CreateBuilder { code_hash: Default::default(), - gas_limit: Default::default(), + limits: Set(LimitParamsV2 { + ref_time_limit: 0, + proof_time_limit: 0, + storage_deposit_limit: None, + }), endowment: Default::default(), exec_input: Default::default(), salt: Default::default(), @@ -435,17 +529,8 @@ where } } -impl - CreateBuilder< - E, - ContractRef, - Unset, - GasLimit, - Endowment, - Args, - Salt, - RetType, - > +impl + CreateBuilder, Limits, Endowment, Args, Salt, RetType> where E: Environment, { @@ -454,19 +539,11 @@ where pub fn code_hash( self, code_hash: E::Hash, - ) -> CreateBuilder< - E, - ContractRef, - Set, - GasLimit, - Endowment, - Args, - Salt, - RetType, - > { + ) -> CreateBuilder, Limits, Endowment, Args, Salt, RetType> + { CreateBuilder { code_hash: Set(code_hash), - gas_limit: self.gas_limit, + limits: self.limits, endowment: self.endowment, exec_input: self.exec_input, salt: self.salt, @@ -477,35 +554,86 @@ where } impl - CreateBuilder, Endowment, Args, Salt, RetType> + CreateBuilder< + E, + ContractRef, + CodeHash, + Set, + Endowment, + Args, + Salt, + RetType, + > where E: Environment, { /// Sets the maximum allowed gas costs for the contract instantiation. #[inline] - pub fn gas_limit( - self, - gas_limit: u64, - ) -> CreateBuilder, Endowment, Args, Salt, RetType> - { + pub fn gas_limit(self, gas_limit: u64) -> Self { CreateBuilder { - code_hash: self.code_hash, - gas_limit: Set(gas_limit), - endowment: self.endowment, - exec_input: self.exec_input, - salt: self.salt, - return_type: self.return_type, - _phantom: Default::default(), + limits: Set(LimitParamsV1 { gas_limit }), + ..self + } + } +} + +impl + CreateBuilder< + E, + ContractRef, + CodeHash, + Set>, + Endowment, + Args, + Salt, + RetType, + > +where + E: Environment, +{ + /// todo: [AJ] comment + #[inline] + pub fn ref_time_limit(self, ref_time_limit: u64) -> Self { + CreateBuilder { + limits: Set(LimitParamsV2 { + ref_time_limit, + ..self.limits.value() + }), + ..self + } + } + + /// todo: [AJ] comment + #[inline] + pub fn proof_time_limit(self, proof_time_limit: u64) -> Self { + CreateBuilder { + limits: Set(LimitParamsV2 { + proof_time_limit, + ..self.limits.value() + }), + ..self + } + } + + /// todo: [AJ] comment + #[inline] + pub fn storage_deposit_limit(self, storage_deposit_limit: E::Balance) -> Self { + CreateBuilder { + limits: Set(LimitParamsV2 { + storage_deposit_limit: Some(storage_deposit_limit), + ..self.limits.value() + }), + ..self } } } -impl +impl CreateBuilder< E, ContractRef, CodeHash, - GasLimit, + Limits, Unset, Args, Salt, @@ -523,7 +651,7 @@ where E, ContractRef, CodeHash, - GasLimit, + Limits, Set, Args, Salt, @@ -531,7 +659,7 @@ where > { CreateBuilder { code_hash: self.code_hash, - gas_limit: self.gas_limit, + limits: self.limits, endowment: Set(endowment), exec_input: self.exec_input, salt: self.salt, @@ -541,12 +669,12 @@ where } } -impl +impl CreateBuilder< E, ContractRef, CodeHash, - GasLimit, + Limits, Endowment, Unset>, Salt, @@ -564,7 +692,7 @@ where E, ContractRef, CodeHash, - GasLimit, + Limits, Endowment, Set>, Salt, @@ -572,7 +700,7 @@ where > { CreateBuilder { code_hash: self.code_hash, - gas_limit: self.gas_limit, + limits: self.limits, endowment: self.endowment, exec_input: Set(exec_input), salt: self.salt, @@ -582,12 +710,12 @@ where } } -impl +impl CreateBuilder< E, ContractRef, CodeHash, - GasLimit, + Limits, Endowment, Args, Unset, @@ -605,7 +733,7 @@ where E, ContractRef, CodeHash, - GasLimit, + Limits, Endowment, Args, Set, @@ -616,7 +744,7 @@ where { CreateBuilder { code_hash: self.code_hash, - gas_limit: self.gas_limit, + limits: self.limits, endowment: self.endowment, exec_input: self.exec_input, salt: Set(salt), @@ -626,12 +754,12 @@ where } } -impl +impl CreateBuilder< E, ContractRef, CodeHash, - GasLimit, + Limits, Endowment, Args, Salt, @@ -656,7 +784,7 @@ where E, ContractRef, CodeHash, - GasLimit, + Limits, Endowment, Args, Salt, @@ -668,7 +796,7 @@ where { CreateBuilder { code_hash: self.code_hash, - gas_limit: self.gas_limit, + limits: self.limits, endowment: self.endowment, exec_input: self.exec_input, salt: self.salt, @@ -678,12 +806,12 @@ where } } -impl +impl CreateBuilder< E, ContractRef, Set, - GasLimit, + Set, Set, Set>, Set, @@ -691,14 +819,13 @@ impl > where E: Environment, - GasLimit: Unwrap, { /// 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), + limits: self.limits.value(), endowment: self.endowment.value(), exec_input: self.exec_input.value(), salt_bytes: self.salt.value(), @@ -708,12 +835,63 @@ where } } -impl +impl + CreateBuilder< + E, + ContractRef, + Set, + Set>, + Set, + Set>, + Set, + Set>, + > +where + E: Environment, + ContractRef: FromAccountId, + Args: scale::Encode, + Salt: AsRef<[u8]>, + RetType: ConstructorReturnType, +{ + /// Instantiates the contract and returns its account ID 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`][`CreateBuilder::try_instantiate`] method + /// instead. + #[inline] + pub fn instantiate(self) -> >::Output { + self.params().instantiate() + } + + /// Instantiates the contract and returns its account ID 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( + self, + ) -> Result< + ink_primitives::ConstructorResult< + >::Output, + >, + Error, + > { + self.params().try_instantiate() + } +} + +impl CreateBuilder< E, ContractRef, Set, - GasLimit, + Set, Set, Set>, Set, @@ -722,7 +900,6 @@ impl where E: Environment, ContractRef: FromAccountId, - GasLimit: Unwrap, Args: scale::Encode, Salt: AsRef<[u8]>, RetType: ConstructorReturnType, diff --git a/crates/env/src/call/mod.rs b/crates/env/src/call/mod.rs index a3f97ec5de5..60c3f2ff556 100644 --- a/crates/env/src/call/mod.rs +++ b/crates/env/src/call/mod.rs @@ -55,6 +55,8 @@ pub use self::{ CreateBuilder, CreateParams, FromAccountId, + LimitParamsV1, + LimitParamsV2, }, execution_input::ExecutionInput, selector::Selector, diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 2e567004f2b..d9b3af1d14c 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -22,6 +22,8 @@ use crate::{ CreateParams, DelegateCall, FromAccountId, + LimitParamsV1, + LimitParamsV2, }, event::{ Event, @@ -478,7 +480,7 @@ impl TypedEnvBackend for EnvInstance { fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, Args, Salt, R>, ) -> Result< ink_primitives::ConstructorResult< >::Output, @@ -492,7 +494,32 @@ impl TypedEnvBackend for EnvInstance { R: ConstructorReturnType, { let _code_hash = params.code_hash(); - let _gas_limit = params.gas_limit(); + let _ref_time_limit = params.ref_time_limit(); + let _proof_time_limit = params.proof_time_limit(); + let _storage_deposit_limit = params.storage_deposit_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_contract_v1( + &mut self, + params: &CreateParams, + ) -> Result< + ink_primitives::ConstructorResult< + >::Output, + >, + > + where + E: Environment, + ContractRef: FromAccountId, + Args: scale::Encode, + Salt: AsRef<[u8]>, + R: ConstructorReturnType, + { + let _code_hash = params.code_hash(); + let _ref_time_limit = params.gas_limit(); let _endowment = params.endowment(); let _input = params.exec_input(); let _salt_bytes = params.salt_bytes(); diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index ce36767ab90..e3c1bfeb211 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -543,9 +543,9 @@ impl TypedEnvBackend for EnvInstance { } } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult< >::Output, diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 7dc17992ae9..a1bdfd11a21 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -23,6 +23,8 @@ use ink_env::{ CreateParams, DelegateCall, FromAccountId, + LimitParamsV1, + LimitParamsV2, }, hash::{ CryptoHash, @@ -493,7 +495,7 @@ where /// For more details visit: [`ink_env::instantiate_contract`] pub fn instantiate_contract( self, - params: &CreateParams, + params: &CreateParams, Args, Salt, R>, ) -> Result< ink_primitives::ConstructorResult< >::Output, @@ -508,6 +510,24 @@ where ink_env::instantiate_contract::(params) } + /// todo: [AJ] docs + pub fn instantiate_contract_v1( + self, + params: &CreateParams, + ) -> Result< + ink_primitives::ConstructorResult< + >::Output, + >, + > + where + ContractRef: FromAccountId, + Args: scale::Encode, + Salt: AsRef<[u8]>, + R: ConstructorReturnType, + { + ink_env::instantiate_contract_v1::(params) + } + /// Invokes a contract message and returns its result. /// /// # Example diff --git a/integration-tests/cross-contract-calls/e2e_tests.rs b/integration-tests/cross-contract-calls/e2e_tests.rs index d26301dc694..861c1169d1f 100644 --- a/integration-tests/cross-contract-calls/e2e_tests.rs +++ b/integration-tests/cross-contract-calls/e2e_tests.rs @@ -12,7 +12,7 @@ async fn flip_and_get(mut client: Client) -> E2EResult<()> { .await .expect("other_contract upload failed"); - let mut constructor = CrossContractCallsRef::new(other_contract_code.code_hash); + let mut constructor = CrossContractCallsRef::new_v1(other_contract_code.code_hash); let contract = client .instantiate("cross-contract-calls", &ink_e2e::alice(), &mut constructor) .submit() @@ -34,6 +34,50 @@ async fn flip_and_get(mut client: Client) -> E2EResult<()> { Ok(()) } +#[ink_e2e::test] +async fn instantiate_v2_with_limits(mut client: Client) -> E2EResult<()> { + // given + let other_contract_code = client + .upload("other-contract", &ink_e2e::alice()) + .submit() + .await + .expect("other_contract upload failed"); + + const REF_TIME_LIMIT: u64 = 500_000_000; + const PROOF_TIME_LIMIT: u64 = 100_000; + const STORAGE_DEPOSIT_LIMIT: u128 = 1_000_000_000; + + let mut constructor = CrossContractCallsRef::new_v2_with_limits(other_contract_code.code_hash, + REF_TIME_LIMIT, + PROOF_TIME_LIMIT, + STORAGE_DEPOSIT_LIMIT + ); + let contract = client + .instantiate("cross-contract-calls", &ink_e2e::alice(), &mut constructor) + .submit() + .await; + + assert!(contract.is_ok()); +} + +#[ink_e2e::test] +async fn instantiate_v2_no_limits(mut client: Client) -> E2EResult<()> { + // given + let other_contract_code = client + .upload("other-contract", &ink_e2e::alice()) + .submit() + .await + .expect("other_contract upload failed"); + + let mut constructor = CrossContractCallsRef::new_v2_no_limits(other_contract_code.code_hash); + let contract = client + .instantiate("cross-contract-calls", &ink_e2e::alice(), &mut constructor) + .submit() + .await; + + assert!(contract.is_ok()); +} + #[ink_e2e::test] async fn flip_and_get_v2(mut client: Client) -> E2EResult<()> { // given @@ -43,7 +87,7 @@ async fn flip_and_get_v2(mut client: Client) -> E2EResult<() .await .expect("other_contract upload failed"); - let mut constructor = CrossContractCallsRef::new(other_contract_code.code_hash); + let mut constructor = CrossContractCallsRef::new_v1(other_contract_code.code_hash); let contract = client .instantiate("cross-contract-calls", &ink_e2e::alice(), &mut constructor) .submit() diff --git a/integration-tests/cross-contract-calls/lib.rs b/integration-tests/cross-contract-calls/lib.rs index 3cd90fc1371..9a0bf8b1643 100755 --- a/integration-tests/cross-contract-calls/lib.rs +++ b/integration-tests/cross-contract-calls/lib.rs @@ -11,11 +11,44 @@ mod cross_contract_calls { } impl CrossContractCalls { - /// Initializes the contract by instantiating the code at the given code hash and - /// storing the resulting account id. + /// Initializes the contract by instantiating the code at the given code hash via + /// `instantiate_v2` host function with the supplied weight and storage + /// limits. #[ink(constructor)] - pub fn new(other_contract_code_hash: Hash) -> Self { + pub fn new_v2_with_limits( + other_contract_code_hash: Hash, + ref_time_limit: u64, + proof_time_limit: u64, + storage_deposit_limit: Balance, + ) -> Self { + let other_contract = OtherContractRef::new(true) + .code_hash(other_contract_code_hash) + .endowment(0) + .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) + .instantiate(); + + Self { other_contract } + } + + /// Initializes the contract by instantiating the code at the given code hash via + /// the `instantiate_v2` host function with no weight or storage limits. + #[ink(constructor)] + pub fn new_v2_no_limits(other_contract_code_hash: Hash) -> Self { + let other_contract = OtherContractRef::new(true) + .code_hash(other_contract_code_hash) + .endowment(0) + .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) + .instantiate(); + + Self { other_contract } + } + + /// Initializes the contract by instantiating the code at the given code hash via + /// the original `instantiate` host function. + #[ink(constructor)] + pub fn new_v1(other_contract_code_hash: Hash) -> Self { let other_contract = OtherContractRef::new(true) + .v1() .code_hash(other_contract_code_hash) .endowment(0) .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) From 7f95df5f7e69578bf93753b46094a2f6302d3096 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 21 Feb 2024 15:23:29 +0000 Subject: [PATCH 02/19] onchain impls and codegen --- crates/env/src/engine/on_chain/impls.rs | 56 ++++++++++++++++++- .../generator/as_dependency/contract_ref.rs | 3 +- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index e3c1bfeb211..a9bbfba1cca 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -25,6 +25,8 @@ use crate::{ CreateParams, DelegateCall, FromAccountId, + LimitParamsV1, + LimitParamsV2, }, event::{ Event, @@ -543,9 +545,59 @@ impl TypedEnvBackend for EnvInstance { } } - fn instantiate_contract( + fn instantiate_contract( &mut self, - params: &CreateParams, + params: &CreateParams, Args, Salt, RetType>, + ) -> Result< + ink_primitives::ConstructorResult< + >::Output, + >, + > + where + E: Environment, + ContractRef: FromAccountId, + Args: scale::Encode, + Salt: AsRef<[u8]>, + RetType: ConstructorReturnType, + { + let mut scoped = self.scoped_buffer(); + let ref_time_limit = params.ref_time_limit(); + let proof_time_limit = params.proof_time_limit(); + let storage_deposit_limit = params + .storage_deposit_limit() + .map(|limit| &*scoped.take_encoded(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_v2( + enc_code_hash, + ref_time_limit, + proof_time_limit, + storage_deposit_limit, + enc_endowment, + enc_input, + Some(out_address), + Some(out_return_value), + salt, + ); + + crate::engine::decode_instantiate_result::<_, E, ContractRef, RetType>( + instantiate_result.map_err(Into::into), + &mut &out_address[..], + &mut &out_return_value[..], + ) + } + + fn instantiate_contract_v1( + &mut self, + params: &CreateParams, ) -> Result< ink_primitives::ConstructorResult< >::Output, 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 0801345fb60..e646f665cfc 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -444,6 +444,7 @@ impl ContractRef<'_> { let selector_bytes = constructor.composed_selector().hex_lits(); let input_bindings = generator::input_bindings(constructor.inputs()); let input_types = generator::input_types(constructor.inputs()); + let storage_ident = self.contract.module().storage().ident(); let arg_list = generator::generate_argument_list(input_types.iter().cloned()); let ret_type = constructor .output() @@ -459,7 +460,7 @@ impl ContractRef<'_> { Environment, Self, ::ink::env::call::utils::Unset, - ::ink::env::call::utils::Unset, + ::ink::env::call::utils::Set<::ink::env::call::LimitParamsV2<<#storage_ident as ::ink::env::ContractEnv>::Env>>, ::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>, From af50a8b1924f7b273e7229f04458694324e7fc54 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 23 Feb 2024 09:26:31 +0000 Subject: [PATCH 03/19] WIP add v1 builder method --- crates/env/src/call/create_builder.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 1ed1a0fbcd0..829391894dd 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -591,6 +591,31 @@ impl where E: Environment, { + /// todo: [AJ] comment + #[inline] + pub fn instantiate_v1(self) -> CreateBuilder< + E, + ContractRef, + CodeHash, + Set, + Endowment, + Args, + Salt, + RetType, + > { + CreateBuilder { + code_hash: (), + limits: Set(LimitParamsV1 { + gas_limit: self.limits.value().ref_time_limit, + }), + endowment: self.endowment, + exec_input: self.exec_input, + salt: self.salt, + return_type: self.return_type, + _phantom: Default::default(), + } + } + /// todo: [AJ] comment #[inline] pub fn ref_time_limit(self, ref_time_limit: u64) -> Self { From 96840c49ca33a3c2a470bd3742992b9b4c872fdd Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 23 Feb 2024 14:25:22 +0000 Subject: [PATCH 04/19] fixes --- crates/e2e/src/builders.rs | 3 ++- crates/env/src/call/create_builder.rs | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/e2e/src/builders.rs b/crates/e2e/src/builders.rs index 0de77855b71..4e71ab14121 100644 --- a/crates/e2e/src/builders.rs +++ b/crates/e2e/src/builders.rs @@ -21,6 +21,7 @@ use ink_env::{ }, CreateBuilder, ExecutionInput, + LimitParamsV2, }, Environment, }; @@ -32,7 +33,7 @@ pub type CreateBuilderPartial = CreateBuilder< E, ContractRef, Unset<::Hash>, - Unset, + Set>, Unset<::Balance>, Set>, Unset, diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 829391894dd..4141bda30db 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -166,13 +166,13 @@ where } /// todo: [AJ] docs -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct LimitParamsV1 { gas_limit: u64, } /// todo: [AJ] docs -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct LimitParamsV2 where E: Environment, @@ -604,7 +604,7 @@ where RetType, > { CreateBuilder { - code_hash: (), + code_hash: self.code_hash, limits: Set(LimitParamsV1 { gas_limit: self.limits.value().ref_time_limit, }), From 16214602289e50271145a17f4072fbacfcf43bef Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 23 Feb 2024 17:24:23 +0000 Subject: [PATCH 05/19] Fix existing delegator README --- integration-tests/upgradeable-contracts/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/upgradeable-contracts/README.md b/integration-tests/upgradeable-contracts/README.md index 74a25d764ce..85ed2765bb3 100644 --- a/integration-tests/upgradeable-contracts/README.md +++ b/integration-tests/upgradeable-contracts/README.md @@ -29,7 +29,7 @@ called again, since it will fail to load the migrated storage. ## [Delegator](delegator/) -Delegator patter is based around a low level cross contract call function `delegate_call`. +The Delegator pattern is based around the low level host function `delegate_call`. It allows a contract to delegate its execution to some on-chain uploaded code. It is different from a traditional cross-contract call From 28849b5981d20880d3af1768875331b05e8fb00a Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 23 Feb 2024 17:33:08 +0000 Subject: [PATCH 06/19] Update delegator README --- integration-tests/upgradeable-contracts/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/integration-tests/upgradeable-contracts/README.md b/integration-tests/upgradeable-contracts/README.md index 85ed2765bb3..8b83108277a 100644 --- a/integration-tests/upgradeable-contracts/README.md +++ b/integration-tests/upgradeable-contracts/README.md @@ -49,3 +49,14 @@ This is because `Lazy` and `Mapping` interact with the storage directly instead If your storage is completely layoutless (it only contains `Lazy` and `Mapping` fields), the order of fields and layout do not need to match for the same reason as mentioned above. +### Delegate dependency locks + +The `delegator` contract depends upon the contract code to which it delegates. Since code +can be deleted by anybody if there are no instances of the contract on the chain, this +would break the `delegator` contract. To prevent this, the `delegator` contract utilizes +the `lock_delegate_dependency` and `unlock_delegate_dependency` host functions. Calling +`lock_delegate_dependency` will prevent the code at the given hash from being deleted, +until `unlock_delegate_dependency` is called from within the `delegator` contract instance. +Note that these two methods can be called by anybody executing the contract, so it is the +responsibility of the contract developer to ensure correct access control. + From 6f40bc28b36d38ae801938203c325939ee27c3aa Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 26 Feb 2024 09:05:23 +0000 Subject: [PATCH 07/19] fmt --- crates/env/src/call/create_builder.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 4141bda30db..77ea0ac6f7a 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -593,7 +593,9 @@ where { /// todo: [AJ] comment #[inline] - pub fn instantiate_v1(self) -> CreateBuilder< + pub fn instantiate_v1( + self, + ) -> CreateBuilder< E, ContractRef, CodeHash, From e6c46c967fa7b95dcc8821f414f6a933433665f8 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 26 Feb 2024 09:22:15 +0000 Subject: [PATCH 08/19] fmt --- .../cross-contract-calls/e2e_tests.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/integration-tests/cross-contract-calls/e2e_tests.rs b/integration-tests/cross-contract-calls/e2e_tests.rs index 861c1169d1f..2906ea069e1 100644 --- a/integration-tests/cross-contract-calls/e2e_tests.rs +++ b/integration-tests/cross-contract-calls/e2e_tests.rs @@ -35,7 +35,9 @@ async fn flip_and_get(mut client: Client) -> E2EResult<()> { } #[ink_e2e::test] -async fn instantiate_v2_with_limits(mut client: Client) -> E2EResult<()> { +async fn instantiate_v2_with_limits( + mut client: Client, +) -> E2EResult<()> { // given let other_contract_code = client .upload("other-contract", &ink_e2e::alice()) @@ -47,10 +49,11 @@ async fn instantiate_v2_with_limits(mut client: Client) -> E const PROOF_TIME_LIMIT: u64 = 100_000; const STORAGE_DEPOSIT_LIMIT: u128 = 1_000_000_000; - let mut constructor = CrossContractCallsRef::new_v2_with_limits(other_contract_code.code_hash, + let mut constructor = CrossContractCallsRef::new_v2_with_limits( + other_contract_code.code_hash, REF_TIME_LIMIT, PROOF_TIME_LIMIT, - STORAGE_DEPOSIT_LIMIT + STORAGE_DEPOSIT_LIMIT, ); let contract = client .instantiate("cross-contract-calls", &ink_e2e::alice(), &mut constructor) @@ -61,7 +64,9 @@ async fn instantiate_v2_with_limits(mut client: Client) -> E } #[ink_e2e::test] -async fn instantiate_v2_no_limits(mut client: Client) -> E2EResult<()> { +async fn instantiate_v2_no_limits( + mut client: Client, +) -> E2EResult<()> { // given let other_contract_code = client .upload("other-contract", &ink_e2e::alice()) @@ -69,7 +74,8 @@ async fn instantiate_v2_no_limits(mut client: Client) -> E2E .await .expect("other_contract upload failed"); - let mut constructor = CrossContractCallsRef::new_v2_no_limits(other_contract_code.code_hash); + let mut constructor = + CrossContractCallsRef::new_v2_no_limits(other_contract_code.code_hash); let contract = client .instantiate("cross-contract-calls", &ink_e2e::alice(), &mut constructor) .submit() From b9d8316468d826d77fc3ac2d91a62d8619ffefc0 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 26 Feb 2024 14:34:34 +0000 Subject: [PATCH 09/19] test for storage deposit limit exhausted --- .../cross-contract-calls/e2e_tests.rs | 53 +++++++++++++++++-- integration-tests/cross-contract-calls/lib.rs | 5 +- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/integration-tests/cross-contract-calls/e2e_tests.rs b/integration-tests/cross-contract-calls/e2e_tests.rs index 2906ea069e1..7b70dc152d9 100644 --- a/integration-tests/cross-contract-calls/e2e_tests.rs +++ b/integration-tests/cross-contract-calls/e2e_tests.rs @@ -35,7 +35,7 @@ async fn flip_and_get(mut client: Client) -> E2EResult<()> { } #[ink_e2e::test] -async fn instantiate_v2_with_limits( +async fn instantiate_v2_with_insufficient_storage_deposit_limit( mut client: Client, ) -> E2EResult<()> { // given @@ -47,7 +47,7 @@ async fn instantiate_v2_with_limits( const REF_TIME_LIMIT: u64 = 500_000_000; const PROOF_TIME_LIMIT: u64 = 100_000; - const STORAGE_DEPOSIT_LIMIT: u128 = 1_000_000_000; + const STORAGE_DEPOSIT_LIMIT: u128 = 100_000_000_000; let mut constructor = CrossContractCallsRef::new_v2_with_limits( other_contract_code.code_hash, @@ -60,7 +60,50 @@ async fn instantiate_v2_with_limits( .submit() .await; - assert!(contract.is_ok()); + let Err(ink_e2e::Error::InstantiateDryRun(err)) = contract else { + panic!("instantiate should have failed at the dry run"); + }; + + // insufficient storage deposit limit + assert!( + err.error + .to_string() + .contains("StorageDepositLimitExhausted"), + "should have failed with StorageDepositLimitExhausted" + ); + + Ok(()) +} + +#[ink_e2e::test] +async fn instantiate_v2_with_sufficient_limits( + mut client: Client, +) -> E2EResult<()> { + // given + let other_contract_code = client + .upload("other-contract", &ink_e2e::alice()) + .submit() + .await + .expect("other_contract upload failed"); + + const REF_TIME_LIMIT: u64 = 500_000_000; + const PROOF_TIME_LIMIT: u64 = 100_000; + const STORAGE_DEPOSIT_LIMIT: u128 = 500_000_000_000; + + let mut constructor = CrossContractCallsRef::new_v2_with_limits( + other_contract_code.code_hash, + REF_TIME_LIMIT, + PROOF_TIME_LIMIT, + STORAGE_DEPOSIT_LIMIT, + ); + let contract = client + .instantiate("cross-contract-calls", &ink_e2e::alice(), &mut constructor) + .submit() + .await; + + assert!(contract.is_ok(), "{}", contract.err().unwrap()); + + Ok(()) } #[ink_e2e::test] @@ -81,7 +124,9 @@ async fn instantiate_v2_no_limits( .submit() .await; - assert!(contract.is_ok()); + assert!(contract.is_ok(), "{}", contract.err().unwrap()); + + Ok(()) } #[ink_e2e::test] diff --git a/integration-tests/cross-contract-calls/lib.rs b/integration-tests/cross-contract-calls/lib.rs index 9a0bf8b1643..335617158d8 100755 --- a/integration-tests/cross-contract-calls/lib.rs +++ b/integration-tests/cross-contract-calls/lib.rs @@ -25,6 +25,9 @@ mod cross_contract_calls { .code_hash(other_contract_code_hash) .endowment(0) .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) + .ref_time_limit(ref_time_limit) + .proof_time_limit(proof_time_limit) + .storage_deposit_limit(storage_deposit_limit) .instantiate(); Self { other_contract } @@ -48,7 +51,7 @@ mod cross_contract_calls { #[ink(constructor)] pub fn new_v1(other_contract_code_hash: Hash) -> Self { let other_contract = OtherContractRef::new(true) - .v1() + .instantiate_v1() .code_hash(other_contract_code_hash) .endowment(0) .salt_bytes([0xDE, 0xAD, 0xBE, 0xEF]) From 84053ed259055e0f5ed8b28a7cc1eab884a7d0d7 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 26 Feb 2024 15:17:16 +0000 Subject: [PATCH 10/19] clippy --- integration-tests/cross-contract-calls/e2e_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/cross-contract-calls/e2e_tests.rs b/integration-tests/cross-contract-calls/e2e_tests.rs index 7b70dc152d9..ea66516d204 100644 --- a/integration-tests/cross-contract-calls/e2e_tests.rs +++ b/integration-tests/cross-contract-calls/e2e_tests.rs @@ -29,7 +29,7 @@ async fn flip_and_get(mut client: Client) -> E2EResult<()> { .expect("Calling `flip_and_get` failed") .return_value(); - assert_eq!(result, false); + assert!(!result); Ok(()) } From ebe1315cde52daf1e909e2ed6d07299b25922b48 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 26 Feb 2024 16:17:14 +0000 Subject: [PATCH 11/19] docs --- crates/ink/src/env_access.rs | 81 ++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 3 deletions(-) diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 0ce5c160bf5..a60df70dbd7 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -424,7 +424,10 @@ where ink_env::emit_event::(event) } - /// Instantiates another contract. + /// Instantiates another contract using the supplied code hash. + /// + /// Invokes the `instantiate_v2` host function which allows passing all weight and + /// storage limit parameters. /// /// # Example /// @@ -461,7 +464,9 @@ where /// pub fn instantiate_contract(&self) -> MyContractRef { /// let create_params = build_create::() /// .code_hash(Hash::from([0x42; 32])) - /// .gas_limit(4000) + /// .ref_time_limit(500_000_000) + /// .proof_time_limit(100_000) + /// .storage_deposit_limit(500_000_000_000) /// .endowment(25) /// .exec_input( /// ExecutionInput::new(Selector::new(ink::selector_bytes!("new"))) @@ -510,7 +515,77 @@ where ink_env::instantiate_contract::(params) } - /// todo: [AJ] docs + /// Instantiates another contract using the supplied code hash. + /// + /// # 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; + /// # } + /// use ink::env::{ + /// DefaultEnvironment, + /// call::{build_create, Selector, ExecutionInput} + /// }; + /// use other_contract::OtherContractRef; + /// # + /// # #[ink(storage)] + /// # pub struct MyContract { } + /// # + /// # impl MyContract { + /// # #[ink(constructor)] + /// # pub fn new() -> Self { + /// # Self {} + /// # } + /// # + /// + /// /// Instantiates another contract. + /// #[ink(message)] + /// pub fn instantiate_contract(&self) -> MyContractRef { + /// let create_params = build_create::() + /// .instantiate_v1() + /// .code_hash(Hash::from([0x42; 32])) + /// .gas_limit(500_000_000) + /// .endowment(25) + /// .exec_input( + /// ExecutionInput::new(Selector::new(ink::selector_bytes!("new"))) + /// .push_arg(42) + /// .push_arg(true) + /// .push_arg(&[0x10u8; 32]), + /// ) + /// .salt_bytes(&[0xCA, 0xFE, 0xBA, 0xBE]) + /// .returns::() + /// .params(); + /// self.env() + /// .instantiate_contract_v1(&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)) + /// } + /// # + /// # } + /// # } + /// ``` + /// + /// See [our `delegator` example](/~https://github.com/paritytech/ink/tree/master/integration-tests/integration%20tests/examples/delegator) + /// for a complete contract example. + /// + /// # Note + /// + /// For more details visit: [`ink_env::instantiate_contract_v1`] + pub fn instantiate_contract_v1( self, params: &CreateParams, From de78b3b27b49b483c175a0f79f9e5a430849d443 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 26 Feb 2024 16:29:03 +0000 Subject: [PATCH 12/19] docs --- crates/env/src/call/call_builder.rs | 2 +- crates/env/src/call/create_builder.rs | 28 ++++++++++++++++++--------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/crates/env/src/call/call_builder.rs b/crates/env/src/call/call_builder.rs index f5c31f8f58c..9429976b1bd 100644 --- a/crates/env/src/call/call_builder.rs +++ b/crates/env/src/call/call_builder.rs @@ -691,7 +691,7 @@ where /// limit parameter (equivalent to the `ref_time_limit` in the latest `call_v2`). /// /// This method instance is used to allow usage of the generated call builder methods - /// for messages which initialize the builder with the original [`CallV1`] type. + /// for messages which initialize the builder with the new [`Call`] type. pub fn call_v1(self) -> CallBuilder>, Args, RetType> { let call_type = self.call_type.value(); CallBuilder { diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs index 77ea0ac6f7a..be526028224 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -20,6 +20,7 @@ use crate::{ Set, Unset, }, + CallV1, ExecutionInput, Selector, }, @@ -165,13 +166,15 @@ where } } -/// todo: [AJ] docs +/// Defines the limit params for the legacy `ext::instantiate_v1` host function, +/// consisting of the `gas_limit` which is equivalent to the `ref_time_limit` in the new +/// `ext::instantiate`. #[derive(Clone, Debug)] pub struct LimitParamsV1 { gas_limit: u64, } -/// todo: [AJ] docs +/// Defines the limit params for the new `ext::instantiate` host function. #[derive(Clone, Debug)] pub struct LimitParamsV2 where @@ -242,19 +245,20 @@ impl where E: Environment, { - /// todo: [AJ] docs + /// Gets the `ref_time_limit` part of the weight limit for the contract instantiation. #[inline] pub fn ref_time_limit(&self) -> u64 { self.limits.ref_time_limit } - /// todo: [AJ] docs + /// Gets the `proof_time_limit` part of the weight limit for the contract + /// instantiation. #[inline] pub fn proof_time_limit(&self) -> u64 { self.limits.proof_time_limit } - /// todo: [AJ] docs + /// Gets the `storage_deposit_limit` for the contract instantiation. #[inline] pub fn storage_deposit_limit(&self) -> Option<&E::Balance> { self.limits.storage_deposit_limit.as_ref() @@ -591,7 +595,12 @@ impl where E: Environment, { - /// todo: [AJ] comment + /// Switch to the original `instantiate` host function API, which only allows the + /// `gas_limit` limit parameter (equivalent to the `ref_time_limit` in the latest + /// `instantiate_v2`). + /// + /// This method instance is used to allow usage of the generated builder methods + /// for constructors which initialize the builder with the new [`LimitParamsV2`] type. #[inline] pub fn instantiate_v1( self, @@ -618,7 +627,7 @@ where } } - /// todo: [AJ] comment + /// Sets the `ref_time_limit` part of the weight limit for the contract instantiation. #[inline] pub fn ref_time_limit(self, ref_time_limit: u64) -> Self { CreateBuilder { @@ -630,7 +639,8 @@ where } } - /// todo: [AJ] comment + /// Sets the `proof_time_limit` part of the weight limit for the contract + /// instantiation. #[inline] pub fn proof_time_limit(self, proof_time_limit: u64) -> Self { CreateBuilder { @@ -642,7 +652,7 @@ where } } - /// todo: [AJ] comment + /// Sets the `storage_deposit_limit` for the contract instantiation. #[inline] pub fn storage_deposit_limit(self, storage_deposit_limit: E::Balance) -> Self { CreateBuilder { From e4af888e381c5911d102eabc1fabcd4a7fb1a568 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 26 Feb 2024 16:30:02 +0000 Subject: [PATCH 13/19] Remove gas_limit from doc tests --- 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 be526028224..23ae65ee2f9 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -446,7 +446,6 @@ where /// # 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(ink::selector_bytes!("my_constructor"))) @@ -491,7 +490,6 @@ where /// # 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(ink::selector_bytes!("my_constructor"))) From 098e05f64113daee12410b87ff124042ab7c368c Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 26 Feb 2024 16:30:38 +0000 Subject: [PATCH 14/19] Warning --- 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 23ae65ee2f9..5e5230d4dd9 100644 --- a/crates/env/src/call/create_builder.rs +++ b/crates/env/src/call/create_builder.rs @@ -20,7 +20,6 @@ use crate::{ Set, Unset, }, - CallV1, ExecutionInput, Selector, }, From 5878eb793ea8e70a9b80cfa4597b9ac424504fc4 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 26 Feb 2024 16:34:22 +0000 Subject: [PATCH 15/19] CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37aa5ad1e69..ca98b7e1d1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [Linter] Publish the linting crates on crates.io - [#2060](/~https://github.com/paritytech/ink/pull/2060) - [E2E] Added `create_call_builder` for testing existing contracts - [#2075](/~https://github.com/paritytech/ink/pull/2075) - `call_v2` cross-contract calls with additional limit parameters - [#2077](/~https://github.com/paritytech/ink/pull/2077) +- `instantiate_v2` with additional limit parameters - [#2123](/~https://github.com/paritytech/ink/pull/2123) - `delegate_dependency` api calls - [#2076](/~https://github.com/paritytech/ink/pull/2076) ### Changed From ee88f21b14bdca353d676298b03ffd377eb24295 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 26 Feb 2024 16:44:22 +0000 Subject: [PATCH 16/19] fix example --- .../lang-err-integration-tests/call-builder/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/integration-tests/lang-err-integration-tests/call-builder/lib.rs b/integration-tests/lang-err-integration-tests/call-builder/lib.rs index c6cbf7bc48e..9aee41f00e8 100755 --- a/integration-tests/lang-err-integration-tests/call-builder/lib.rs +++ b/integration-tests/lang-err-integration-tests/call-builder/lib.rs @@ -104,7 +104,6 @@ mod call_builder { ) -> Option { let mut params = ConstructorsReturnValueRef::new(init_value) .code_hash(code_hash) - .gas_limit(0) .endowment(0) .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) .params(); @@ -146,7 +145,6 @@ mod call_builder { > { let mut params = ConstructorsReturnValueRef::try_new(init_value) .code_hash(code_hash) - .gas_limit(0) .endowment(0) .salt_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]) .params(); From 5ca8245ae66783e6b76844b03f33077bcb153b0f Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 26 Feb 2024 16:47:49 +0000 Subject: [PATCH 17/19] docs --- crates/env/src/api.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index b905333dd93..da22b62db8d 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -353,7 +353,8 @@ where /// /// # Note /// -/// This is a low level way to instantiate another smart contract. +/// This is a low level way to instantiate another smart contract, calling the latest +/// `instantiate_v2` host function. /// /// Prefer to use methods on a `ContractRef` or the /// [`CreateBuilder`](`crate::call::CreateBuilder`) @@ -390,7 +391,8 @@ where /// /// # Note /// -/// This is a low level way to instantiate another smart contract. +/// This is a low level way to instantiate another smart contract, calling the legacy +/// `instantiate_v1` host function. /// /// Prefer to use methods on a `ContractRef` or the /// [`CreateBuilder`](`crate::call::CreateBuilder`) From b2fa0c0d22b4e93a043bf8ee3465fbe65fc3997b Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 27 Feb 2024 09:32:08 +0000 Subject: [PATCH 18/19] ui test --- .../fail/constructor-return-result-non-codec-error.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 f5573446a5a..ce7891f77f5 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 @@ -33,14 +33,14 @@ error[E0277]: the trait bound `contract::Error: WrapperTypeDecode` is not satisf Arc = note: required for `contract::Error` to implement `ink::parity_scale_codec::Decode` = note: required for `Result` to implement `ConstructorReturnType` -note: required by a bound in `CreateBuilder::>>::returns` +note: required by a bound in `CreateBuilder::>>::returns` --> $WORKSPACE/crates/env/src/call/create_builder.rs | | pub fn returns( | ------- required by a bound in this associated function ... | R: ConstructorReturnType, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `CreateBuilder::>>::returns` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 6f41de9d0c48b1668e878aecc7e4d5c4309d55c8 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 27 Feb 2024 09:44:24 +0000 Subject: [PATCH 19/19] ui 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 3f20047f990..fd1ed118173 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 @@ -45,7 +45,6 @@ fn main() { 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() @@ -55,7 +54,6 @@ fn main() { 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() @@ -65,7 +63,6 @@ fn main() { 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() @@ -75,7 +72,6 @@ fn main() { 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()