From 84722865d695385ce114374cc9251f5859ee0052 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 16 May 2022 18:03:05 +0200 Subject: [PATCH 01/13] Remove `Default` bound on `AccountId` type --- crates/env/src/types.rs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/crates/env/src/types.rs b/crates/env/src/types.rs index 4168d8fb8fc..0f4df001a17 100644 --- a/crates/env/src/types.rs +++ b/crates/env/src/types.rs @@ -110,8 +110,7 @@ pub trait Environment { + Eq + Ord + AsRef<[u8]> - + AsMut<[u8]> - + Default; + + AsMut<[u8]>; /// The type of balances. type Balance: 'static @@ -202,18 +201,7 @@ pub type BlockNumber = u32; /// This is a mirror of the `AccountId` type used in the default configuration /// of PALLET contracts. #[derive( - Debug, - Copy, - Clone, - PartialEq, - Eq, - Ord, - PartialOrd, - Hash, - Encode, - Decode, - From, - Default, + Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Encode, Decode, From, )] #[cfg_attr(feature = "std", derive(TypeInfo))] pub struct AccountId([u8; 32]); From c05dcf825b99962b45277ea4b2ad3fb0d2273bbd Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 16 May 2022 18:03:31 +0200 Subject: [PATCH 02/13] Manually implement storage traits for AccountID Since it doesn't implement `Default` we can't use the macro implementations anymore. --- crates/storage/src/traits/impls/prims.rs | 49 +++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/crates/storage/src/traits/impls/prims.rs b/crates/storage/src/traits/impls/prims.rs index b0507b91fdb..3447cec0856 100644 --- a/crates/storage/src/traits/impls/prims.rs +++ b/crates/storage/src/traits/impls/prims.rs @@ -54,7 +54,7 @@ impl_layout_for_primitive!( // We do not include `f32` and `f64` since Wasm contracts currently // do not support them since they are non deterministic. We might add them // to this list once we add deterministic support for those primitives. - Key, Hash, AccountId, (), + Key, Hash, (), String, bool, u8, u16, u32, u64, u128, @@ -288,6 +288,53 @@ where } } +impl SpreadLayout for AccountId +where + Self: PackedLayout, +{ + const FOOTPRINT: u64 = 1_u64; + const REQUIRES_DEEP_CLEAN_UP: bool = false; + + fn pull_spread(ptr: &mut KeyPtr) -> Self { + crate::traits::impls::forward_pull_packed::(ptr) + } + + fn push_spread(&self, ptr: &mut KeyPtr) { + crate::traits::impls::forward_push_packed::(self, ptr) + } + + fn clear_spread(&self, ptr: &mut KeyPtr) { + crate::traits::impls::forward_clear_packed::(self, ptr) + } +} + +// TODO: Not sure if this can actually be implemented, since we need some sort of "sane" default +// here +impl SpreadAllocate for AccountId +where + Self: PackedLayout, +{ + #[inline] + fn allocate_spread(ptr: &mut KeyPtr) -> Self { + ptr.advance_by(::FOOTPRINT); + [0u8; 32].into() + } +} + +impl PackedLayout for AccountId { + #[inline] + fn pull_packed(&mut self, _at: &::ink_primitives::Key) {} + #[inline] + fn push_packed(&self, _at: &::ink_primitives::Key) {} + #[inline] + fn clear_packed(&self, _at: &::ink_primitives::Key) {} +} + +impl PackedAllocate for AccountId { + #[inline] + fn allocate_packed(&mut self, _at: &::ink_primitives::Key) {} +} + #[cfg(test)] mod tests { use crate::push_pull_works_for_primitive; From e3037a2f7a2569a7ae432abd710f0aae17e8d874 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 16 May 2022 18:04:04 +0200 Subject: [PATCH 03/13] Update `Call` builder to not use default AccountId --- crates/env/src/call/call_builder.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/env/src/call/call_builder.rs b/crates/env/src/call/call_builder.rs index f9149fe5ea3..5e53a5f95dd 100644 --- a/crates/env/src/call/call_builder.rs +++ b/crates/env/src/call/call_builder.rs @@ -73,7 +73,11 @@ where /// Returns the account ID of the called contract instance. #[inline] pub(crate) fn callee(&self) -> &E::AccountId { - &self.call_type.callee + &self + .call_type + .callee + .as_ref() + .expect("TODO, probably return Option here") } /// Returns the chosen gas limit for the called contract execution. @@ -261,7 +265,7 @@ where /// The default call type for cross-contract calls. Performs a cross-contract call to `callee` /// with gas limit `gas_limit`, transferring `transferred_value` of currency. pub struct Call { - callee: E::AccountId, + callee: Option, gas_limit: Gas, transferred_value: E::Balance, } @@ -290,7 +294,7 @@ where /// Sets the `callee` for the current cross-contract call. pub fn callee(self, callee: E::AccountId) -> Self { Call { - callee, + callee: Some(callee), gas_limit: self.gas_limit, transferred_value: self.transferred_value, } @@ -448,7 +452,7 @@ where let call_type = self.call_type.value(); CallBuilder { call_type: Set(Call { - callee, + callee: Some(callee), gas_limit: call_type.gas_limit, transferred_value: call_type.transferred_value, }), From 909af82e6ecc3b4a3601060101fa10ea1923106f Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 18 May 2022 16:15:36 +0200 Subject: [PATCH 04/13] Use non-Default bound functions when reading AccountIds --- crates/env/src/engine/on_chain/impls.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index e8a98d71c6f..db15f020fbc 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -332,7 +332,8 @@ impl EnvBackend for EnvInstance { impl TypedEnvBackend for EnvInstance { fn caller(&mut self) -> E::AccountId { - self.get_property_inplace::(ext::caller) + self.get_property::(ext::caller) + .expect("The executed contract must have a caller with a valid account id.") } fn transferred_value(&mut self) -> E::Balance { @@ -348,7 +349,8 @@ impl TypedEnvBackend for EnvInstance { } fn account_id(&mut self) -> E::AccountId { - self.get_property_inplace::(ext::address) + self.get_property::(ext::address) + .expect("A contract being executed must have a valid account id.") } fn balance(&mut self) -> E::Balance { From 39574945906862ca8845929b95b8e9b639ba5409 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 18 May 2022 16:29:19 +0200 Subject: [PATCH 05/13] Remove unused `get_property_inplace` method --- crates/env/src/engine/on_chain/impls.rs | 14 -------------- crates/env/src/types.rs | 2 +- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index db15f020fbc..8bb106df2d5 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -179,20 +179,6 @@ impl EnvInstance { ScopedBuffer::from(&mut self.buffer[..]) } - /// Returns the contract property value into the given result buffer. - /// - /// # Note - /// - /// This skips the potentially costly decoding step that is often equivalent to a `memcpy`. - fn get_property_inplace(&mut self, ext_fn: fn(output: &mut &mut [u8])) -> T - where - T: Default + AsMut<[u8]>, - { - let mut result = T::default(); - ext_fn(&mut result.as_mut()); - result - } - /// Returns the contract property value from its little-endian representation. /// /// # Note diff --git a/crates/env/src/types.rs b/crates/env/src/types.rs index 0f4df001a17..124ecdb862e 100644 --- a/crates/env/src/types.rs +++ b/crates/env/src/types.rs @@ -102,7 +102,7 @@ pub trait Environment { /// The value must match the maximum number of supported event topics of the used runtime. const MAX_EVENT_TOPICS: usize; - /// The address type. + /// The account id type. type AccountId: 'static + scale::Codec + Clone From 5419bd6efae62c3a2e649add1e1420aab133b582 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 18 May 2022 19:29:00 +0200 Subject: [PATCH 06/13] Update `CallParams` to use `None` when no account ID is set --- crates/env/src/call/call_builder.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/env/src/call/call_builder.rs b/crates/env/src/call/call_builder.rs index 5e53a5f95dd..8e3f4ed4490 100644 --- a/crates/env/src/call/call_builder.rs +++ b/crates/env/src/call/call_builder.rs @@ -71,13 +71,11 @@ where E: Environment, { /// Returns the account ID of the called contract instance. + /// + /// Returns `None` if no account ID has been set for the call. #[inline] - pub(crate) fn callee(&self) -> &E::AccountId { - &self - .call_type - .callee - .as_ref() - .expect("TODO, probably return Option here") + pub(crate) fn callee(&self) -> &Option { + &self.call_type.callee } /// Returns the chosen gas limit for the called contract execution. From 823eebbe8340b4dc62b6c346155140f25149a328 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 18 May 2022 19:30:02 +0200 Subject: [PATCH 07/13] Update examples to explicitly use zero address --- examples/dns/lib.rs | 11 +++++++++-- examples/erc1155/lib.rs | 11 +++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/examples/dns/lib.rs b/examples/dns/lib.rs index 6a54f4a2213..cdcc195d9b4 100644 --- a/examples/dns/lib.rs +++ b/examples/dns/lib.rs @@ -58,7 +58,7 @@ mod dns { /// to facilitate transfers, voting and DApp-related operations instead /// of resorting to long IP addresses that are hard to remember. #[ink(storage)] - #[derive(Default, SpreadAllocate)] + #[derive(SpreadAllocate)] pub struct DomainNameService { /// A hashmap to store all name to addresses mapping. name_to_address: Mapping, @@ -88,7 +88,7 @@ mod dns { // This call is required in order to correctly initialize the // `Mapping`s of our contract. ink_lang::utils::initialize_contract(|contract: &mut Self| { - contract.default_address = Default::default(); + contract.default_address = zero_address(); }) } @@ -176,6 +176,13 @@ mod dns { } } + /// Helper for referencing the zero address (0x00). Note that in practice this address should + /// not be treated in any special way (such as a default placeholder) since it has a known + /// private key. + fn zero_address() -> AccountId { + [0u8; 32].into() + } + #[cfg(test)] mod tests { use super::*; diff --git a/examples/erc1155/lib.rs b/examples/erc1155/lib.rs index 0c9a3f432a2..77f94c099be 100644 --- a/examples/erc1155/lib.rs +++ b/examples/erc1155/lib.rs @@ -436,7 +436,7 @@ mod erc1155 { ensure!(self.is_approved_for_all(from, caller), Error::NotApproved); } - ensure!(to != AccountId::default(), Error::ZeroAddressTransfer); + ensure!(to != zero_address(), Error::ZeroAddressTransfer); let balance = self.balance_of(from, token_id); ensure!(balance >= value, Error::InsufficientBalance); @@ -461,7 +461,7 @@ mod erc1155 { ensure!(self.is_approved_for_all(from, caller), Error::NotApproved); } - ensure!(to != AccountId::default(), Error::ZeroAddressTransfer); + ensure!(to != zero_address(), Error::ZeroAddressTransfer); ensure!(!token_ids.is_empty(), Error::BatchTransferMismatch); ensure!( token_ids.len() == values.len(), @@ -585,6 +585,13 @@ mod erc1155 { } } + /// Helper for referencing the zero address (0x00). Note that in practice this address should + /// not be treated in any special way (such as a default placeholder) since it has a known + /// private key. + fn zero_address() -> AccountId { + [0u8; 32].into() + } + #[cfg(test)] mod tests { /// Imports all the definitions from the outer scope so we can use them here. From ca4c212c03db8fa6576b8526674592c23f1f34da Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 31 Jan 2023 18:29:34 -0800 Subject: [PATCH 08/13] Remove unused environment function --- crates/env/src/engine/on_chain/impls.rs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 19ca666e959..ae9fa3fdb1b 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -182,21 +182,6 @@ impl EnvInstance { ScopedBuffer::from(&mut self.buffer[..]) } - /// Returns the contract property value into the given result buffer. - /// - /// # Note - /// - /// This skips the potentially costly decoding step that is often equivalent to a `memcpy`. - #[inline(always)] - fn get_property_inplace(&mut self, ext_fn: fn(output: &mut &mut [u8])) -> T - where - T: Default + AsMut<[u8]>, - { - let mut result = T::default(); - ext_fn(&mut result.as_mut()); - result - } - /// Returns the contract property value from its little-endian representation. /// /// # Note From 2c2cc44be78742b6717ef84b32228bfd5ed8d92d Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 31 Jan 2023 18:29:50 -0800 Subject: [PATCH 09/13] Manually implement `Default` in DNS example --- examples/dns/lib.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/examples/dns/lib.rs b/examples/dns/lib.rs index 55036629340..550c86f83e6 100644 --- a/examples/dns/lib.rs +++ b/examples/dns/lib.rs @@ -53,7 +53,6 @@ mod dns { /// to facilitate transfers, voting and DApp-related operations instead /// of resorting to long IP addresses that are hard to remember. #[ink(storage)] - #[derive(Default)] pub struct DomainNameService { /// A hashmap to store all name to addresses mapping. name_to_address: Mapping, @@ -63,6 +62,21 @@ mod dns { default_address: AccountId, } + impl Default for DomainNameService { + fn default() -> Self { + let mut name_to_address = Mapping::new(); + name_to_address.insert(Hash::default(), &zero_address()); + let mut name_to_owner = Mapping::new(); + name_to_owner.insert(Hash::default(), &zero_address()); + + Self { + name_to_address, + name_to_owner, + default_address: zero_address(), + } + } + } + /// Errors that can occur upon calling this contract. #[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(::scale_info::TypeInfo))] From 71fa03fe4d500d53827c43f78e10ad1c2cb02afc Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 31 Jan 2023 18:47:25 -0800 Subject: [PATCH 10/13] Fix spellcheck --- examples/dns/lib.rs | 2 +- examples/erc1155/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/dns/lib.rs b/examples/dns/lib.rs index 550c86f83e6..a78eb8cb26b 100644 --- a/examples/dns/lib.rs +++ b/examples/dns/lib.rs @@ -179,7 +179,7 @@ mod dns { } } - /// Helper for referencing the zero address (0x00). Note that in practice this address should + /// Helper for referencing the zero address (`0x00`). Note that in practice this address should /// not be treated in any special way (such as a default placeholder) since it has a known /// private key. fn zero_address() -> AccountId { diff --git a/examples/erc1155/lib.rs b/examples/erc1155/lib.rs index 9b5eda87b24..4f703b2a922 100644 --- a/examples/erc1155/lib.rs +++ b/examples/erc1155/lib.rs @@ -581,7 +581,7 @@ mod erc1155 { } } - /// Helper for referencing the zero address (0x00). Note that in practice this address should + /// Helper for referencing the zero address (`0x00`). Note that in practice this address should /// not be treated in any special way (such as a default placeholder) since it has a known /// private key. fn zero_address() -> AccountId { From ca9d24d2e06f50b2fcbf810c9b7f8b265308a113 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 31 Jan 2023 19:57:58 -0800 Subject: [PATCH 11/13] Correctly encode the `callee` account ID when calling `pallet-contracts` --- crates/env/src/engine/on_chain/impls.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index ae9fa3fdb1b..e3a7d4a4e6c 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -412,7 +412,11 @@ impl TypedEnvBackend for EnvInstance { { let mut scope = self.scoped_buffer(); let gas_limit = params.gas_limit(); - let enc_callee = scope.take_encoded(params.callee()); + let callee = params + .callee() + .as_ref() + .expect("An account ID must be set in order to call a contract."); + let enc_callee = scope.take_encoded(callee); let enc_transferred_value = scope.take_encoded(params.transferred_value()); let call_flags = params.call_flags(); let enc_input = if !call_flags.forward_input() && !call_flags.clone_input() { From b7feae2dcbbfab49a01aec4206e48b4a0821fb02 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 31 Jan 2023 20:26:26 -0800 Subject: [PATCH 12/13] Update `CHANGELOG` --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e54bc9fd5f..64955cbe3e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - Rename `_checked` codegen call methods with `try_` ‒ [#1621](https://github.com/paritytech/ink/pull/1621) +- Remove `Default` implementation for AccountId ‒ [#1255](https://github.com/paritytech/ink/pull/1255) ### Breaking Changes 1. We've renamed some of the generated message methods on the `ContractRef` struct. They have been changed from `_checked` to `try_` ([#1621](https://github.com/paritytech/ink/pull/1621)) +1. We have removed the `Default` implementation for `AccountId`s. This is because of + security concerns around the use of the zero address which has a known private key in + the `sr25519` and `ed25519` curves ([#1255](https://github.com/paritytech/ink/pull/1255)). ## Version 4.0.0-beta.1 The coolest feature included in this release is the first first published version of From c86692f25b4f8ec7699778f537f314c74a76a46c Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 1 Feb 2023 18:33:48 +0000 Subject: [PATCH 13/13] Make cross-contract callee non-optional (#1636) * Make cross-contract callee non-optional * clippy * Fmt * Fix * clippy * clippy * clippy * Add a similar method for `code_hash` * Fix doc tests * RustFmt * Rename top level methods to `call` and `delegate` * Fix some renames --------- Co-authored-by: Hernando Castano --- crates/env/src/call/call_builder.rs | 104 ++++++++---------- crates/env/src/engine/on_chain/impls.rs | 6 +- .../generator/as_dependency/call_builder.rs | 2 +- .../src/generator/trait_def/call_builder.rs | 2 +- crates/ink/src/env_access.rs | 6 +- examples/erc1155/lib.rs | 4 +- .../call-builder/lib.rs | 5 +- examples/multisig/lib.rs | 20 +--- .../forward-calls/lib.rs | 10 +- 9 files changed, 62 insertions(+), 97 deletions(-) diff --git a/crates/env/src/call/call_builder.rs b/crates/env/src/call/call_builder.rs index 95c851c6f76..3ea6c065c97 100644 --- a/crates/env/src/call/call_builder.rs +++ b/crates/env/src/call/call_builder.rs @@ -28,7 +28,6 @@ use crate::{ Error, }; use core::marker::PhantomData; -use ink_primitives::Clear; use num_traits::Zero; /// The final parameters to the cross-contract call. @@ -71,10 +70,8 @@ where E: Environment, { /// Returns the account ID of the called contract instance. - /// - /// Returns `None` if no account ID has been set for the call. #[inline] - pub fn callee(&self) -> &Option { + pub fn callee(&self) -> &E::AccountId { &self.call_type.callee } @@ -205,11 +202,9 @@ where /// # type AccountId = ::AccountId; /// # type Balance = ::Balance; /// build_call::() -/// .call_type( -/// Call::new() -/// .callee(AccountId::from([0x42; 32])) -/// .gas_limit(5000) -/// .transferred_value(10)) +/// .call(AccountId::from([0x42; 32])) +/// .gas_limit(5000) +/// .transferred_value(10) /// .exec_input( /// ExecutionInput::new(Selector::new([0xDE, 0xAD, 0xBE, 0xEF])) /// .push_arg(42u8) @@ -241,9 +236,8 @@ where /// # }; /// # type AccountId = ::AccountId; /// let my_return_value: i32 = build_call::() -/// .call_type(Call::new() -/// .callee(AccountId::from([0x42; 32])) -/// .gas_limit(5000)) +/// .call_type(Call::new(AccountId::from([0x42; 32]))) +/// .gas_limit(5000) /// .transferred_value(10) /// .exec_input( /// ExecutionInput::new(Selector::new([0xDE, 0xAD, 0xBE, 0xEF])) @@ -270,8 +264,7 @@ where /// # use ink_primitives::Clear; /// # type AccountId = ::AccountId; /// let my_return_value: i32 = build_call::() -/// .call_type(DelegateCall::new() -/// .code_hash(::Hash::CLEAR_HASH)) +/// .delegate(::Hash::CLEAR_HASH) /// .exec_input( /// ExecutionInput::new(Selector::new([0xDE, 0xAD, 0xBE, 0xEF])) /// .push_arg(42u8) @@ -306,12 +299,9 @@ where /// # type AccountId = ::AccountId; /// # type Balance = ::Balance; /// let call_result = build_call::() -/// .call_type( -/// Call::new() -/// .callee(AccountId::from([0x42; 32])) -/// .gas_limit(5000) -/// .transferred_value(10), -/// ) +/// .call(AccountId::from([0x42; 32])) +/// .gas_limit(5000) +/// .transferred_value(10) /// .try_invoke() /// .expect("Got an error from the Contract's pallet."); /// @@ -343,41 +333,26 @@ where /// The default call type for cross-contract calls. Performs a cross-contract call to `callee` /// with gas limit `gas_limit`, transferring `transferred_value` of currency. pub struct Call { - callee: Option, + callee: E::AccountId, gas_limit: Gas, transferred_value: E::Balance, } -impl Default for Call { - fn default() -> Self { - Call { - callee: Default::default(), +impl Call { + /// Returns a clean builder for [`Call`]. + pub fn new(callee: E::AccountId) -> Self { + Self { + callee, gas_limit: Default::default(), transferred_value: E::Balance::zero(), } } } -impl Call { - /// Returns a clean builder for [`Call`]. - pub fn new() -> Self { - Default::default() - } -} - impl Call where E: Environment, { - /// Sets the `callee` for the current cross-contract call. - pub fn callee(self, callee: E::AccountId) -> Self { - Call { - callee: Some(callee), - gas_limit: self.gas_limit, - transferred_value: self.transferred_value, - } - } - /// Sets the `gas_limit` for the current cross-contract call. pub fn gas_limit(self, gas_limit: Gas) -> Self { Call { @@ -404,16 +379,8 @@ pub struct DelegateCall { impl DelegateCall { /// Returns a clean builder for [`DelegateCall`] - pub const fn new() -> Self { - DelegateCall { - code_hash: E::Hash::CLEAR_HASH, - } - } -} - -impl Default for DelegateCall { - fn default() -> Self { - Self::new() + pub const fn new(code_hash: E::Hash) -> Self { + DelegateCall { code_hash } } } @@ -521,26 +488,43 @@ where } } -impl CallBuilder>, Args, RetType> +impl CallBuilder, Args, RetType> where E: Environment, { - /// Sets the `callee` for the current cross-contract call. - pub fn callee(self, callee: E::AccountId) -> Self { - let call_type = self.call_type.value(); + /// Prepares the `CallBuilder` for a cross-contract [`Call`]. + pub fn call( + self, + callee: E::AccountId, + ) -> CallBuilder>, Args, RetType> { CallBuilder { - call_type: Set(Call { - callee: Some(callee), - gas_limit: call_type.gas_limit, - transferred_value: call_type.transferred_value, - }), + call_type: Set(Call::new(callee)), + call_flags: self.call_flags, + exec_input: self.exec_input, + return_type: self.return_type, + _phantom: Default::default(), + } + } + + /// Prepares the `CallBuilder` for a cross-contract [`DelegateCall`]. + pub fn delegate( + self, + code_hash: E::Hash, + ) -> CallBuilder>, Args, RetType> { + CallBuilder { + call_type: Set(DelegateCall::new(code_hash)), call_flags: self.call_flags, exec_input: self.exec_input, return_type: self.return_type, _phantom: Default::default(), } } +} +impl CallBuilder>, Args, RetType> +where + E: Environment, +{ /// Sets the `gas_limit` for the current cross-contract call. pub fn gas_limit(self, gas_limit: Gas) -> Self { let call_type = self.call_type.value(); diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index e3a7d4a4e6c..ae9fa3fdb1b 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -412,11 +412,7 @@ impl TypedEnvBackend for EnvInstance { { let mut scope = self.scoped_buffer(); let gas_limit = params.gas_limit(); - let callee = params - .callee() - .as_ref() - .expect("An account ID must be set in order to call a contract."); - let enc_callee = scope.take_encoded(callee); + let enc_callee = scope.take_encoded(params.callee()); let enc_transferred_value = scope.take_encoded(params.transferred_value()); let call_flags = params.call_flags(); let enc_input = if !call_flags.forward_input() && !call_flags.clone_input() { 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 06ce61e4425..fe5f09feafe 100644 --- a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs @@ -391,7 +391,7 @@ impl CallBuilder<'_> { #( , #input_bindings : #input_types )* ) -> #output_type { ::ink::env::call::build_call::() - .call_type(::ink::env::call::Call::new().callee(::ink::ToAccountId::to_account_id(self))) + .call(::ink::ToAccountId::to_account_id(self)) .exec_input( ::ink::env::call::ExecutionInput::new( ::ink::env::call::Selector::new([ #( #selector_bytes ),* ]) 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 34221367b36..69db77bb431 100644 --- a/crates/ink/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/ink/codegen/src/generator/trait_def/call_builder.rs @@ -319,7 +319,7 @@ impl CallBuilder<'_> { #( , #input_bindings : #input_types )* ) -> Self::#output_ident { ::ink::env::call::build_call::() - .call_type(::ink::env::call::Call::new().callee(::ink::ToAccountId::to_account_id(self))) + .call(::ink::ToAccountId::to_account_id(self)) .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 89cbcf82556..f54660cd42a 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -524,8 +524,7 @@ where /// pub fn invoke_contract(&self) -> i32 { /// let call_params = build_call::() /// .call_type( - /// Call::new() - /// .callee(AccountId::from([0x42; 32])) + /// Call::new(AccountId::from([0x42; 32])) /// .gas_limit(5000) /// .transferred_value(10)) /// .exec_input( @@ -588,8 +587,7 @@ where /// pub fn invoke_contract_delegate(&self) -> i32 { /// let call_params = build_call::() /// .call_type( - /// DelegateCall::new() - /// .code_hash(::Hash::CLEAR_HASH)) + /// DelegateCall::new(::Hash::CLEAR_HASH)) /// .exec_input( /// ExecutionInput::new(Selector::new([0xCA, 0xFE, 0xBA, 0xBE])) /// .push_arg(42u8) diff --git a/examples/erc1155/lib.rs b/examples/erc1155/lib.rs index 4f703b2a922..ed49e73bcc6 100644 --- a/examples/erc1155/lib.rs +++ b/examples/erc1155/lib.rs @@ -358,7 +358,6 @@ mod erc1155 { { use ink::env::call::{ build_call, - Call, ExecutionInput, Selector, }; @@ -366,7 +365,8 @@ mod erc1155 { // If our recipient is a smart contract we need to see if they accept or // reject this transfer. If they reject it we need to revert the call. let result = build_call::() - .call_type(Call::new().callee(to).gas_limit(5000)) + .call(to) + .gas_limit(5000) .exec_input( ExecutionInput::new(Selector::new(ON_ERC_1155_RECEIVED_SELECTOR)) .push_arg(caller) diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 1d143fadece..092ad1d0358 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -21,7 +21,6 @@ mod call_builder { use ink::env::{ call::{ build_call, - Call, ExecutionInput, Selector, }, @@ -52,7 +51,7 @@ mod call_builder { selector: [u8; 4], ) -> Option { let result = build_call::() - .call_type(Call::new().callee(address)) + .call(address) .exec_input(ExecutionInput::new(Selector::new(selector))) .returns::<()>() .try_invoke() @@ -79,7 +78,7 @@ mod call_builder { use ink::env::call::build_call; build_call::() - .call_type(Call::new().callee(address)) + .call(address) .exec_input(ExecutionInput::new(Selector::new(selector))) .returns::<()>() .invoke() diff --git a/examples/multisig/lib.rs b/examples/multisig/lib.rs index 250db845d3c..b5452c7b1c6 100755 --- a/examples/multisig/lib.rs +++ b/examples/multisig/lib.rs @@ -67,7 +67,6 @@ mod multisig { env::{ call::{ build_call, - Call, ExecutionInput, }, CallFlags, @@ -310,7 +309,6 @@ mod multisig { /// use ink::env::{ /// call::{ /// utils::ArgumentList, - /// Call, /// CallParams, /// ExecutionInput, /// Selector, @@ -536,12 +534,9 @@ mod multisig { let t = self.take_transaction(trans_id).expect(WRONG_TRANSACTION_ID); assert!(self.env().transferred_value() == t.transferred_value); let result = build_call::<::Env>() - .call_type( - Call::new() - .callee(t.callee) - .gas_limit(t.gas_limit) - .transferred_value(t.transferred_value), - ) + .call(t.callee) + .gas_limit(t.gas_limit) + .transferred_value(t.transferred_value) .call_flags(CallFlags::default().set_allow_reentry(t.allow_reentry)) .exec_input( ExecutionInput::new(t.selector.into()).push_arg(CallInput(&t.input)), @@ -574,12 +569,9 @@ mod multisig { self.ensure_confirmed(trans_id); let t = self.take_transaction(trans_id).expect(WRONG_TRANSACTION_ID); let result = build_call::<::Env>() - .call_type( - Call::new() - .callee(t.callee) - .gas_limit(t.gas_limit) - .transferred_value(t.transferred_value), - ) + .call(t.callee) + .gas_limit(t.gas_limit) + .transferred_value(t.transferred_value) .call_flags(CallFlags::default().set_allow_reentry(t.allow_reentry)) .exec_input( ExecutionInput::new(t.selector.into()).push_arg(CallInput(&t.input)), diff --git a/examples/upgradeable-contracts/forward-calls/lib.rs b/examples/upgradeable-contracts/forward-calls/lib.rs index 51c4144cc06..d65c5111680 100644 --- a/examples/upgradeable-contracts/forward-calls/lib.rs +++ b/examples/upgradeable-contracts/forward-calls/lib.rs @@ -17,7 +17,6 @@ #[ink::contract] pub mod proxy { - use ink::env::call::Call; /// A simple proxy contract. #[ink(storage)] @@ -70,12 +69,9 @@ pub mod proxy { #[ink(message, payable, selector = _)] pub fn forward(&self) -> u32 { ink::env::call::build_call::() - .call_type( - Call::new() - .callee(self.forward_to) - .transferred_value(self.env().transferred_value()) - .gas_limit(0), - ) + .call(self.forward_to) + .transferred_value(self.env().transferred_value()) + .gas_limit(0) .call_flags( ink::env::CallFlags::default() .set_forward_input(true)