diff --git a/crates/e2e/Cargo.toml b/crates/e2e/Cargo.toml index 18f42631d70..e22f34b0938 100644 --- a/crates/e2e/Cargo.toml +++ b/crates/e2e/Cargo.toml @@ -29,14 +29,14 @@ tokio = { version = "1.18.2", features = ["rt-multi-thread"] } log = { version = "0.4" } env_logger = { version = "0.10" } scale = { package = "parity-scale-codec", version = "3.4", default-features = false, features = ["derive"] } -subxt = "0.27.0" +subxt = "0.28.0" # Substrate -pallet-contracts-primitives = "18.0.0" -sp-core = "16.0.0" -sp-keyring = "18.0.0" -sp-runtime = "18.0.0" -sp-weights = "14.0.0" +pallet-contracts-primitives = "23.0.0" +sp-core = "20.0.0" +sp-keyring = "23.0.0" +sp-runtime = "23.0.0" +sp-weights = "19.0.0" [dev-dependencies] # Required for the doctest of `MessageBuilder::call` diff --git a/crates/e2e/src/client.rs b/crates/e2e/src/client.rs index 217838e1f9d..8165f7f6a7a 100644 --- a/crates/e2e/src/client.rs +++ b/crates/e2e/src/client.rs @@ -31,6 +31,7 @@ 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, @@ -42,10 +43,14 @@ use subxt::{ blocks::ExtrinsicEvents, config::ExtrinsicParams, events::EventDetails, - ext::scale_value::{ - Composite, - Value, - ValueDef, + ext::{ + scale_decode, + scale_encode, + scale_value::{ + Composite, + Value, + ValueDef, + }, }, tx::PairSigner, }; @@ -279,6 +284,8 @@ where 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 @@ -307,12 +314,21 @@ where 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, scale::Decode, scale::Encode)] +#[derive( + Debug, + scale::Decode, + scale::Encode, + scale_decode::DecodeAsType, + scale_encode::EncodeAsType, +)] +#[decode_as_type(trait_bounds = "", crate_path = "subxt::ext::scale_decode")] +#[encode_as_type(crate_path = "subxt::ext::scale_encode")] struct ContractInstantiatedEvent { /// Account id of the deployer. pub deployer: E::AccountId, @@ -329,7 +345,15 @@ where } /// Code with the specified hash has been stored. -#[derive(Debug, scale::Decode, scale::Encode)] +#[derive( + Debug, + scale::Decode, + scale::Encode, + scale_decode::DecodeAsType, + scale_encode::EncodeAsType, +)] +#[decode_as_type(trait_bounds = "", crate_path = "subxt::ext::scale_decode")] +#[encode_as_type(crate_path = "subxt::ext::scale_encode")] struct CodeStoredEvent { /// Hash under which the contract code was stored. pub code_hash: E::Hash, @@ -548,7 +572,7 @@ where .api .instantiate_with_code( value, - dry_run.gas_required, + dry_run.gas_required.into(), storage_deposit_limit, code, data.clone(), @@ -580,10 +604,9 @@ where // multiple accounts as part of its constructor! } 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, - ); + let dispatch_error = + subxt::error::DispatchError::decode_from(evt.field_bytes(), metadata) + .map_err(Error::Decoding)?; log_error(&format!( "extrinsic for instantiate failed: {dispatch_error:?}" )); @@ -672,10 +695,10 @@ where 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, - ); + let dispatch_error = + subxt::error::DispatchError::decode_from(evt.field_bytes(), metadata) + .map_err(Error::Decoding)?; + log_error(&format!("extrinsic for upload failed: {dispatch_error:?}")); return Err(Error::UploadExtrinsic(dispatch_error)) } @@ -727,9 +750,9 @@ where let tx_events = self .api .call( - sp_runtime::MultiAddress::Id(message.account_id().clone()), + subxt::utils::MultiAddress::Id(message.account_id().clone()), value, - dry_run.exec_result.gas_required, + dry_run.exec_result.gas_required.into(), storage_deposit_limit, message.exec_input().to_vec(), signer, @@ -743,10 +766,9 @@ where if is_extrinsic_failed_event(&evt) { let metadata = self.api.client.metadata(); - let dispatch_error = subxt::error::DispatchError::decode_from( - evt.field_bytes(), - &metadata, - ); + let dispatch_error = + subxt::error::DispatchError::decode_from(evt.field_bytes(), metadata) + .map_err(Error::Decoding)?; log_error(&format!("extrinsic for call failed: {dispatch_error:?}")); return Err(Error::CallExtrinsic(dispatch_error)) } @@ -788,10 +810,10 @@ where if is_extrinsic_failed_event(&evt) { let metadata = self.api.client.metadata(); - let dispatch_error = subxt::error::DispatchError::decode_from( - evt.field_bytes(), - &metadata, - ); + let dispatch_error = + subxt::error::DispatchError::decode_from(evt.field_bytes(), metadata) + .map_err(Error::Decoding)?; + log_error(&format!("extrinsic for call failed: {dispatch_error:?}")); return Err(Error::CallExtrinsic(dispatch_error)) } @@ -857,7 +879,7 @@ where .api .client .storage() - .at(None) + .at_latest() .await .unwrap_or_else(|err| { panic!("unable to fetch balance: {err:?}"); diff --git a/crates/e2e/src/xts.rs b/crates/e2e/src/xts.rs index 6e11b5e614f..ffccdb344c1 100644 --- a/crates/e2e/src/xts.rs +++ b/crates/e2e/src/xts.rs @@ -28,49 +28,101 @@ use sp_core::{ Bytes, H256, }; -use sp_weights::Weight; use subxt::{ blocks::ExtrinsicEvents, config::ExtrinsicParams, + ext::scale_encode, rpc_params, - tx, + utils::MultiAddress, OnlineClient, }; +/// Copied from `sp_weight` to additionally implement `scale_encode::EncodeAsType`. +#[derive( + Copy, + Clone, + Eq, + PartialEq, + Debug, + Default, + scale::Encode, + scale::Decode, + scale::MaxEncodedLen, + scale_encode::EncodeAsType, + serde::Serialize, + serde::Deserialize, +)] +#[encode_as_type(crate_path = "subxt::ext::scale_encode")] +pub struct Weight { + #[codec(compact)] + /// The weight of computational time used based on some reference hardware. + ref_time: u64, + #[codec(compact)] + /// The weight of storage space used by proof of validity. + proof_size: u64, +} + +impl From for Weight { + fn from(weight: sp_weights::Weight) -> Self { + Self { + ref_time: weight.ref_time(), + proof_size: weight.proof_size(), + } + } +} + +impl From for sp_weights::Weight { + fn from(weight: Weight) -> Self { + sp_weights::Weight::from_parts(weight.ref_time, weight.proof_size) + } +} + /// A raw call to `pallet-contracts`'s `instantiate_with_code`. -#[derive(Debug, scale::Encode, scale::Decode)] -pub struct InstantiateWithCode { +#[derive(Debug, scale::Encode, scale::Decode, scale_encode::EncodeAsType)] +#[encode_as_type(trait_bounds = "", crate_path = "subxt::ext::scale_encode")] +pub struct InstantiateWithCode { #[codec(compact)] - value: B, + value: E::Balance, gas_limit: Weight, - storage_deposit_limit: Option, + storage_deposit_limit: Option, code: Vec, data: Vec, salt: Vec, } /// A raw call to `pallet-contracts`'s `call`. -#[derive(Debug, scale::Encode, scale::Decode)] -pub struct Call { - dest: sp_runtime::MultiAddress, +#[derive(Debug, scale::Decode, scale::Encode, scale_encode::EncodeAsType)] +#[encode_as_type(trait_bounds = "", crate_path = "subxt::ext::scale_encode")] +pub struct Call { + dest: MultiAddress, #[codec(compact)] - value: B, + value: E::Balance, gas_limit: Weight, - storage_deposit_limit: Option, + storage_deposit_limit: Option, data: Vec, } /// A raw call to `pallet-contracts`'s `call`. -#[derive(Debug, scale::Encode, scale::Decode)] +#[derive(Debug, scale::Decode, scale::Encode, scale_encode::EncodeAsType)] +#[encode_as_type(trait_bounds = "", crate_path = "subxt::ext::scale_encode")] pub struct Transfer { - dest: C::Address, + dest: subxt::utils::Static, #[codec(compact)] value: E::Balance, } #[derive( - Debug, Clone, Copy, scale::Encode, scale::Decode, PartialEq, Eq, serde::Serialize, + Debug, + Clone, + Copy, + PartialEq, + Eq, + serde::Serialize, + scale::Decode, + scale::Encode, + scale_encode::EncodeAsType, )] +#[encode_as_type(crate_path = "subxt::ext::scale_encode")] pub enum Determinism { /// The execution should be deterministic and hence no indeterministic instructions /// are allowed. @@ -90,10 +142,11 @@ pub enum Determinism { } /// A raw call to `pallet-contracts`'s `upload`. -#[derive(Debug, scale::Encode, scale::Decode)] -pub struct UploadCode { +#[derive(Debug, scale::Encode, scale::Decode, scale_encode::EncodeAsType)] +#[encode_as_type(trait_bounds = "", crate_path = "subxt::ext::scale_encode")] +pub struct UploadCode { code: Vec, - storage_deposit_limit: Option, + storage_deposit_limit: Option, determinism: Determinism, } @@ -183,14 +236,13 @@ where dest: C::AccountId, value: E::Balance, ) -> Result<(), subxt::Error> { - let call = subxt::tx::StaticTxPayload::new( + let call = subxt::tx::Payload::new( "Balances", "transfer", Transfer:: { - dest: dest.into(), + dest: subxt::utils::Static(dest.into()), value, }, - Default::default(), ) .unvalidated(); @@ -249,7 +301,7 @@ where signer: &Signer, ) -> ExtrinsicEvents where - Call: tx::TxPayload, + Call: subxt::tx::TxPayload, { self.client .tx() @@ -292,10 +344,10 @@ where salt: Vec, signer: &Signer, ) -> ExtrinsicEvents { - let call = subxt::tx::StaticTxPayload::new( + let call = subxt::tx::Payload::new( "Contracts", "instantiate_with_code", - InstantiateWithCode:: { + InstantiateWithCode:: { value, gas_limit, storage_deposit_limit, @@ -303,7 +355,6 @@ where data, salt, }, - Default::default(), ) .unvalidated(); @@ -347,15 +398,14 @@ where code: Vec, storage_deposit_limit: Option, ) -> ExtrinsicEvents { - let call = subxt::tx::StaticTxPayload::new( + let call = subxt::tx::Payload::new( "Contracts", "upload_code", - UploadCode:: { + UploadCode:: { code, storage_deposit_limit, determinism: Determinism::Deterministic, }, - Default::default(), ) .unvalidated(); @@ -398,24 +448,23 @@ where /// contains all events that are associated with this transaction. pub async fn call( &self, - contract: sp_runtime::MultiAddress, + contract: MultiAddress, value: E::Balance, gas_limit: Weight, storage_deposit_limit: Option, data: Vec, signer: &Signer, ) -> ExtrinsicEvents { - let call = subxt::tx::StaticTxPayload::new( + let call = subxt::tx::Payload::new( "Contracts", "call", - Call:: { + Call:: { dest: contract, value, gas_limit, storage_deposit_limit, data, }, - Default::default(), ) .unvalidated(); diff --git a/crates/env/Cargo.toml b/crates/env/Cargo.toml index a55143051cc..d9c662ec2fb 100644 --- a/crates/env/Cargo.toml +++ b/crates/env/Cargo.toml @@ -47,6 +47,8 @@ secp256k1 = { version = "0.27.0", features = ["recovery", "global-context"], opt # # Sadly couldn't be marked as dev-dependency. # Never use this crate outside the off-chain environment! +scale-decode = { version = "0.5.0", default-features = false, optional = true } +scale-encode = { version = "0.1.0", default-features = false, optional = true } scale-info = { version = "2.5", default-features = false, features = ["derive"], optional = true } [dev-dependencies] @@ -61,6 +63,8 @@ std = [ "ink_storage_traits/std", "ink_engine/std", "scale/std", + "scale-decode", + "scale-encode", "scale-info/std", "secp256k1", "num-traits/std", diff --git a/crates/env/src/types.rs b/crates/env/src/types.rs index fab2503dc21..7de1f3e11ba 100644 --- a/crates/env/src/types.rs +++ b/crates/env/src/types.rs @@ -106,6 +106,16 @@ pub trait AccountIdGuard {} /// used in the [`DefaultEnvironment`]. impl AccountIdGuard for AccountId {} +cfg_if::cfg_if! { + if #[cfg(feature = "std")] { + pub trait CodecAsType: scale_decode::DecodeAsType + scale_encode::EncodeAsType {} + impl CodecAsType for T {} + } else { + pub trait CodecAsType {} + impl CodecAsType for T {} + } +} + /// The environmental types usable by contracts defined with ink!. pub trait Environment { /// The maximum number of supported event topics provided by the runtime. @@ -117,6 +127,7 @@ pub trait Environment { /// The account id type. type AccountId: 'static + scale::Codec + + CodecAsType + Clone + PartialEq + Eq @@ -127,6 +138,7 @@ pub trait Environment { /// The type of balances. type Balance: 'static + scale::Codec + + CodecAsType + Copy + Clone + PartialEq @@ -137,6 +149,7 @@ pub trait Environment { /// The type of hash. type Hash: 'static + scale::Codec + + CodecAsType + Copy + Clone + Clear @@ -149,6 +162,7 @@ pub trait Environment { /// The type of a timestamp. type Timestamp: 'static + scale::Codec + + CodecAsType + Copy + Clone + PartialEq @@ -159,6 +173,7 @@ pub trait Environment { /// The type of block number. type BlockNumber: 'static + scale::Codec + + CodecAsType + Copy + Clone + PartialEq diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index b004b5e3788..fe28b60ff64 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -18,6 +18,8 @@ include = ["/Cargo.toml", "src/**/*.rs", "/README.md", "/LICENSE"] derive_more = { version = "0.99", default-features = false, features = ["from", "display"] } ink_prelude = { version = "4.1.0", path = "../prelude/", default-features = false } scale = { package = "parity-scale-codec", version = "3.4", default-features = false, features = ["derive"] } +scale-decode = { version = "0.5.0", default-features = false, features = ["derive"], optional = true } +scale-encode = { version = "0.1.0", default-features = false, features = ["derive"], optional = true } scale-info = { version = "2.5", default-features = false, features = ["derive"], optional = true } xxhash-rust = { version = "0.8", features = ["const_xxh32"] } @@ -26,5 +28,7 @@ default = ["std"] std = [ "ink_prelude/std", "scale/std", + "scale-decode", + "scale-encode", "scale-info/std", ] diff --git a/crates/primitives/src/types.rs b/crates/primitives/src/types.rs index bd369290a80..d2b58a38ecf 100644 --- a/crates/primitives/src/types.rs +++ b/crates/primitives/src/types.rs @@ -19,7 +19,11 @@ use scale::{ Encode, }; #[cfg(feature = "std")] -use scale_info::TypeInfo; +use { + scale_decode::DecodeAsType, + scale_encode::EncodeAsType, + scale_info::TypeInfo, +}; /// The default environment `AccountId` type. /// @@ -28,9 +32,9 @@ use scale_info::TypeInfo; /// 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, + Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Decode, Encode, From, )] -#[cfg_attr(feature = "std", derive(TypeInfo))] +#[cfg_attr(feature = "std", derive(TypeInfo, DecodeAsType, EncodeAsType))] pub struct AccountId([u8; 32]); impl AsRef<[u8; 32]> for AccountId { @@ -85,12 +89,12 @@ impl<'a> TryFrom<&'a [u8]> for AccountId { Ord, PartialOrd, Hash, - Encode, Decode, + Encode, From, Default, )] -#[cfg_attr(feature = "std", derive(TypeInfo))] +#[cfg_attr(feature = "std", derive(TypeInfo, DecodeAsType, EncodeAsType))] pub struct Hash([u8; 32]); impl<'a> TryFrom<&'a [u8]> for Hash { diff --git a/integration-tests/call-runtime/Cargo.toml b/integration-tests/call-runtime/Cargo.toml index 84538775554..3406b0868fc 100644 --- a/integration-tests/call-runtime/Cargo.toml +++ b/integration-tests/call-runtime/Cargo.toml @@ -17,8 +17,8 @@ scale-info = { version = "2.5", default-features = false, features = ["derive"], # (especially for global allocator). # # See also: https://substrate.stackexchange.com/questions/4733/error-when-compiling-a-contract-using-the-xcm-chain-extension. -sp-io = { version = "18.0.0", default-features = false, features = ["disable_panic_handler", "disable_oom", "disable_allocator"] } -sp-runtime = { version = "19.0.0", default-features = false } +sp-io = { version = "22.0.0", default-features = false, features = ["disable_panic_handler", "disable_oom", "disable_allocator"] } +sp-runtime = { version = "23.0.0", default-features = false } [dev-dependencies] ink_e2e = { path = "../../crates/e2e" } diff --git a/integration-tests/e2e-call-runtime/Cargo.toml b/integration-tests/e2e-call-runtime/Cargo.toml index f77aa5bbe32..215de11c43e 100644 --- a/integration-tests/e2e-call-runtime/Cargo.toml +++ b/integration-tests/e2e-call-runtime/Cargo.toml @@ -13,7 +13,7 @@ scale-info = { version = "2.5", default-features = false, features = ["derive"], [dev-dependencies] ink_e2e = { path = "../../crates/e2e" } -subxt = { version = "0.27.1", default-features = false } +subxt = { version = "0.28.0", default-features = false } [lib] path = "lib.rs" diff --git a/integration-tests/e2e-call-runtime/lib.rs b/integration-tests/e2e-call-runtime/lib.rs index 8edd1b8d2dc..07fa4cf87a7 100644 --- a/integration-tests/e2e-call-runtime/lib.rs +++ b/integration-tests/e2e-call-runtime/lib.rs @@ -21,8 +21,10 @@ pub mod e2e_call_runtime { #[cfg(all(test, feature = "e2e-tests"))] mod e2e_tests { use super::*; - use ink_e2e::build_message; - use subxt::dynamic::Value; + use ink_e2e::{ + build_message, + subxt::dynamic::Value, + }; type E2EResult = std::result::Result>;