From 77d81cd257fcbf538914a0e28efabb1fa09d3524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 10 Jul 2023 13:46:14 +0200 Subject: [PATCH 01/11] Extract error --- crates/e2e/src/client.rs | 151 +++++++++------------------------------ crates/e2e/src/error.rs | 31 ++++++++ crates/e2e/src/lib.rs | 27 ++----- 3 files changed, 72 insertions(+), 137 deletions(-) create mode 100644 crates/e2e/src/error.rs diff --git a/crates/e2e/src/client.rs b/crates/e2e/src/client.rs index c8bf879cee2..0ffbb654d01 100644 --- a/crates/e2e/src/client.rs +++ b/crates/e2e/src/client.rs @@ -13,29 +13,15 @@ // limitations under the License. use super::{ - builders::{ - constructor_exec_input, - CreateBuilderPartial, - }, - log_error, - log_info, - sr25519, - CodeUploadResult, - ContractExecResult, - ContractInstantiateResult, - ContractsApi, - Signer, + builders::{constructor_exec_input, CreateBuilderPartial}, + log_error, log_info, sr25519, CodeUploadResult, ContractExecResult, + ContractInstantiateResult, ContractsApi, Signer, }; use ink::codegen::ContractCallBuilder; use ink_env::{ call::{ - utils::{ - ReturnType, - Set, - }, - Call, - ExecutionInput, - FromAccountId, + utils::{ReturnType, Set}, + Call, ExecutionInput, FromAccountId, }, Environment, }; @@ -43,30 +29,26 @@ use ink_primitives::MessageResult; use pallet_contracts_primitives::ExecReturnValue; use sp_core::Pair; #[cfg(feature = "std")] -use std::{ - collections::BTreeMap, - fmt::Debug, - marker::PhantomData, - path::PathBuf, -}; +use std::{collections::BTreeMap, fmt::Debug, marker::PhantomData, path::PathBuf}; use subxt::{ blocks::ExtrinsicEvents, config::ExtrinsicParams, events::EventDetails, ext::{ - scale_decode, - scale_encode, - scale_value::{ - Composite, - Value, - ValueDef, - }, + scale_decode, scale_encode, + scale_value::{Composite, Value, ValueDef}, }, tx::PairSigner, - Config, }; +pub type Error = crate::error::Error< + ::AccountId, + ::Balance, + ::Hash, + subxt::error::DispatchError, +>; + /// Represents an initialized contract message builder. pub type CallBuilderFinal = ink_env::call::CallBuilder< E, @@ -133,7 +115,7 @@ where /// We implement a custom `Debug` here, as to avoid requiring the trait /// bound `Debug` for `E`. -impl core::fmt::Debug for InstantiationResult +impl Debug for InstantiationResult where C: subxt::Config, C::AccountId: Debug, @@ -292,69 +274,6 @@ where } } -/// An error occurred while interacting with the Substrate node. -/// -/// We only convey errors here that are caused by the contract's -/// testing logic. For anything concerning the node (like inability -/// to communicate with it, fetch the nonce, account info, etc.) we -/// panic. -pub enum Error -where - C: subxt::Config, - E: Environment, - ::Balance: core::fmt::Debug, -{ - /// No contract with the given name found in scope. - ContractNotFound(String), - /// The `instantiate_with_code` dry run failed. - InstantiateDryRun(ContractInstantiateResult), - /// The `instantiate_with_code` extrinsic failed. - InstantiateExtrinsic(subxt::error::DispatchError), - /// The `upload` dry run failed. - UploadDryRun(CodeUploadResult), - /// The `upload` extrinsic failed. - UploadExtrinsic(subxt::error::DispatchError), - /// The `call` dry run failed. - CallDryRun(ContractExecResult), - /// The `call` extrinsic failed. - CallExtrinsic(subxt::error::DispatchError), - /// Error fetching account balance. - Balance(String), - /// Decoding failed. - Decoding(subxt::Error), -} - -// We implement a custom `Debug` here, as to avoid requiring the trait -// bound `Debug` for `C`. -// TODO(#xxx) Improve the Debug implementations below to also output `_`. -impl core::fmt::Debug for Error -where - C: subxt::Config, - E: Environment, - ::Balance: core::fmt::Debug, -{ - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - match &self { - Error::ContractNotFound(name) => { - f.write_str(&format!("ContractNotFound: {name}")) - } - Error::InstantiateDryRun(res) => { - f.write_str(&format!( - "InstantiateDryRun: {}", - &String::from_utf8_lossy(&res.debug_message) - )) - } - Error::InstantiateExtrinsic(_) => f.write_str("InstantiateExtrinsic"), - Error::UploadDryRun(_) => f.write_str("UploadDryRun"), - Error::UploadExtrinsic(_) => f.write_str("UploadExtrinsic"), - Error::CallDryRun(_) => f.write_str("CallDryRun"), - Error::CallExtrinsic(_) => f.write_str("CallExtrinsic"), - Error::Balance(msg) => write!(f, "Balance: {msg}"), - Error::Decoding(err) => write!(f, "Decoding: {err}"), - } - } -} - /// A contract was successfully instantiated. #[derive( Debug, @@ -607,7 +526,7 @@ where )); log_info(&format!("instantiate dry run result: {:?}", dry_run.result)); if dry_run.result.is_err() { - return Err(Error::InstantiateDryRun(dry_run)) + return Err(Error::::InstantiateDryRun(dry_run)); } let tx_events = self @@ -648,11 +567,11 @@ where let metadata = self.api.client.metadata(); let dispatch_error = subxt::error::DispatchError::decode_from(evt.field_bytes(), metadata) - .map_err(Error::Decoding)?; + .map_err(|e| Error::::Decoding(e.to_string()))?; log_error(&format!( "extrinsic for instantiate failed: {dispatch_error}" )); - return Err(Error::InstantiateExtrinsic(dispatch_error)) + return Err(Error::::InstantiateExtrinsic(dispatch_error)); } } let account_id = account_id.expect("cannot extract `account_id` from events"); @@ -714,7 +633,7 @@ where .await; log_info(&format!("upload dry run: {dry_run:?}")); if dry_run.is_err() { - return Err(Error::UploadDryRun(dry_run)) + return Err(Error::::UploadDryRun(dry_run)); } let tx_events = self.api.upload(signer, code, storage_deposit_limit).await; @@ -735,15 +654,15 @@ where uploaded.code_hash )); hash = Some(uploaded.code_hash); - break + break; } else if is_extrinsic_failed_event(&evt) { let metadata = self.api.client.metadata(); let dispatch_error = subxt::error::DispatchError::decode_from(evt.field_bytes(), metadata) - .map_err(Error::Decoding)?; + .map_err(|e| Error::::Decoding(e.to_string()))?; log_error(&format!("extrinsic for upload failed: {dispatch_error}")); - return Err(Error::UploadExtrinsic(dispatch_error)) + return Err(Error::::UploadExtrinsic(dispatch_error)); } } @@ -791,7 +710,7 @@ where let dry_run = self.call_dry_run(signer, message, value, None).await; if dry_run.exec_result.result.is_err() { - return Err(Error::CallDryRun(dry_run.exec_result)) + return Err(Error::::CallDryRun(dry_run.exec_result)); } let tx_events = self @@ -815,9 +734,9 @@ where let metadata = self.api.client.metadata(); let dispatch_error = subxt::error::DispatchError::decode_from(evt.field_bytes(), metadata) - .map_err(Error::Decoding)?; + .map_err(|e| Error::::Decoding(e.to_string()))?; log_error(&format!("extrinsic for call failed: {dispatch_error}")); - return Err(Error::CallExtrinsic(dispatch_error)) + return Err(Error::::CallExtrinsic(dispatch_error)); } } @@ -859,10 +778,10 @@ where let metadata = self.api.client.metadata(); let dispatch_error = subxt::error::DispatchError::decode_from(evt.field_bytes(), metadata) - .map_err(Error::Decoding)?; + .map_err(|e| Error::::Decoding(e.to_string()))?; log_error(&format!("extrinsic for call failed: {dispatch_error}")); - return Err(Error::CallExtrinsic(dispatch_error)) + return Err(Error::::CallExtrinsic(dispatch_error)); } } @@ -947,13 +866,13 @@ where panic!("unable to decode account info: {err:?}"); }); - let account_data = get_composite_field_value(&account, "data")?; - let balance = get_composite_field_value(account_data, "free")?; + let account_data = get_composite_field_value::(&account, "data")?; + let balance = get_composite_field_value::(account_data, "free")?; let balance = balance.as_u128().ok_or_else(|| { - Error::Balance(format!("{balance:?} should convert to u128")) + Error::::Balance(format!("{balance:?} should convert to u128")) })?; let balance = E::Balance::try_from(balance).map_err(|_| { - Error::Balance(format!("{balance:?} failed to convert from u128")) + Error::::Balance(format!("{balance:?} failed to convert from u128")) })?; log_info(&format!( @@ -982,17 +901,17 @@ where .iter() .find(|(name, _)| name == field_name) .ok_or_else(|| { - Error::Balance(format!("No field named '{field_name}' found")) + Error::::Balance(format!("No field named '{field_name}' found")) })?; Ok(field) } else { - Err(Error::Balance( + Err(Error::::Balance( "Expected a composite type with named fields".into(), )) } } /// Returns true if the give event is System::Extrinsic failed. -fn is_extrinsic_failed_event(event: &EventDetails) -> bool { +fn is_extrinsic_failed_event(event: &EventDetails) -> bool { event.pallet_name() == "System" && event.variant_name() == "ExtrinsicFailed" } diff --git a/crates/e2e/src/error.rs b/crates/e2e/src/error.rs new file mode 100644 index 00000000000..df1f921714e --- /dev/null +++ b/crates/e2e/src/error.rs @@ -0,0 +1,31 @@ +use pallet_contracts_primitives::{ + CodeUploadResult, ContractExecResult, ContractInstantiateResult, +}; + +/// An error occurred while interacting with the Substrate node. +/// +/// We only convey errors here that are caused by the contract's +/// testing logic. For anything concerning the node (like inability +/// to communicate with it, fetch the nonce, account info, etc.) we +/// panic. +#[derive(Debug)] +pub enum Error { + /// No contract with the given name found in scope. + ContractNotFound(String), + /// The `instantiate_with_code` dry run failed. + InstantiateDryRun(ContractInstantiateResult), + /// The `instantiate_with_code` extrinsic failed. + InstantiateExtrinsic(DispatchError), + /// The `upload` dry run failed. + UploadDryRun(CodeUploadResult), + /// The `upload` extrinsic failed. + UploadExtrinsic(DispatchError), + /// The `call` dry run failed. + CallDryRun(ContractExecResult), + /// The `call` extrinsic failed. + CallExtrinsic(DispatchError), + /// Error fetching account balance. + Balance(String), + /// Decoding failed. + Decoding(String), +} diff --git a/crates/e2e/src/lib.rs b/crates/e2e/src/lib.rs index 76e5641ffd1..421c2aaf214 100644 --- a/crates/e2e/src/lib.rs +++ b/crates/e2e/src/lib.rs @@ -22,43 +22,28 @@ mod builders; mod client; mod default_accounts; +mod error; mod node_proc; mod xts; pub use client::{ - CallBuilderFinal, - CallDryRunResult, - CallResult, - Client, - Error, - InstantiationResult, + CallBuilderFinal, CallDryRunResult, CallResult, Client, Error, InstantiationResult, UploadResult, }; pub use default_accounts::*; pub use ink_e2e_macro::test; -pub use node_proc::{ - TestNodeProcess, - TestNodeProcessBuilder, -}; +pub use node_proc::{TestNodeProcess, TestNodeProcessBuilder}; pub use sp_core::H256; pub use sp_keyring::AccountKeyring; -pub use subxt::{ - self, - tx::PairSigner, -}; +pub use subxt::{self, tx::PairSigner}; pub use tokio; pub use tracing_subscriber; use pallet_contracts_primitives::{ - CodeUploadResult, - ContractExecResult, - ContractInstantiateResult, + CodeUploadResult, ContractExecResult, ContractInstantiateResult, }; use sp_core::sr25519; -use std::{ - cell::RefCell, - sync::Once, -}; +use std::{cell::RefCell, sync::Once}; use xts::ContractsApi; pub use subxt::PolkadotConfig; From d24f0ffa0e7bd90b25804df31632ea050b1ee740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 10 Jul 2023 13:48:21 +0200 Subject: [PATCH 02/11] Correct doc for error --- crates/e2e/src/error.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/e2e/src/error.rs b/crates/e2e/src/error.rs index df1f921714e..31c5a8b57df 100644 --- a/crates/e2e/src/error.rs +++ b/crates/e2e/src/error.rs @@ -2,12 +2,11 @@ use pallet_contracts_primitives::{ CodeUploadResult, ContractExecResult, ContractInstantiateResult, }; -/// An error occurred while interacting with the Substrate node. +/// An error occurred while interacting with the E2E backend. /// -/// We only convey errors here that are caused by the contract's -/// testing logic. For anything concerning the node (like inability -/// to communicate with it, fetch the nonce, account info, etc.) we -/// panic. +/// We only convey errors here that are caused by the contract's testing logic. For anything +/// concerning the execution environment (like inability to communicate with node or runtime, fetch +/// the nonce, account info, etc.) we panic. #[derive(Debug)] pub enum Error { /// No contract with the given name found in scope. From 58c6af6f267efef214e14fe2772f5d22d3ff9b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 10 Jul 2023 14:08:37 +0200 Subject: [PATCH 03/11] Start moving results: instantiation result --- crates/e2e/src/client.rs | 112 ++++++++--------------------- crates/e2e/src/contract_results.rs | 45 ++++++++++++ crates/e2e/src/lib.rs | 5 +- crates/e2e/src/xts.rs | 23 ++---- 4 files changed, 84 insertions(+), 101 deletions(-) create mode 100644 crates/e2e/src/contract_results.rs diff --git a/crates/e2e/src/client.rs b/crates/e2e/src/client.rs index 0ffbb654d01..a26aeed1e49 100644 --- a/crates/e2e/src/client.rs +++ b/crates/e2e/src/client.rs @@ -17,11 +17,11 @@ use super::{ log_error, log_info, sr25519, CodeUploadResult, ContractExecResult, ContractInstantiateResult, ContractsApi, Signer, }; -use ink::codegen::ContractCallBuilder; +use crate::contract_results::InstantiationResult; use ink_env::{ call::{ utils::{ReturnType, Set}, - Call, ExecutionInput, FromAccountId, + Call, ExecutionInput, }, Environment, }; @@ -42,8 +42,8 @@ use subxt::{ tx::PairSigner, }; -pub type Error = crate::error::Error< - ::AccountId, +pub type Error = crate::error::Error< + ::AccountId, ::Balance, ::Hash, subxt::error::DispatchError, @@ -57,33 +57,6 @@ pub type CallBuilderFinal = ink_env::call::CallBuilder< Set>, >; -/// Result of a contract instantiation. -pub struct InstantiationResult { - /// The account id at which the contract was instantiated. - pub account_id: E::AccountId, - /// The result of the dry run, contains debug messages - /// if there were any. - pub dry_run: ContractInstantiateResult, - /// Events that happened with the contract instantiation. - pub events: ExtrinsicEvents, -} - -impl InstantiationResult -where - C: subxt::Config, - E: Environment, -{ - pub fn call(&self) -> ::Type - where - Contract: ContractCallBuilder, - ::Type: FromAccountId, - { - <::Type as FromAccountId>::from_account_id( - self.account_id.clone(), - ) - } -} - /// Result of a contract upload. pub struct UploadResult { /// The hash with which the contract can be instantiated. @@ -113,25 +86,6 @@ where } } -/// We implement a custom `Debug` here, as to avoid requiring the trait -/// bound `Debug` for `E`. -impl Debug for InstantiationResult -where - C: subxt::Config, - C::AccountId: Debug, - E: Environment, - ::AccountId: Debug, - ::Balance: Debug, -{ - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - f.debug_struct("InstantiationResult") - .field("account_id", &self.account_id) - .field("dry_run", &self.dry_run) - .field("events", &self.events) - .finish() - } -} - /// Result of a contract call. pub struct CallResult { /// The result of the dry run, contains debug messages @@ -427,7 +381,7 @@ where constructor: CreateBuilderPartial, value: E::Balance, storage_deposit_limit: Option, - ) -> Result, Error> + ) -> Result>, Error> where Args: scale::Encode, { @@ -453,7 +407,7 @@ where constructor: CreateBuilderPartial, value: E::Balance, storage_deposit_limit: Option, - ) -> ContractInstantiateResult + ) -> ContractInstantiateResult where Args: scale::Encode, { @@ -501,7 +455,7 @@ where constructor: CreateBuilderPartial, value: E::Balance, storage_deposit_limit: Option, - ) -> Result, Error> + ) -> Result>, Error> where Args: scale::Encode, { @@ -526,7 +480,7 @@ where )); log_info(&format!("instantiate dry run result: {:?}", dry_run.result)); if dry_run.result.is_err() { - return Err(Error::::InstantiateDryRun(dry_run)); + return Err(Error::::InstantiateDryRun(dry_run)); } let tx_events = self @@ -567,11 +521,11 @@ where let metadata = self.api.client.metadata(); let dispatch_error = subxt::error::DispatchError::decode_from(evt.field_bytes(), metadata) - .map_err(|e| Error::::Decoding(e.to_string()))?; + .map_err(|e| Error::::Decoding(e.to_string()))?; log_error(&format!( "extrinsic for instantiate failed: {dispatch_error}" )); - return Err(Error::::InstantiateExtrinsic(dispatch_error)); + return Err(Error::::InstantiateExtrinsic(dispatch_error)); } } let account_id = account_id.expect("cannot extract `account_id` from events"); @@ -610,7 +564,7 @@ where contract_name: &str, signer: &Signer, storage_deposit_limit: Option, - ) -> Result, Error> { + ) -> Result, Error> { let code = self.load_code(contract_name); let ret = self .exec_upload(signer, code, storage_deposit_limit) @@ -625,7 +579,7 @@ where signer: &Signer, code: Vec, storage_deposit_limit: Option, - ) -> Result, Error> { + ) -> Result, Error> { // dry run the instantiate to calculate the gas limit let dry_run = self .api @@ -633,7 +587,7 @@ where .await; log_info(&format!("upload dry run: {dry_run:?}")); if dry_run.is_err() { - return Err(Error::::UploadDryRun(dry_run)); + return Err(Error::::UploadDryRun(dry_run)); } let tx_events = self.api.upload(signer, code, storage_deposit_limit).await; @@ -659,10 +613,10 @@ where let metadata = self.api.client.metadata(); let dispatch_error = subxt::error::DispatchError::decode_from(evt.field_bytes(), metadata) - .map_err(|e| Error::::Decoding(e.to_string()))?; + .map_err(|e| Error::::Decoding(e.to_string()))?; log_error(&format!("extrinsic for upload failed: {dispatch_error}")); - return Err(Error::::UploadExtrinsic(dispatch_error)); + return Err(Error::::UploadExtrinsic(dispatch_error)); } } @@ -697,7 +651,7 @@ where message: &CallBuilderFinal, value: E::Balance, storage_deposit_limit: Option, - ) -> Result, Error> + ) -> Result, Error> where Args: scale::Encode, RetType: scale::Decode, @@ -710,7 +664,7 @@ where let dry_run = self.call_dry_run(signer, message, value, None).await; if dry_run.exec_result.result.is_err() { - return Err(Error::::CallDryRun(dry_run.exec_result)); + return Err(Error::::CallDryRun(dry_run.exec_result)); } let tx_events = self @@ -734,9 +688,9 @@ where let metadata = self.api.client.metadata(); let dispatch_error = subxt::error::DispatchError::decode_from(evt.field_bytes(), metadata) - .map_err(|e| Error::::Decoding(e.to_string()))?; + .map_err(|e| Error::::Decoding(e.to_string()))?; log_error(&format!("extrinsic for call failed: {dispatch_error}")); - return Err(Error::::CallExtrinsic(dispatch_error)); + return Err(Error::::CallExtrinsic(dispatch_error)); } } @@ -763,7 +717,7 @@ where pallet_name: &'a str, call_name: &'a str, call_data: Vec, - ) -> Result, Error> { + ) -> Result, Error> { let tx_events = self .api .runtime_call(signer, pallet_name, call_name, call_data) @@ -778,10 +732,10 @@ where let metadata = self.api.client.metadata(); let dispatch_error = subxt::error::DispatchError::decode_from(evt.field_bytes(), metadata) - .map_err(|e| Error::::Decoding(e.to_string()))?; + .map_err(|e| Error::::Decoding(e.to_string()))?; log_error(&format!("extrinsic for call failed: {dispatch_error}")); - return Err(Error::::CallExtrinsic(dispatch_error)); + return Err(Error::::CallExtrinsic(dispatch_error)); } } @@ -830,10 +784,7 @@ where } /// Returns the balance of `account_id`. - pub async fn balance( - &self, - account_id: E::AccountId, - ) -> Result> + pub async fn balance(&self, account_id: E::AccountId) -> Result> where E::Balance: TryFrom, { @@ -866,13 +817,13 @@ where panic!("unable to decode account info: {err:?}"); }); - let account_data = get_composite_field_value::(&account, "data")?; - let balance = get_composite_field_value::(account_data, "free")?; + let account_data = get_composite_field_value::<_, E>(&account, "data")?; + let balance = get_composite_field_value::<_, E>(account_data, "free")?; let balance = balance.as_u128().ok_or_else(|| { - Error::::Balance(format!("{balance:?} should convert to u128")) + Error::::Balance(format!("{balance:?} should convert to u128")) })?; let balance = E::Balance::try_from(balance).map_err(|_| { - Error::::Balance(format!("{balance:?} failed to convert from u128")) + Error::::Balance(format!("{balance:?} failed to convert from u128")) })?; log_info(&format!( @@ -887,12 +838,11 @@ where /// Returns `Err` if: /// - The value is not a [`Value::Composite`] with [`Composite::Named`] fields /// - The value does not contain a field with the given name. -fn get_composite_field_value<'a, T, C, E>( +fn get_composite_field_value<'a, T, E>( value: &'a Value, field_name: &str, -) -> Result<&'a Value, Error> +) -> Result<&'a Value, Error> where - C: subxt::Config, E: Environment, E::Balance: Debug, { @@ -901,11 +851,11 @@ where .iter() .find(|(name, _)| name == field_name) .ok_or_else(|| { - Error::::Balance(format!("No field named '{field_name}' found")) + Error::::Balance(format!("No field named '{field_name}' found")) })?; Ok(field) } else { - Err(Error::::Balance( + Err(Error::::Balance( "Expected a composite type with named fields".into(), )) } diff --git a/crates/e2e/src/contract_results.rs b/crates/e2e/src/contract_results.rs new file mode 100644 index 00000000000..a89cbe98089 --- /dev/null +++ b/crates/e2e/src/contract_results.rs @@ -0,0 +1,45 @@ +use ink::codegen::ContractCallBuilder; +use ink_env::call::FromAccountId; +use ink_env::Environment; +use pallet_contracts_primitives::ContractInstantiateResult; +use std::fmt::Debug; + +/// Result of a contract instantiation. +pub struct InstantiationResult { + /// The account id at which the contract was instantiated. + pub account_id: E::AccountId, + /// The result of the dry run, contains debug messages + /// if there were any. + pub dry_run: ContractInstantiateResult, + /// Events that happened with the contract instantiation. + pub events: EventLog, +} + +impl InstantiationResult { + /// Returns the account id at which the contract was instantiated. + pub fn call(&self) -> ::Type + where + Contract: ContractCallBuilder, + Contract::Type: FromAccountId, + { + <::Type as FromAccountId>::from_account_id( + self.account_id.clone(), + ) + } +} + +/// We implement a custom `Debug` here, as to avoid requiring the trait bound `Debug` for `E`. +impl Debug for InstantiationResult +where + E::AccountId: Debug, + E::Balance: Debug, + EventLog: Debug, +{ + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + f.debug_struct("InstantiationResult") + .field("account_id", &self.account_id) + .field("dry_run", &self.dry_run) + .field("events", &self.events) + .finish() + } +} diff --git a/crates/e2e/src/lib.rs b/crates/e2e/src/lib.rs index 421c2aaf214..d33b5e6a0f6 100644 --- a/crates/e2e/src/lib.rs +++ b/crates/e2e/src/lib.rs @@ -21,15 +21,16 @@ mod builders; mod client; +mod contract_results; mod default_accounts; mod error; mod node_proc; mod xts; pub use client::{ - CallBuilderFinal, CallDryRunResult, CallResult, Client, Error, InstantiationResult, - UploadResult, + CallBuilderFinal, CallDryRunResult, CallResult, Client, Error, UploadResult, }; +pub use contract_results::InstantiationResult; pub use default_accounts::*; pub use ink_e2e_macro::test; pub use node_proc::{TestNodeProcess, TestNodeProcessBuilder}; diff --git a/crates/e2e/src/xts.rs b/crates/e2e/src/xts.rs index fc2463227db..3b7c124956c 100644 --- a/crates/e2e/src/xts.rs +++ b/crates/e2e/src/xts.rs @@ -12,28 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::{ - log_info, - sr25519, - ContractExecResult, - ContractInstantiateResult, - Signer, -}; +use super::{log_info, sr25519, ContractExecResult, ContractInstantiateResult, Signer}; use ink_env::Environment; use core::marker::PhantomData; use pallet_contracts_primitives::CodeUploadResult; -use sp_core::{ - Bytes, - H256, -}; +use sp_core::{Bytes, H256}; use subxt::{ - blocks::ExtrinsicEvents, - config::ExtrinsicParams, - ext::scale_encode, - rpc_params, - utils::MultiAddress, - OnlineClient, + blocks::ExtrinsicEvents, config::ExtrinsicParams, ext::scale_encode, rpc_params, + utils::MultiAddress, OnlineClient, }; /// Copied from `sp_weight` to additionally implement `scale_encode::EncodeAsType`. @@ -267,7 +254,7 @@ where data: Vec, salt: Vec, signer: &Signer, - ) -> ContractInstantiateResult { + ) -> ContractInstantiateResult { let code = Code::Upload(code); let call_request = RpcInstantiateRequest:: { origin: subxt::tx::Signer::account_id(signer).clone(), From 8fb5f174b16ea1f3342c5206afc366d706faaa61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 10 Jul 2023 14:12:53 +0200 Subject: [PATCH 04/11] UploadResult --- crates/e2e/src/client.rs | 39 ++++-------------------------- crates/e2e/src/contract_results.rs | 28 ++++++++++++++++++++- crates/e2e/src/lib.rs | 10 +++----- 3 files changed, 35 insertions(+), 42 deletions(-) diff --git a/crates/e2e/src/client.rs b/crates/e2e/src/client.rs index a26aeed1e49..c00f433f9ef 100644 --- a/crates/e2e/src/client.rs +++ b/crates/e2e/src/client.rs @@ -14,10 +14,10 @@ use super::{ builders::{constructor_exec_input, CreateBuilderPartial}, - log_error, log_info, sr25519, CodeUploadResult, ContractExecResult, - ContractInstantiateResult, ContractsApi, Signer, + log_error, log_info, sr25519, ContractExecResult, ContractInstantiateResult, + ContractsApi, Signer, }; -use crate::contract_results::InstantiationResult; +use crate::contract_results::{InstantiationResult, UploadResult}; use ink_env::{ call::{ utils::{ReturnType, Set}, @@ -57,35 +57,6 @@ pub type CallBuilderFinal = ink_env::call::CallBuilder< Set>, >; -/// Result of a contract upload. -pub struct UploadResult { - /// The hash with which the contract can be instantiated. - pub code_hash: E::Hash, - /// The result of the dry run, contains debug messages - /// if there were any. - pub dry_run: CodeUploadResult, - /// Events that happened with the contract instantiation. - pub events: ExtrinsicEvents, -} - -/// We implement a custom `Debug` here, to avoid requiring the trait -/// bound `Debug` for `E`. -impl Debug for UploadResult -where - C: subxt::Config, - E: Environment, - ::Balance: Debug, - ::Hash: Debug, -{ - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - f.debug_struct("UploadResult") - .field("code_hash", &self.code_hash) - .field("dry_run", &self.dry_run) - .field("events", &self.events) - .finish() - } -} - /// Result of a contract call. pub struct CallResult { /// The result of the dry run, contains debug messages @@ -564,7 +535,7 @@ where contract_name: &str, signer: &Signer, storage_deposit_limit: Option, - ) -> Result, Error> { + ) -> Result>, Error> { let code = self.load_code(contract_name); let ret = self .exec_upload(signer, code, storage_deposit_limit) @@ -579,7 +550,7 @@ where signer: &Signer, code: Vec, storage_deposit_limit: Option, - ) -> Result, Error> { + ) -> Result>, Error> { // dry run the instantiate to calculate the gas limit let dry_run = self .api diff --git a/crates/e2e/src/contract_results.rs b/crates/e2e/src/contract_results.rs index a89cbe98089..bd810e2c3d4 100644 --- a/crates/e2e/src/contract_results.rs +++ b/crates/e2e/src/contract_results.rs @@ -1,7 +1,7 @@ use ink::codegen::ContractCallBuilder; use ink_env::call::FromAccountId; use ink_env::Environment; -use pallet_contracts_primitives::ContractInstantiateResult; +use pallet_contracts_primitives::{CodeUploadResult, ContractInstantiateResult}; use std::fmt::Debug; /// Result of a contract instantiation. @@ -43,3 +43,29 @@ where .finish() } } + +/// Result of a contract upload. +pub struct UploadResult { + /// The hash with which the contract can be instantiated. + pub code_hash: E::Hash, + /// The result of the dry run, contains debug messages if there were any. + pub dry_run: CodeUploadResult, + /// Events that happened with the contract instantiation. + pub events: EventLog, +} + +/// We implement a custom `Debug` here, to avoid requiring the trait bound `Debug` for `E`. +impl Debug for UploadResult +where + E::Balance: Debug, + E::Hash: Debug, + EventLog: Debug, +{ + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + f.debug_struct("UploadResult") + .field("code_hash", &self.code_hash) + .field("dry_run", &self.dry_run) + .field("events", &self.events) + .finish() + } +} diff --git a/crates/e2e/src/lib.rs b/crates/e2e/src/lib.rs index d33b5e6a0f6..0bfe7210b26 100644 --- a/crates/e2e/src/lib.rs +++ b/crates/e2e/src/lib.rs @@ -27,10 +27,8 @@ mod error; mod node_proc; mod xts; -pub use client::{ - CallBuilderFinal, CallDryRunResult, CallResult, Client, Error, UploadResult, -}; -pub use contract_results::InstantiationResult; +pub use client::{CallBuilderFinal, CallDryRunResult, CallResult, Client, Error}; +pub use contract_results::{InstantiationResult, UploadResult}; pub use default_accounts::*; pub use ink_e2e_macro::test; pub use node_proc::{TestNodeProcess, TestNodeProcessBuilder}; @@ -40,9 +38,7 @@ pub use subxt::{self, tx::PairSigner}; pub use tokio; pub use tracing_subscriber; -use pallet_contracts_primitives::{ - CodeUploadResult, ContractExecResult, ContractInstantiateResult, -}; +use pallet_contracts_primitives::{ContractExecResult, ContractInstantiateResult}; use sp_core::sr25519; use std::{cell::RefCell, sync::Once}; use xts::ContractsApi; From ed8b9cf9d6cefe33b40300a06433b606e485d3e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 10 Jul 2023 14:25:01 +0200 Subject: [PATCH 05/11] CallResult --- crates/e2e/src/client.rs | 86 +++++------------------------- crates/e2e/src/contract_results.rs | 58 ++++++++++++++++++++ crates/e2e/src/lib.rs | 4 +- 3 files changed, 72 insertions(+), 76 deletions(-) diff --git a/crates/e2e/src/client.rs b/crates/e2e/src/client.rs index c00f433f9ef..ed19171d488 100644 --- a/crates/e2e/src/client.rs +++ b/crates/e2e/src/client.rs @@ -17,7 +17,7 @@ use super::{ log_error, log_info, sr25519, ContractExecResult, ContractInstantiateResult, ContractsApi, Signer, }; -use crate::contract_results::{InstantiationResult, UploadResult}; +use crate::contract_results::{CallResult, InstantiationResult, UploadResult}; use ink_env::{ call::{ utils::{ReturnType, Set}, @@ -57,78 +57,6 @@ pub type CallBuilderFinal = ink_env::call::CallBuilder< Set>, >; -/// Result of a contract call. -pub struct CallResult { - /// The result of the dry run, contains debug messages - /// if there were any. - pub dry_run: CallDryRunResult, - /// Events that happened with the contract instantiation. - pub events: ExtrinsicEvents, -} - -impl CallResult -where - C: subxt::Config, - E: Environment, - V: scale::Decode, -{ - /// Returns the [`MessageResult`] from the execution of the dry-run message - /// call. - /// - /// # Panics - /// - if the dry-run message call failed to execute. - /// - if message result cannot be decoded into the expected return value type. - pub fn message_result(&self) -> MessageResult { - self.dry_run.message_result() - } - - /// Returns the decoded return value of the message from the dry-run. - /// - /// Panics if the value could not be decoded. The raw bytes can be accessed - /// via [`CallResult::return_data`]. - pub fn return_value(self) -> V { - self.dry_run.return_value() - } - - /// Returns the return value as raw bytes of the message from the dry-run. - /// - /// Panics if the dry-run message call failed to execute. - pub fn return_data(&self) -> &[u8] { - &self.dry_run.exec_return_value().data - } - - /// Returns any debug message output by the contract decoded as UTF-8. - pub fn debug_message(&self) -> String { - self.dry_run.debug_message() - } - - /// Returns true if the specified event was triggered by the call. - pub fn contains_event(&self, pallet_name: &str, variant_name: &str) -> bool { - self.events.iter().any(|event| { - let event = event.unwrap(); - event.pallet_name() == pallet_name && event.variant_name() == variant_name - }) - } -} - -/// We implement a custom `Debug` here, as to avoid requiring the trait -/// bound `Debug` for `E`. -// TODO(#xxx) Improve the `Debug` implementation. -impl Debug for CallResult -where - C: subxt::Config + Debug, - E: Environment + Debug, - ::Balance: Debug, - V: Debug, -{ - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - f.debug_struct("CallResult") - .field("dry_run", &self.dry_run) - .field("events", &self.events) - .finish() - } -} - /// Result of the dry run of a contract call. #[derive(Debug)] pub struct CallDryRunResult { @@ -622,7 +550,7 @@ where message: &CallBuilderFinal, value: E::Balance, storage_deposit_limit: Option, - ) -> Result, Error> + ) -> Result>, Error> where Args: scale::Encode, RetType: scale::Decode, @@ -836,3 +764,13 @@ where fn is_extrinsic_failed_event(event: &EventDetails) -> bool { event.pallet_name() == "System" && event.variant_name() == "ExtrinsicFailed" } + +impl CallResult> { + /// Returns true if the specified event was triggered by the call. + pub fn contains_event(&self, pallet_name: &str, variant_name: &str) -> bool { + self.events.iter().any(|event| { + let event = event.unwrap(); + event.pallet_name() == pallet_name && event.variant_name() == variant_name + }) + } +} diff --git a/crates/e2e/src/contract_results.rs b/crates/e2e/src/contract_results.rs index bd810e2c3d4..836a87931dc 100644 --- a/crates/e2e/src/contract_results.rs +++ b/crates/e2e/src/contract_results.rs @@ -1,6 +1,8 @@ +use crate::CallDryRunResult; use ink::codegen::ContractCallBuilder; use ink_env::call::FromAccountId; use ink_env::Environment; +use ink_primitives::MessageResult; use pallet_contracts_primitives::{CodeUploadResult, ContractInstantiateResult}; use std::fmt::Debug; @@ -69,3 +71,59 @@ where .finish() } } + +/// Result of a contract call. +pub struct CallResult { + /// The result of the dry run, contains debug messages if there were any. + pub dry_run: CallDryRunResult, + /// Events that happened with the contract instantiation. + pub events: EventLog, +} + +impl CallResult { + /// Returns the [`MessageResult`] from the execution of the dry-run message + /// call. + /// + /// # Panics + /// - if the dry-run message call failed to execute. + /// - if message result cannot be decoded into the expected return value type. + pub fn message_result(&self) -> MessageResult { + self.dry_run.message_result() + } + + /// Returns the decoded return value of the message from the dry-run. + /// + /// Panics if the value could not be decoded. The raw bytes can be accessed + /// via [`CallResult::return_data`]. + pub fn return_value(self) -> V { + self.dry_run.return_value() + } + + /// Returns the return value as raw bytes of the message from the dry-run. + /// + /// Panics if the dry-run message call failed to execute. + pub fn return_data(&self) -> &[u8] { + &self.dry_run.exec_return_value().data + } + + /// Returns any debug message output by the contract decoded as UTF-8. + pub fn debug_message(&self) -> String { + self.dry_run.debug_message() + } +} + +// TODO(#xxx) Improve the `Debug` implementation. +impl Debug for CallResult +where + E: Debug, + E::Balance: Debug, + V: Debug, + EventLog: Debug, +{ + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + f.debug_struct("CallResult") + .field("dry_run", &self.dry_run) + .field("events", &self.events) + .finish() + } +} diff --git a/crates/e2e/src/lib.rs b/crates/e2e/src/lib.rs index 0bfe7210b26..e80ab92dc48 100644 --- a/crates/e2e/src/lib.rs +++ b/crates/e2e/src/lib.rs @@ -27,8 +27,8 @@ mod error; mod node_proc; mod xts; -pub use client::{CallBuilderFinal, CallDryRunResult, CallResult, Client, Error}; -pub use contract_results::{InstantiationResult, UploadResult}; +pub use client::{CallBuilderFinal, CallDryRunResult, Client, Error}; +pub use contract_results::{CallResult, InstantiationResult, UploadResult}; pub use default_accounts::*; pub use ink_e2e_macro::test; pub use node_proc::{TestNodeProcess, TestNodeProcessBuilder}; From 043092428a71a920ee7c16e9602104b309ae9156 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 10 Jul 2023 14:28:30 +0200 Subject: [PATCH 06/11] CallDryRunResult --- crates/e2e/src/client.rs | 81 ++---------------------------- crates/e2e/src/contract_results.rs | 70 +++++++++++++++++++++++++- crates/e2e/src/lib.rs | 6 ++- 3 files changed, 77 insertions(+), 80 deletions(-) diff --git a/crates/e2e/src/client.rs b/crates/e2e/src/client.rs index ed19171d488..25cd2968697 100644 --- a/crates/e2e/src/client.rs +++ b/crates/e2e/src/client.rs @@ -14,10 +14,11 @@ use super::{ builders::{constructor_exec_input, CreateBuilderPartial}, - log_error, log_info, sr25519, ContractExecResult, ContractInstantiateResult, - ContractsApi, Signer, + log_error, log_info, sr25519, ContractInstantiateResult, ContractsApi, Signer, +}; +use crate::contract_results::{ + CallDryRunResult, CallResult, InstantiationResult, UploadResult, }; -use crate::contract_results::{CallResult, InstantiationResult, UploadResult}; use ink_env::{ call::{ utils::{ReturnType, Set}, @@ -25,11 +26,9 @@ use ink_env::{ }, Environment, }; -use ink_primitives::MessageResult; -use pallet_contracts_primitives::ExecReturnValue; use sp_core::Pair; #[cfg(feature = "std")] -use std::{collections::BTreeMap, fmt::Debug, marker::PhantomData, path::PathBuf}; +use std::{collections::BTreeMap, fmt::Debug, path::PathBuf}; use subxt::{ blocks::ExtrinsicEvents, @@ -57,76 +56,6 @@ pub type CallBuilderFinal = ink_env::call::CallBuilder< Set>, >; -/// Result of the dry run of a contract call. -#[derive(Debug)] -pub struct CallDryRunResult { - /// The result of the dry run, contains debug messages - /// if there were any. - pub exec_result: ContractExecResult, - _marker: PhantomData, -} - -impl CallDryRunResult -where - E: Environment, - V: scale::Decode, -{ - /// Returns true if the dry-run execution resulted in an error. - pub fn is_err(&self) -> bool { - self.exec_result.result.is_err() - } - - /// Returns the [`ExecReturnValue`] resulting from the dry-run message call. - /// - /// Panics if the dry-run message call failed to execute. - pub fn exec_return_value(&self) -> &ExecReturnValue { - self.exec_result - .result - .as_ref() - .unwrap_or_else(|call_err| panic!("Call dry-run failed: {call_err:?}")) - } - - /// Returns the [`MessageResult`] from the execution of the dry-run message - /// call. - /// - /// # Panics - /// - if the dry-run message call failed to execute. - /// - if message result cannot be decoded into the expected return value type. - pub fn message_result(&self) -> MessageResult { - let data = &self.exec_return_value().data; - scale::Decode::decode(&mut data.as_ref()).unwrap_or_else(|env_err| { - panic!( - "Decoding dry run result to ink! message return type failed: {env_err}" - ) - }) - } - - /// Returns the decoded return value of the message from the dry-run. - /// - /// Panics if the value could not be decoded. The raw bytes can be accessed - /// via [`CallResult::return_data`]. - pub fn return_value(self) -> V { - self.message_result() - .unwrap_or_else(|lang_err| { - panic!( - "Encountered a `LangError` while decoding dry run result to ink! message: {lang_err:?}" - ) - }) - } - - /// Returns the return value as raw bytes of the message from the dry-run. - /// - /// Panics if the dry-run message call failed to execute. - pub fn return_data(&self) -> &[u8] { - &self.exec_return_value().data - } - - /// Returns any debug message output by the contract decoded as UTF-8. - pub fn debug_message(&self) -> String { - String::from_utf8_lossy(&self.exec_result.debug_message).into() - } -} - /// A contract was successfully instantiated. #[derive( Debug, diff --git a/crates/e2e/src/contract_results.rs b/crates/e2e/src/contract_results.rs index 836a87931dc..3ce8764b049 100644 --- a/crates/e2e/src/contract_results.rs +++ b/crates/e2e/src/contract_results.rs @@ -1,10 +1,12 @@ -use crate::CallDryRunResult; use ink::codegen::ContractCallBuilder; use ink_env::call::FromAccountId; use ink_env::Environment; use ink_primitives::MessageResult; -use pallet_contracts_primitives::{CodeUploadResult, ContractInstantiateResult}; +use pallet_contracts_primitives::{ + CodeUploadResult, ContractExecResult, ContractInstantiateResult, ExecReturnValue, +}; use std::fmt::Debug; +use std::marker::PhantomData; /// Result of a contract instantiation. pub struct InstantiationResult { @@ -127,3 +129,67 @@ where .finish() } } + +/// Result of the dry run of a contract call. +#[derive(Debug)] +pub struct CallDryRunResult { + /// The result of the dry run, contains debug messages if there were any. + pub exec_result: ContractExecResult, + pub _marker: PhantomData, +} + +impl CallDryRunResult { + /// Returns true if the dry-run execution resulted in an error. + pub fn is_err(&self) -> bool { + self.exec_result.result.is_err() + } + + /// Returns the [`ExecReturnValue`] resulting from the dry-run message call. + /// + /// Panics if the dry-run message call failed to execute. + pub fn exec_return_value(&self) -> &ExecReturnValue { + self.exec_result + .result + .as_ref() + .unwrap_or_else(|call_err| panic!("Call dry-run failed: {call_err:?}")) + } + + /// Returns the [`MessageResult`] from the execution of the dry-run message call. + /// + /// # Panics + /// - if the dry-run message call failed to execute. + /// - if message result cannot be decoded into the expected return value type. + pub fn message_result(&self) -> MessageResult { + let data = &self.exec_return_value().data; + scale::Decode::decode(&mut data.as_ref()).unwrap_or_else(|env_err| { + panic!( + "Decoding dry run result to ink! message return type failed: {env_err}" + ) + }) + } + + /// Returns the decoded return value of the message from the dry-run. + /// + /// Panics if the value could not be decoded. The raw bytes can be accessed via + /// [`CallResult::return_data`]. + pub fn return_value(self) -> V { + self.message_result() + .unwrap_or_else(|lang_err| { + panic!( + "Encountered a `LangError` while decoding dry run result to ink! message: {lang_err:?}" + ) + }) + } + + /// Returns the return value as raw bytes of the message from the dry-run. + /// + /// Panics if the dry-run message call failed to execute. + pub fn return_data(&self) -> &[u8] { + &self.exec_return_value().data + } + + /// Returns any debug message output by the contract decoded as UTF-8. + pub fn debug_message(&self) -> String { + String::from_utf8_lossy(&self.exec_result.debug_message).into() + } +} diff --git a/crates/e2e/src/lib.rs b/crates/e2e/src/lib.rs index e80ab92dc48..107f96a1c41 100644 --- a/crates/e2e/src/lib.rs +++ b/crates/e2e/src/lib.rs @@ -27,8 +27,10 @@ mod error; mod node_proc; mod xts; -pub use client::{CallBuilderFinal, CallDryRunResult, Client, Error}; -pub use contract_results::{CallResult, InstantiationResult, UploadResult}; +pub use client::{CallBuilderFinal, Client, Error}; +pub use contract_results::{ + CallDryRunResult, CallResult, InstantiationResult, UploadResult, +}; pub use default_accounts::*; pub use ink_e2e_macro::test; pub use node_proc::{TestNodeProcess, TestNodeProcessBuilder}; From 96ac3ba2f9b043c7d93246cb5280b919bbdfa78a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 10 Jul 2023 14:38:12 +0200 Subject: [PATCH 07/11] Formatting --- crates/e2e/macro/src/config.rs | 4 +- crates/e2e/src/client.rs | 56 +++++++++++++++------- crates/e2e/src/contract_results.rs | 23 ++++++--- crates/e2e/src/error.rs | 10 ++-- crates/e2e/src/lib.rs | 31 +++++++++--- crates/e2e/src/xts.rs | 21 ++++++-- crates/ink/ir/src/ir/item_mod.rs | 2 +- crates/ink/ir/src/ir/trait_def/item/mod.rs | 2 +- 8 files changed, 108 insertions(+), 41 deletions(-) diff --git a/crates/e2e/macro/src/config.rs b/crates/e2e/macro/src/config.rs index 1c4da1bdf84..f84486df0b1 100644 --- a/crates/e2e/macro/src/config.rs +++ b/crates/e2e/macro/src/config.rs @@ -55,7 +55,7 @@ impl TryFrom for E2EConfig { return Err(format_err_spanned!( arg, "expected a string literal for `additional_contracts` ink! E2E test configuration argument", - )) + )); } } else if arg.name.is_ident("environment") { if let Some((_, ast)) = environment { @@ -67,7 +67,7 @@ impl TryFrom for E2EConfig { return Err(format_err_spanned!( arg, "expected a path for `environment` ink! E2E test configuration argument", - )) + )); } } else { return Err(format_err_spanned!( diff --git a/crates/e2e/src/client.rs b/crates/e2e/src/client.rs index 25cd2968697..8c221c7f43d 100644 --- a/crates/e2e/src/client.rs +++ b/crates/e2e/src/client.rs @@ -13,30 +13,54 @@ // limitations under the License. use super::{ - builders::{constructor_exec_input, CreateBuilderPartial}, - log_error, log_info, sr25519, ContractInstantiateResult, ContractsApi, Signer, + builders::{ + constructor_exec_input, + CreateBuilderPartial, + }, + log_error, + log_info, + sr25519, + ContractInstantiateResult, + ContractsApi, + Signer, }; use crate::contract_results::{ - CallDryRunResult, CallResult, InstantiationResult, UploadResult, + CallDryRunResult, + CallResult, + InstantiationResult, + UploadResult, }; use ink_env::{ call::{ - utils::{ReturnType, Set}, - Call, ExecutionInput, + utils::{ + ReturnType, + Set, + }, + Call, + ExecutionInput, }, Environment, }; use sp_core::Pair; #[cfg(feature = "std")] -use std::{collections::BTreeMap, fmt::Debug, path::PathBuf}; +use std::{ + collections::BTreeMap, + fmt::Debug, + path::PathBuf, +}; use subxt::{ blocks::ExtrinsicEvents, config::ExtrinsicParams, events::EventDetails, ext::{ - scale_decode, scale_encode, - scale_value::{Composite, Value, ValueDef}, + scale_decode, + scale_encode, + scale_value::{ + Composite, + Value, + ValueDef, + }, }, tx::PairSigner, }; @@ -308,7 +332,7 @@ where )); log_info(&format!("instantiate dry run result: {:?}", dry_run.result)); if dry_run.result.is_err() { - return Err(Error::::InstantiateDryRun(dry_run)); + return Err(Error::::InstantiateDryRun(dry_run)) } let tx_events = self @@ -353,7 +377,7 @@ where log_error(&format!( "extrinsic for instantiate failed: {dispatch_error}" )); - return Err(Error::::InstantiateExtrinsic(dispatch_error)); + return Err(Error::::InstantiateExtrinsic(dispatch_error)) } } let account_id = account_id.expect("cannot extract `account_id` from events"); @@ -415,7 +439,7 @@ where .await; log_info(&format!("upload dry run: {dry_run:?}")); if dry_run.is_err() { - return Err(Error::::UploadDryRun(dry_run)); + return Err(Error::::UploadDryRun(dry_run)) } let tx_events = self.api.upload(signer, code, storage_deposit_limit).await; @@ -436,7 +460,7 @@ where uploaded.code_hash )); hash = Some(uploaded.code_hash); - break; + break } else if is_extrinsic_failed_event(&evt) { let metadata = self.api.client.metadata(); let dispatch_error = @@ -444,7 +468,7 @@ where .map_err(|e| Error::::Decoding(e.to_string()))?; log_error(&format!("extrinsic for upload failed: {dispatch_error}")); - return Err(Error::::UploadExtrinsic(dispatch_error)); + return Err(Error::::UploadExtrinsic(dispatch_error)) } } @@ -492,7 +516,7 @@ where let dry_run = self.call_dry_run(signer, message, value, None).await; if dry_run.exec_result.result.is_err() { - return Err(Error::::CallDryRun(dry_run.exec_result)); + return Err(Error::::CallDryRun(dry_run.exec_result)) } let tx_events = self @@ -518,7 +542,7 @@ where subxt::error::DispatchError::decode_from(evt.field_bytes(), metadata) .map_err(|e| Error::::Decoding(e.to_string()))?; log_error(&format!("extrinsic for call failed: {dispatch_error}")); - return Err(Error::::CallExtrinsic(dispatch_error)); + return Err(Error::::CallExtrinsic(dispatch_error)) } } @@ -563,7 +587,7 @@ where .map_err(|e| Error::::Decoding(e.to_string()))?; log_error(&format!("extrinsic for call failed: {dispatch_error}")); - return Err(Error::::CallExtrinsic(dispatch_error)); + return Err(Error::::CallExtrinsic(dispatch_error)) } } diff --git a/crates/e2e/src/contract_results.rs b/crates/e2e/src/contract_results.rs index 3ce8764b049..982691163f0 100644 --- a/crates/e2e/src/contract_results.rs +++ b/crates/e2e/src/contract_results.rs @@ -1,12 +1,19 @@ use ink::codegen::ContractCallBuilder; -use ink_env::call::FromAccountId; -use ink_env::Environment; +use ink_env::{ + call::FromAccountId, + Environment, +}; use ink_primitives::MessageResult; use pallet_contracts_primitives::{ - CodeUploadResult, ContractExecResult, ContractInstantiateResult, ExecReturnValue, + CodeUploadResult, + ContractExecResult, + ContractInstantiateResult, + ExecReturnValue, +}; +use std::{ + fmt::Debug, + marker::PhantomData, }; -use std::fmt::Debug; -use std::marker::PhantomData; /// Result of a contract instantiation. pub struct InstantiationResult { @@ -32,7 +39,8 @@ impl InstantiationResult { } } -/// We implement a custom `Debug` here, as to avoid requiring the trait bound `Debug` for `E`. +/// We implement a custom `Debug` here, as to avoid requiring the trait bound `Debug` for +/// `E`. impl Debug for InstantiationResult where E::AccountId: Debug, @@ -58,7 +66,8 @@ pub struct UploadResult { pub events: EventLog, } -/// We implement a custom `Debug` here, to avoid requiring the trait bound `Debug` for `E`. +/// We implement a custom `Debug` here, to avoid requiring the trait bound `Debug` for +/// `E`. impl Debug for UploadResult where E::Balance: Debug, diff --git a/crates/e2e/src/error.rs b/crates/e2e/src/error.rs index 31c5a8b57df..e3242d99a57 100644 --- a/crates/e2e/src/error.rs +++ b/crates/e2e/src/error.rs @@ -1,12 +1,14 @@ use pallet_contracts_primitives::{ - CodeUploadResult, ContractExecResult, ContractInstantiateResult, + CodeUploadResult, + ContractExecResult, + ContractInstantiateResult, }; /// An error occurred while interacting with the E2E backend. /// -/// We only convey errors here that are caused by the contract's testing logic. For anything -/// concerning the execution environment (like inability to communicate with node or runtime, fetch -/// the nonce, account info, etc.) we panic. +/// We only convey errors here that are caused by the contract's testing logic. For +/// anything concerning the execution environment (like inability to communicate with node +/// or runtime, fetch the nonce, account info, etc.) we panic. #[derive(Debug)] pub enum Error { /// No contract with the given name found in scope. diff --git a/crates/e2e/src/lib.rs b/crates/e2e/src/lib.rs index 107f96a1c41..795c3411cc4 100644 --- a/crates/e2e/src/lib.rs +++ b/crates/e2e/src/lib.rs @@ -27,22 +27,41 @@ mod error; mod node_proc; mod xts; -pub use client::{CallBuilderFinal, Client, Error}; +pub use client::{ + CallBuilderFinal, + Client, + Error, +}; pub use contract_results::{ - CallDryRunResult, CallResult, InstantiationResult, UploadResult, + CallDryRunResult, + CallResult, + InstantiationResult, + UploadResult, }; pub use default_accounts::*; pub use ink_e2e_macro::test; -pub use node_proc::{TestNodeProcess, TestNodeProcessBuilder}; +pub use node_proc::{ + TestNodeProcess, + TestNodeProcessBuilder, +}; pub use sp_core::H256; pub use sp_keyring::AccountKeyring; -pub use subxt::{self, tx::PairSigner}; +pub use subxt::{ + self, + tx::PairSigner, +}; pub use tokio; pub use tracing_subscriber; -use pallet_contracts_primitives::{ContractExecResult, ContractInstantiateResult}; +use pallet_contracts_primitives::{ + ContractExecResult, + ContractInstantiateResult, +}; use sp_core::sr25519; -use std::{cell::RefCell, sync::Once}; +use std::{ + cell::RefCell, + sync::Once, +}; use xts::ContractsApi; pub use subxt::PolkadotConfig; diff --git a/crates/e2e/src/xts.rs b/crates/e2e/src/xts.rs index 3b7c124956c..49e9245dbd2 100644 --- a/crates/e2e/src/xts.rs +++ b/crates/e2e/src/xts.rs @@ -12,15 +12,28 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::{log_info, sr25519, ContractExecResult, ContractInstantiateResult, Signer}; +use super::{ + log_info, + sr25519, + ContractExecResult, + ContractInstantiateResult, + Signer, +}; use ink_env::Environment; use core::marker::PhantomData; use pallet_contracts_primitives::CodeUploadResult; -use sp_core::{Bytes, H256}; +use sp_core::{ + Bytes, + H256, +}; use subxt::{ - blocks::ExtrinsicEvents, config::ExtrinsicParams, ext::scale_encode, rpc_params, - utils::MultiAddress, OnlineClient, + blocks::ExtrinsicEvents, + config::ExtrinsicParams, + ext::scale_encode, + rpc_params, + utils::MultiAddress, + OnlineClient, }; /// Copied from `sp_weight` to additionally implement `scale_encode::EncodeAsType`. diff --git a/crates/ink/ir/src/ir/item_mod.rs b/crates/ink/ir/src/ir/item_mod.rs index 5d70a43bb28..9e60e6d02a4 100644 --- a/crates/ink/ir/src/ir/item_mod.rs +++ b/crates/ink/ir/src/ir/item_mod.rs @@ -316,7 +316,7 @@ impl ItemMod { message.callable().span(), "encountered ink! message with wildcard complement `selector = @` but no \ wildcard `selector = _` defined" - )) + )); } } } diff --git a/crates/ink/ir/src/ir/trait_def/item/mod.rs b/crates/ink/ir/src/ir/trait_def/item/mod.rs index 69b8f95b266..6297a20acc9 100644 --- a/crates/ink/ir/src/ir/trait_def/item/mod.rs +++ b/crates/ink/ir/src/ir/trait_def/item/mod.rs @@ -384,7 +384,7 @@ impl InkItemTrait { ).into_combine(format_err_spanned!( duplicate_selector, "first ink! trait constructor or message with same selector found here", - ))) + ))); } assert!( duplicate_ident.is_none(), From 46a5e90b491c337d7becaedef1fe2c2c7bb49dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 10 Jul 2023 14:54:18 +0200 Subject: [PATCH 08/11] Annotation --- integration-tests/contract-transfer/lib.rs | 2 +- .../constructors-return-value/lib.rs | 6 ++---- .../lang-err-integration-tests/contract-ref/lib.rs | 2 +- .../lang-err-integration-tests/integration-flipper/lib.rs | 7 ++----- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/integration-tests/contract-transfer/lib.rs b/integration-tests/contract-transfer/lib.rs index 1e403697a25..65a0463d5c3 100644 --- a/integration-tests/contract-transfer/lib.rs +++ b/integration-tests/contract-transfer/lib.rs @@ -208,7 +208,7 @@ pub mod give_me { let call_res = client.call(&ink_e2e::bob(), &transfer, 10, None).await; // then - if let Err(ink_e2e::Error::CallDryRun(dry_run)) = call_res { + if let Err(ink_e2e::Error::::CallDryRun(dry_run)) = call_res { let debug_message = String::from_utf8_lossy(&dry_run.debug_message); assert!(debug_message.contains("paid an unpayable message")) } else { diff --git a/integration-tests/lang-err-integration-tests/constructors-return-value/lib.rs b/integration-tests/lang-err-integration-tests/constructors-return-value/lib.rs index 0242694b625..f644b937ab7 100644 --- a/integration-tests/lang-err-integration-tests/constructors-return-value/lib.rs +++ b/integration-tests/lang-err-integration-tests/constructors-return-value/lib.rs @@ -1,9 +1,7 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] pub use self::constructors_return_value::{ - ConstructorError, - ConstructorsReturnValue, - ConstructorsReturnValueRef, + ConstructorError, ConstructorsReturnValue, ConstructorsReturnValueRef, }; #[ink::contract] @@ -259,7 +257,7 @@ pub mod constructors_return_value { .await; assert!( - matches!(result, Err(ink_e2e::Error::InstantiateExtrinsic(_))), + matches!(result, Err(ink_e2e::Error::::InstantiateExtrinsic(_))), "Constructor should fail" ); diff --git a/integration-tests/lang-err-integration-tests/contract-ref/lib.rs b/integration-tests/lang-err-integration-tests/contract-ref/lib.rs index 55c6a4652e2..b6ca565b891 100755 --- a/integration-tests/lang-err-integration-tests/contract-ref/lib.rs +++ b/integration-tests/lang-err-integration-tests/contract-ref/lib.rs @@ -165,7 +165,7 @@ mod contract_ref { ); let contains_err_msg = match instantiate_result.unwrap_err() { - ink_e2e::Error::InstantiateDryRun(dry_run) => { + ink_e2e::Error::::InstantiateDryRun(dry_run) => { String::from_utf8_lossy(&dry_run.debug_message).contains( "Received an error from the Flipper constructor while instantiating Flipper FlipperError" ) diff --git a/integration-tests/lang-err-integration-tests/integration-flipper/lib.rs b/integration-tests/lang-err-integration-tests/integration-flipper/lib.rs index 9d05434c555..f941ab12634 100644 --- a/integration-tests/lang-err-integration-tests/integration-flipper/lib.rs +++ b/integration-tests/lang-err-integration-tests/integration-flipper/lib.rs @@ -1,9 +1,6 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -pub use self::integration_flipper::{ - Flipper, - FlipperRef, -}; +pub use self::integration_flipper::{Flipper, FlipperRef}; #[ink::contract] pub mod integration_flipper { @@ -134,7 +131,7 @@ pub mod integration_flipper { assert!(matches!( err_flip_call_result, - Err(ink_e2e::Error::CallExtrinsic(_)) + Err(ink_e2e::Error::::CallExtrinsic(_)) )); let flipped_value = client From c77b67034f856169896b3f3fb44bd6e5d752529d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 10 Jul 2023 14:57:34 +0200 Subject: [PATCH 09/11] Formatting --- .../constructors-return-value/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/integration-tests/lang-err-integration-tests/constructors-return-value/lib.rs b/integration-tests/lang-err-integration-tests/constructors-return-value/lib.rs index f644b937ab7..9f3e92b2256 100644 --- a/integration-tests/lang-err-integration-tests/constructors-return-value/lib.rs +++ b/integration-tests/lang-err-integration-tests/constructors-return-value/lib.rs @@ -1,7 +1,9 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] pub use self::constructors_return_value::{ - ConstructorError, ConstructorsReturnValue, ConstructorsReturnValueRef, + ConstructorError, + ConstructorsReturnValue, + ConstructorsReturnValueRef, }; #[ink::contract] From f29b27dd8548e335d80867cec9eb868784ab26b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 10 Jul 2023 15:00:17 +0200 Subject: [PATCH 10/11] Formatting --- .../lang-err-integration-tests/integration-flipper/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/integration-tests/lang-err-integration-tests/integration-flipper/lib.rs b/integration-tests/lang-err-integration-tests/integration-flipper/lib.rs index f941ab12634..306c044ab8e 100644 --- a/integration-tests/lang-err-integration-tests/integration-flipper/lib.rs +++ b/integration-tests/lang-err-integration-tests/integration-flipper/lib.rs @@ -1,6 +1,9 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -pub use self::integration_flipper::{Flipper, FlipperRef}; +pub use self::integration_flipper::{ + Flipper, + FlipperRef, +}; #[ink::contract] pub mod integration_flipper { From 3a5d1abce5bd0f9c466076acdf82be986aea6a88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 10 Jul 2023 15:16:18 +0200 Subject: [PATCH 11/11] No `E` --- integration-tests/contract-transfer/lib.rs | 5 ++++- .../constructors-return-value/lib.rs | 2 +- .../lang-err-integration-tests/contract-ref/lib.rs | 2 +- .../lang-err-integration-tests/integration-flipper/lib.rs | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/integration-tests/contract-transfer/lib.rs b/integration-tests/contract-transfer/lib.rs index 65a0463d5c3..2dc444bd486 100644 --- a/integration-tests/contract-transfer/lib.rs +++ b/integration-tests/contract-transfer/lib.rs @@ -208,7 +208,10 @@ pub mod give_me { let call_res = client.call(&ink_e2e::bob(), &transfer, 10, None).await; // then - if let Err(ink_e2e::Error::::CallDryRun(dry_run)) = call_res { + if let Err(ink_e2e::Error::::CallDryRun( + dry_run, + )) = call_res + { let debug_message = String::from_utf8_lossy(&dry_run.debug_message); assert!(debug_message.contains("paid an unpayable message")) } else { diff --git a/integration-tests/lang-err-integration-tests/constructors-return-value/lib.rs b/integration-tests/lang-err-integration-tests/constructors-return-value/lib.rs index 9f3e92b2256..5d7d2d62b9e 100644 --- a/integration-tests/lang-err-integration-tests/constructors-return-value/lib.rs +++ b/integration-tests/lang-err-integration-tests/constructors-return-value/lib.rs @@ -259,7 +259,7 @@ pub mod constructors_return_value { .await; assert!( - matches!(result, Err(ink_e2e::Error::::InstantiateExtrinsic(_))), + matches!(result, Err(ink_e2e::Error::::InstantiateExtrinsic(_))), "Constructor should fail" ); diff --git a/integration-tests/lang-err-integration-tests/contract-ref/lib.rs b/integration-tests/lang-err-integration-tests/contract-ref/lib.rs index b6ca565b891..6c070d7bd28 100755 --- a/integration-tests/lang-err-integration-tests/contract-ref/lib.rs +++ b/integration-tests/lang-err-integration-tests/contract-ref/lib.rs @@ -165,7 +165,7 @@ mod contract_ref { ); let contains_err_msg = match instantiate_result.unwrap_err() { - ink_e2e::Error::::InstantiateDryRun(dry_run) => { + ink_e2e::Error::::InstantiateDryRun(dry_run) => { String::from_utf8_lossy(&dry_run.debug_message).contains( "Received an error from the Flipper constructor while instantiating Flipper FlipperError" ) diff --git a/integration-tests/lang-err-integration-tests/integration-flipper/lib.rs b/integration-tests/lang-err-integration-tests/integration-flipper/lib.rs index 306c044ab8e..dceb8ea1da4 100644 --- a/integration-tests/lang-err-integration-tests/integration-flipper/lib.rs +++ b/integration-tests/lang-err-integration-tests/integration-flipper/lib.rs @@ -134,7 +134,7 @@ pub mod integration_flipper { assert!(matches!( err_flip_call_result, - Err(ink_e2e::Error::::CallExtrinsic(_)) + Err(ink_e2e::Error::::CallExtrinsic(_)) )); let flipped_value = client