From 4fd2981d6fd0ef70d85e2e13f1c8a94a949d0fcc Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Tue, 20 Aug 2024 12:50:00 +0200 Subject: [PATCH 1/3] Kusama: Make the current inflation formula adjustable. (#364) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR does not alter the inflation of Kusama, but instead make the current parameters of the system fully configurable. ## Parameters The parameters are as follows: ```rust /// Minimum inflation rate used to calculate era payouts. pub static MinInflation: Perquintill = Perquintill::from_rational(25u64, 1000); /// Maximum inflation rate used to calculate era payouts. pub static MaxInflation: Perquintill = Perquintill::from_percent(10); /// Ideal stake ratio used to calculate era payouts. pub static IdealStake: Perquintill = Perquintill::from_percent(75); /// Falloff used to calculate era payouts. pub static Falloff: Perquintill = Perquintill::from_percent(5); /// Whether to use auction slots or not in the calculation of era payouts, then we subtract /// `num_auctioned_slots.min(60) / 200` from `ideal_stake`. /// /// That is, we assume up to 60 parachains that are leased can reduce the ideal stake by a /// maximum of 30%. /// /// With the move to agile-coretime, this parameter does not make much sense and should /// generally be set to false. pub static UseAuctionSlots: bool = true; ``` All of the above are exactly the current values in Kusama, and leave everything unchanged, leading to roughly `1kKSM` minted for validators, and around `90KSM` for treasury. All of the above can be changed via the `Root` track only. Given that it is hard to come to consensus, I highly advise this PR (and a similar PR to Polkadot) to NOT alter any parameter and leave that to the token holders. Just to provide one example, if we set `UseAuctionSlots = false` and leave everything else un-changed, the amount minted per era would be: * `807KSM` for staking * `238KSM` for treasury > This, in my opinion, is the most non-controversial change as the incorporation of auctions in the inflation rate is already meaningless with agile-coretime. ## Consideration for UIs This PR is shipped with a new runtime API that is only added to the Kusama runtime: `Inflation_experimental_inflation_info`. I hope this API is used by the UIs to show the inflation parameters of the network, rather than re-creating the Rust logic in the front-end. --------- Signed-off-by: Oliver Tale-Yazdi Co-authored-by: Oliver Tale-Yazdi Co-authored-by: s0me0ne-unkn0wn <48632512+s0me0ne-unkn0wn@users.noreply.github.com> Co-authored-by: clangenb <37865735+clangenb@users.noreply.github.com> Co-authored-by: Dónal Murray Co-authored-by: Gonçalo Pestana Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> Co-authored-by: Dónal Murray Co-authored-by: fellowship-merge-bot[bot] <151052383+fellowship-merge-bot[bot]@users.noreply.github.com> --- CHANGELOG.md | 2 + Cargo.lock | 38 ++- Cargo.toml | 4 + relay/common/Cargo.toml | 30 +++ relay/common/src/lib.rs | 115 +++++++++ relay/kusama/Cargo.toml | 7 + relay/kusama/src/lib.rs | 237 ++++++++++++++++-- relay/kusama/src/weights/mod.rs | 1 + relay/kusama/src/weights/pallet_parameters.rs | 51 ++++ 9 files changed, 467 insertions(+), 18 deletions(-) create mode 100644 relay/common/Cargo.toml create mode 100644 relay/common/src/lib.rs create mode 100644 relay/kusama/src/weights/pallet_parameters.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f215d3efa..6d351bea8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,8 +20,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Add the Polkadot Coretime Chain runtime ([polkadot-fellows/runtimes#410](https://github.com/polkadot-fellows/runtimes/pull/410)) - Kusama: Add a "Spokesperson" proxy type only allowed to send remarks ([polkadot-fellows/runtimes#430](https://github.com/polkadot-fellows/runtimes/pull/430)) - Add the Polkadot and Kusama Coretime Chain specs ([polkadot-fellows/runtimes#432](https://github.com/polkadot-fellows/runtimes/pull/432)) +- Kusama: Make the current inflation formula adjustable ([polkadot-fellows/runtimes#364](https://github.com/polkadot-fellows/runtimes/pull/364)) - Port Agile Coretime migration from polkadot-sdk in order to fix leases with gaps handling([polkadot-fellows/runtimes#426](https://github.com/polkadot-fellows/runtimes/pull/426)) + #### From [#322](https://github.com/polkadot-fellows/runtimes/pull/322): - Add `claim_assets` extrinsic to `pallet-xcm` ([SDK v1.9 #3403](https://github.com/paritytech/polkadot-sdk/pull/3403)). diff --git a/Cargo.lock b/Cargo.lock index e18345ee89..207caffac2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8703,6 +8703,25 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-parameters" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58d9a81a93202105a660e6aa3d3f81638bdd109ca0497f3e528529cd52d034db" +dependencies = [ + "docify", + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "paste", + "scale-info", + "serde", + "sp-core 34.0.0", + "sp-runtime 38.0.0", + "sp-std", +] + [[package]] name = "pallet-preimage" version = "36.0.0" @@ -11078,6 +11097,18 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "relay-common" +version = "1.0.0" +dependencies = [ + "pallet-staking-reward-fn", + "parity-scale-codec", + "polkadot-primitives", + "scale-info", + "sp-api", + "sp-runtime 38.0.0", +] + [[package]] name = "reqwest" version = "0.11.27" @@ -14239,9 +14270,9 @@ dependencies = [ [[package]] name = "ss58-registry" -version = "1.44.0" +version = "1.47.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35935738370302d5e33963665b77541e4b990a3e919ec904c837a56cfc891de1" +checksum = "4743ce898933fbff7bbf414f497c459a782d496269644b3d650a398ae6a487ba" dependencies = [ "Inflector", "num-format", @@ -14325,6 +14356,7 @@ dependencies = [ "pallet-nomination-pools-runtime-api", "pallet-offences", "pallet-offences-benchmarking", + "pallet-parameters", "pallet-preimage", "pallet-proxy", "pallet-ranked-collective", @@ -14349,6 +14381,7 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-common", "polkadot-runtime-parachains", + "relay-common", "scale-info", "separator", "serde_json", @@ -14376,6 +14409,7 @@ dependencies = [ "sp-transaction-pool", "sp-trie 36.0.0", "sp-version", + "ss58-registry", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", diff --git a/Cargo.toml b/Cargo.toml index 280dcd504a..8c6e70033a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -137,6 +137,7 @@ pallet-nomination-pools-benchmarking = { version = "34.0.0", default-features = pallet-nomination-pools-runtime-api = { version = "31.0.0", default-features = false } pallet-offences = { version = "35.0.0", default-features = false } pallet-offences-benchmarking = { version = "36.0.0", default-features = false } +pallet-parameters = { version = "0.7.0", default-features = false } pallet-preimage = { version = "36.0.0", default-features = false } pallet-proxy = { version = "36.0.0", default-features = false } pallet-ranked-collective = { version = "36.0.0", default-features = false } @@ -243,6 +244,8 @@ subxt = { version = "0.35.0", default-features = false } tracing-subscriber = { version = "0.3.18" } zombienet-sdk = { version = "0.2.4" } tuplex = { version = "0.1.0", default-features = false } +relay-common = { path = "relay/common", default-features = false } +ss58-registry = { version = "1.47.0" } [workspace] resolver = "2" @@ -275,6 +278,7 @@ members = [ "integration-tests/emulated/tests/people/people-kusama", "integration-tests/emulated/tests/people/people-polkadot", "integration-tests/zombienet", + "relay/common", "relay/kusama", "relay/kusama/constants", "relay/polkadot", diff --git a/relay/common/Cargo.toml b/relay/common/Cargo.toml new file mode 100644 index 0000000000..1b6ded352a --- /dev/null +++ b/relay/common/Cargo.toml @@ -0,0 +1,30 @@ +[package] +authors.workspace = true +description = "Shared utilities between relay runtimes" +edition.workspace = true +license.workspace = true +name = "relay-common" +repository.workspace = true +version.workspace = true + +[dependencies] +codec = { features = ["derive", "max-encoded-len"], workspace = true } +scale-info = { features = ["derive"], workspace = true } + +sp-api ={ workspace = true } +sp-runtime = { workspace = true } +polkadot-primitives = { workspace = true } +pallet-staking-reward-fn ={ workspace = true } + + +[features] +default = ["std"] +std = [ + "codec/std", + "scale-info/std", + + "sp-api/std", + "sp-runtime/std", + "polkadot-primitives/std", + "pallet-staking-reward-fn/std", +] diff --git a/relay/common/src/lib.rs b/relay/common/src/lib.rs new file mode 100644 index 0000000000..0f0e119f25 --- /dev/null +++ b/relay/common/src/lib.rs @@ -0,0 +1,115 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Shared code between the Kusama nd Polkadot RC Runtimes. +#![cfg_attr(not(feature = "std"), no_std)] + +use polkadot_primitives::Balance; +use sp_runtime::{Perquintill, Saturating}; + +/// Extra runtime APIs for kusama runtime. +pub mod apis { + /// Information about the current inflation rate of the system. + /// + /// Both fields should be treated as best-effort, given that the inflation rate might not be + /// fully predict-able. + #[derive(scale_info::TypeInfo, codec::Encode, codec::Decode)] + pub struct InflationInfo { + /// The rate of inflation estimated per annum. + pub inflation: sp_runtime::Perquintill, + /// Next amount that we anticipate to mint. + /// + /// First item is the amount that goes to stakers, second is the leftover that is usually + /// forwarded to the treasury. + pub next_mint: (polkadot_primitives::Balance, polkadot_primitives::Balance), + } + + sp_api::decl_runtime_apis! { + pub trait Inflation { + /// Return the current estimates of the inflation amount. + /// + /// This is marked as experimental in light of RFC#89. Nonetheless, its usage is highly + /// recommended over trying to read-storage, or re-create the onchain logic. + fn experimental_inflation_prediction_info() -> InflationInfo; + } + } +} + +// ---- TODO: Below is copy pasted from sdk, remove once we pull the version containing +// https://github.com/paritytech/polkadot-sdk/pull/4938 + +#[derive(Debug, Clone)] +/// Parameters passed into [`relay_era_payout`] function. +pub struct EraPayoutParams { + /// Total staked amount. + pub total_staked: Balance, + /// Total stakable amount. + /// + /// Usually, this is equal to the total issuance, except if a large part of the issuance is + /// locked in another sub-system. + pub total_stakable: Balance, + /// Ideal stake ratio, which is reduced by `legacy_auction_proportion` if not `None`. + pub ideal_stake: Perquintill, + /// Maximum inflation rate. + pub max_annual_inflation: Perquintill, + /// Minimum inflation rate. + pub min_annual_inflation: Perquintill, + /// Falloff used to calculate era payouts. + pub falloff: Perquintill, + /// Fraction of the era period used to calculate era payouts. + pub period_fraction: Perquintill, + /// Legacy auction proportion, which, if not `None`, is subtracted from `ideal_stake`. + pub legacy_auction_proportion: Option, +} + +/// A specialized function to compute the inflation of the staking system, tailored for Polkadot +/// Relay Chains, such as Polkadot, Kusama, and Westend. +pub fn relay_era_payout(params: EraPayoutParams) -> (Balance, Balance) { + let EraPayoutParams { + total_staked, + total_stakable, + ideal_stake, + max_annual_inflation, + min_annual_inflation, + falloff, + period_fraction, + legacy_auction_proportion, + } = params; + + let delta_annual_inflation = max_annual_inflation.saturating_sub(min_annual_inflation); + + let ideal_stake = ideal_stake.saturating_sub(legacy_auction_proportion.unwrap_or_default()); + + let stake = Perquintill::from_rational(total_staked, total_stakable); + let adjustment = pallet_staking_reward_fn::compute_inflation(stake, ideal_stake, falloff); + let staking_inflation = + min_annual_inflation.saturating_add(delta_annual_inflation * adjustment); + + let max_payout = period_fraction * max_annual_inflation * total_stakable; + let staking_payout = (period_fraction * staking_inflation) * total_stakable; + let rest = max_payout.saturating_sub(staking_payout); + + let other_issuance = total_stakable.saturating_sub(total_staked); + if total_staked > other_issuance { + let _cap_rest = Perquintill::from_rational(other_issuance, total_staked) * staking_payout; + // We don't do anything with this, but if we wanted to, we could introduce a cap on the + // treasury amount with: `rest = rest.min(cap_rest);` + } + (staking_payout, rest) +} + +// ---- TODO: Above is copy pasted from sdk, remove once we pull the version containing +// https://github.com/paritytech/polkadot-sdk/pull/4938 diff --git a/relay/kusama/Cargo.toml b/relay/kusama/Cargo.toml index 5a600a1d35..0cc6705aab 100644 --- a/relay/kusama/Cargo.toml +++ b/relay/kusama/Cargo.toml @@ -85,6 +85,7 @@ pallet-whitelist = { workspace = true } pallet-xcm = { workspace = true } pallet-xcm-benchmarks = { optional = true, workspace = true } frame-election-provider-support = { workspace = true } +pallet-parameters = { workspace = true } frame-benchmarking = { optional = true, workspace = true } frame-try-runtime = { optional = true, workspace = true } @@ -105,6 +106,7 @@ xcm-builder = { workspace = true } xcm-runtime-apis = { workspace = true } sp-debug-derive = { workspace = true } +relay-common = { workspace = true } [dev-dependencies] sp-keyring = { workspace = true } @@ -113,6 +115,7 @@ separator = { workspace = true } remote-externalities = { workspace = true } tokio = { features = ["macros"], workspace = true } sp-tracing = { workspace = true } +ss58-registry = { workspace = true } [build-dependencies] substrate-wasm-builder = { workspace = true, optional = true } @@ -166,6 +169,7 @@ std = [ "pallet-offences/std", "pallet-preimage/std", "pallet-proxy/std", + "pallet-parameters/std", "pallet-ranked-collective/std", "pallet-recovery/std", "pallet-referenda/std", @@ -186,6 +190,7 @@ std = [ "pallet-xcm/std", "polkadot-primitives/std", "polkadot-runtime-common/std", + "relay-common/std", "runtime-parachains/std", "scale-info/std", "serde_json/std", @@ -241,6 +246,7 @@ runtime-benchmarks = [ "pallet-nomination-pools/runtime-benchmarks", "pallet-offences-benchmarking/runtime-benchmarks", "pallet-offences/runtime-benchmarks", + "pallet-parameters/runtime-benchmarks", "pallet-preimage/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", "pallet-ranked-collective/runtime-benchmarks", @@ -314,6 +320,7 @@ try-runtime = [ "polkadot-runtime-common/try-runtime", "runtime-parachains/try-runtime", "sp-runtime/try-runtime", + "pallet-parameters/try-runtime", ] # Enable metadata hash generation at compile time for the `CheckMetadataHash` extension. diff --git a/relay/kusama/src/lib.rs b/relay/kusama/src/lib.rs index bb31116d06..1be9dc612c 100644 --- a/relay/kusama/src/lib.rs +++ b/relay/kusama/src/lib.rs @@ -20,8 +20,14 @@ // `construct_runtime!` does a lot of recursion and requires us to increase the limit. #![recursion_limit = "512"] +extern crate alloc; + use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::weights::constants::{WEIGHT_PROOF_SIZE_PER_KB, WEIGHT_REF_TIME_PER_MICROS}; +use frame_support::{ + dynamic_params::{dynamic_pallet_params, dynamic_params}, + traits::EnsureOriginWithArg, + weights::constants::{WEIGHT_PROOF_SIZE_PER_KB, WEIGHT_REF_TIME_PER_MICROS}, +}; use kusama_runtime_constants::system_parachain::coretime::TIMESLICE_PERIOD; use pallet_nis::WithMaximumOf; use polkadot_primitives::{ @@ -40,7 +46,9 @@ use polkadot_runtime_common::{ paras_registrar, prod_or_fast, slots, BalanceToU256, BlockHashCount, BlockLength, CurrencyToVote, SlowAdjustingFeeUpdate, U256ToBalance, }; +use relay_common::apis::*; use scale_info::TypeInfo; +use sp_runtime::traits::Saturating; use sp_std::{ cmp::Ordering, collections::{btree_map::BTreeMap, vec_deque::VecDeque}, @@ -623,6 +631,86 @@ impl pallet_bags_list::Config for Runtime { type Score = sp_npos_elections::VoteWeight; } +/// Dynamic params that can be adjusted at runtime. +#[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::)] +pub mod dynamic_params { + use super::*; + + /// Parameters used to calculate era payouts, see + /// [`polkadot_runtime_common::impls::EraPayoutParams`]. + #[dynamic_pallet_params] + #[codec(index = 0)] + pub mod inflation { + /// Minimum inflation rate used to calculate era payouts. + #[codec(index = 0)] + pub static MinInflation: Perquintill = Perquintill::from_rational(25u64, 1000); + + /// Maximum inflation rate used to calculate era payouts. + #[codec(index = 1)] + pub static MaxInflation: Perquintill = Perquintill::from_percent(10); + + /// Ideal stake ratio used to calculate era payouts. + #[codec(index = 2)] + pub static IdealStake: Perquintill = Perquintill::from_percent(75); + + /// Falloff used to calculate era payouts. + #[codec(index = 3)] + pub static Falloff: Perquintill = Perquintill::from_percent(5); + + /// Whether to use auction slots or not in the calculation of era payouts. If true, then we + /// subtract `num_auctioned_slots.min(60) / 200` from `ideal_stake`. + /// + /// That is, we assume up to 60 parachains that are leased can reduce the ideal stake by a + /// maximum of 30%. + /// + /// With the move to Agile Coretime, this parameter does not make much sense and should + /// generally be set to false. + #[codec(index = 4)] + pub static UseAuctionSlots: bool = false; + } +} + +#[cfg(feature = "runtime-benchmarks")] +impl Default for RuntimeParameters { + fn default() -> Self { + RuntimeParameters::Inflation(dynamic_params::inflation::Parameters::MinInflation( + dynamic_params::inflation::MinInflation, + Some(Perquintill::from_rational(25u64, 1000u64)), + )) + } +} + +/// Defines what origin can modify which dynamic parameters. +pub struct DynamicParameterOrigin; +impl EnsureOriginWithArg for DynamicParameterOrigin { + type Success = (); + + fn try_origin( + origin: RuntimeOrigin, + key: &RuntimeParametersKey, + ) -> Result { + use crate::RuntimeParametersKey::*; + + match key { + Inflation(_) => frame_system::ensure_root(origin.clone()), + } + .map_err(|_| origin) + } + + #[cfg(feature = "runtime-benchmarks")] + fn try_successful_origin(_key: &RuntimeParametersKey) -> Result { + // Provide the origin for the parameter returned by `Default`: + Ok(RuntimeOrigin::root()) + } +} + +impl pallet_parameters::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeParameters = RuntimeParameters; + type AdminOrigin = DynamicParameterOrigin; + type WeightInfo = weights::pallet_parameters::WeightInfo; +} + pub struct EraPayout; impl pallet_staking::EraPayout for EraPayout { fn era_payout( @@ -630,24 +718,30 @@ impl pallet_staking::EraPayout for EraPayout { _total_issuance: Balance, era_duration_millis: u64, ) -> (Balance, Balance) { - // all para-ids that are currently active. - let auctioned_slots = parachains_paras::Parachains::::get() - .into_iter() - // all active para-ids that do not belong to a system chain is the number - // of parachains that we should take into account for inflation. - .filter(|i| *i >= LOWEST_PUBLIC_ID) - .count() as u64; - - const MAX_ANNUAL_INFLATION: Perquintill = Perquintill::from_percent(10); const MILLISECONDS_PER_YEAR: u64 = 1000 * 3600 * 24 * 36525 / 100; - polkadot_runtime_common::impls::era_payout( + let params = relay_common::EraPayoutParams { total_staked, - Nis::issuance().other, - MAX_ANNUAL_INFLATION, - Perquintill::from_rational(era_duration_millis, MILLISECONDS_PER_YEAR), - auctioned_slots, - ) + total_stakable: Nis::issuance().other, + ideal_stake: dynamic_params::inflation::IdealStake::get(), + max_annual_inflation: dynamic_params::inflation::MaxInflation::get(), + min_annual_inflation: dynamic_params::inflation::MinInflation::get(), + falloff: dynamic_params::inflation::Falloff::get(), + period_fraction: Perquintill::from_rational(era_duration_millis, MILLISECONDS_PER_YEAR), + legacy_auction_proportion: if dynamic_params::inflation::UseAuctionSlots::get() { + let auctioned_slots = parachains_paras::Parachains::::get() + .into_iter() + // All active para-ids that do not belong to a system chain is the number of + // parachains that we should take into account for inflation. + .filter(|i| *i >= LOWEST_PUBLIC_ID) + .count() as u64; + Some(Perquintill::from_rational(auctioned_slots.min(60), 200u64)) + } else { + None + }, + }; + log::debug!(target: "runtime::kusama", "params: {:?}", params); + relay_common::relay_era_payout(params) } } @@ -1568,6 +1662,7 @@ construct_runtime! { FellowshipReferenda: pallet_referenda:: = 23, Origins: pallet_custom_origins = 43, Whitelist: pallet_whitelist = 44, + Parameters: pallet_parameters = 46, // Claims. Usable initially. Claims: claims = 19, @@ -1781,6 +1876,7 @@ mod benches { [pallet_vesting, Vesting] [pallet_whitelist, Whitelist] [pallet_asset_rate, AssetRate] + [pallet_parameters, Parameters] // XCM [pallet_xcm, PalletXcmExtrinsiscsBenchmark::] [pallet_xcm_benchmarks::fungible, pallet_xcm_benchmarks::fungible::Pallet::] @@ -1788,7 +1884,47 @@ mod benches { ); } +impl Runtime { + fn impl_experimental_inflation_info() -> InflationInfo { + use pallet_staking::{ActiveEra, EraPayout, ErasTotalStake}; + let (staked, _start) = ActiveEra::::get() + .map(|ae| (ErasTotalStake::::get(ae.index), ae.start.unwrap_or(0))) + .unwrap_or((0, 0)); + let stake_able_issuance = Nis::issuance().other; + + let ideal_staking_rate = dynamic_params::inflation::IdealStake::get(); + let inflation = if dynamic_params::inflation::UseAuctionSlots::get() { + let auctioned_slots = parachains_paras::Parachains::::get() + .into_iter() + // All active para-ids that do not belong to a system chain is the number of + // parachains that we should take into account for inflation. + .filter(|i| *i >= LOWEST_PUBLIC_ID) + .count() as u64; + ideal_staking_rate + .saturating_sub(Perquintill::from_rational(auctioned_slots.min(60), 200u64)) + } else { + ideal_staking_rate + }; + + // We assume un-delayed 6h eras. + let era_duration = 6 * HOURS; + let next_mint = ::EraPayout::era_payout( + staked, + stake_able_issuance, + era_duration.into(), + ); + + InflationInfo { inflation, next_mint } + } +} + sp_api::impl_runtime_apis! { + impl relay_common::apis::Inflation for Runtime { + fn experimental_inflation_prediction_info() -> InflationInfo { + Runtime::impl_experimental_inflation_info() + } + } + impl sp_api::Core for Runtime { fn version() -> RuntimeVersion { VERSION @@ -2844,6 +2980,75 @@ mod remote_tests { ext.execute_with(|| Runtime::on_runtime_upgrade(UpgradeCheckSelect::PreAndPost)); } + #[tokio::test] + async fn next_inflation() { + use hex_literal::hex; + sp_tracing::try_init_simple(); + let transport: Transport = + var("WS").unwrap_or("wss://rpc.dotters.network/kusama".to_string()).into(); + let mut ext = Builder::::default() + .mode(Mode::Online(OnlineConfig { + transport, + hashed_prefixes: vec![ + // entire nis pallet + hex!("928fa8b8d92aa31f47ed74f188a43f70").to_vec(), + // staking eras total stake + hex!("5f3e4907f716ac89b6347d15ececedcaa141c4fe67c2d11f4a10c6aca7a79a04") + .to_vec(), + ], + hashed_keys: vec![ + // staking active era + hex!("5f3e4907f716ac89b6347d15ececedca487df464e44a534ba6b0cbb32407b587") + .to_vec(), + // balances ti + hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80") + .to_vec(), + // timestamp now + hex!("f0c365c3cf59d671eb72da0e7a4113c49f1f0515f462cdcf84e0f1d6045dfcbb") + .to_vec(), + // para-ids + hex!("cd710b30bd2eab0352ddcc26417aa1940b76934f4cc08dee01012d059e1b83ee") + .to_vec(), + ], + ..Default::default() + })) + .build() + .await + .unwrap(); + ext.execute_with(|| { + use pallet_staking::EraPayout; + let (total_staked, started) = pallet_staking::ActiveEra::::get() + .map(|ae| { + (pallet_staking::ErasTotalStake::::get(ae.index), ae.start.unwrap()) + }) + .unwrap(); + let total_issuance = Nis::issuance().other; + let _real_era_duration_millis = + pallet_timestamp::Now::::get().saturating_sub(started); + // 6h in milliseconds + let average_era_duration_millis = 6 * 60 * 60 * 1000; + let (staking, leftover) = ::EraPayout::era_payout( + total_staked, + total_issuance, + average_era_duration_millis, + ); + use ss58_registry::TokenRegistry; + let token: ss58_registry::Token = TokenRegistry::Ksm.into(); + + log::info!(target: "runtime::kusama", "total-staked = {:?}", token.amount(total_staked)); + log::info!(target: "runtime::kusama", "total-issuance = {:?}", token.amount(total_issuance)); + log::info!(target: "runtime::kusama", "staking-rate = {:?}", Perquintill::from_rational(total_staked, total_issuance)); + log::info!(target: "runtime::kusama", "era-duration = {:?}", average_era_duration_millis); + log::info!(target: "runtime::kusama", "min-inflation = {:?}", dynamic_params::inflation::MinInflation::get()); + log::info!(target: "runtime::kusama", "max-inflation = {:?}", dynamic_params::inflation::MaxInflation::get()); + log::info!(target: "runtime::kusama", "falloff = {:?}", dynamic_params::inflation::Falloff::get()); + log::info!(target: "runtime::kusama", "useAuctionSlots = {:?}", dynamic_params::inflation::UseAuctionSlots::get()); + log::info!(target: "runtime::kusama", "idealStake = {:?}", dynamic_params::inflation::IdealStake::get()); + log::info!(target: "runtime::kusama", "maxStakingRewards = {:?}", pallet_staking::MaxStakedRewards::::get()); + log::info!(target: "runtime::kusama", "💰 Inflation ==> staking = {:?} / leftover = {:?}", token.amount(staking), token.amount(leftover)); + }); + } + #[tokio::test] #[ignore = "this test is meant to be executed manually"] async fn try_fast_unstake_all() { diff --git a/relay/kusama/src/weights/mod.rs b/relay/kusama/src/weights/mod.rs index 21d376bcce..263e2e1c6d 100644 --- a/relay/kusama/src/weights/mod.rs +++ b/relay/kusama/src/weights/mod.rs @@ -31,6 +31,7 @@ pub mod pallet_message_queue; pub mod pallet_multisig; pub mod pallet_nis; pub mod pallet_nomination_pools; +pub mod pallet_parameters; pub mod pallet_preimage; pub mod pallet_proxy; pub mod pallet_ranked_collective; diff --git a/relay/kusama/src/weights/pallet_parameters.rs b/relay/kusama/src/weights/pallet_parameters.rs new file mode 100644 index 0000000000..a393c8de68 --- /dev/null +++ b/relay/kusama/src/weights/pallet_parameters.rs @@ -0,0 +1,51 @@ +// Copyright (C) Parity Technologies and the various Polkadot contributors, see Contributions.md +// for a list of specific contributors. +// SPDX-License-Identifier: Apache-2.0 + +//! Autogenerated weights for `pallet_parameters` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-04-05, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-anb7yjbi-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("kusama-dev")`, DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_parameters +// --chain=kusama-dev +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/kusama/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_parameters`. +pub struct WeightInfo(PhantomData); +impl pallet_parameters::WeightInfo for WeightInfo { + /// Storage: `Parameters::Parameters` (r:1 w:1) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn set_parameter() -> Weight { + // Proof Size summary in bytes: + // Measured: `4` + // Estimated: `3493` + // Minimum execution time: 6_937_000 picoseconds. + Weight::from_parts(7_242_000, 0) + .saturating_add(Weight::from_parts(0, 3493)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} From 56de0a9a12b87198b862ae0f2d2d8022bb61b0d9 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 20 Aug 2024 15:56:10 +0300 Subject: [PATCH 2/3] [tests] add more e2e tests, make emulated setup closer to ecosystem reality (#428) In the real world, not all assets are sufficient. This aligns our emulated networks to that reality. Only DOT/KSM and USDT are sufficient "by default" in tests. Also added more e2e tests. - [x] Does not require a CHANGELOG entry --------- Co-authored-by: fellowship-merge-bot[bot] <151052383+fellowship-merge-bot[bot]@users.noreply.github.com> --- .../assets/asset-hub-kusama/src/genesis.rs | 8 +- .../assets/asset-hub-polkadot/src/genesis.rs | 10 +- .../tests/assets/asset-hub-kusama/src/lib.rs | 7 +- .../src/tests/hybrid_transfers.rs | 205 +++++----- .../src/tests/reserve_transfer.rs | 351 ++++++++++++++++- .../assets/asset-hub-kusama/src/tests/send.rs | 133 +++++-- .../asset-hub-kusama/src/tests/teleport.rs | 192 ++------- .../asset-hub-kusama/src/tests/treasury.rs | 24 +- .../assets/asset-hub-polkadot/src/lib.rs | 7 +- .../src/tests/fellowship_treasury.rs | 26 +- .../src/tests/hybrid_transfers.rs | 207 +++++----- .../src/tests/reserve_transfer.rs | 366 ++++++++++++++++-- .../asset-hub-polkadot/src/tests/send.rs | 145 +++++-- .../asset-hub-polkadot/src/tests/teleport.rs | 192 ++------- .../asset-hub-polkadot/src/tests/treasury.rs | 26 +- .../src/tests/snowbridge.rs | 129 ++++++ .../src/tests/fellowship_salary.rs | 25 +- .../tests/people/people-kusama/src/lib.rs | 1 + .../people-kusama/src/tests/claim_assets.rs | 29 ++ .../people/people-kusama/src/tests/mod.rs | 1 + .../people-kusama/src/tests/teleport.rs | 2 +- .../tests/people/people-polkadot/src/lib.rs | 3 +- .../people-polkadot/src/tests/claim_assets.rs | 29 ++ .../people/people-polkadot/src/tests/mod.rs | 1 + .../people-polkadot/src/tests/teleport.rs | 8 +- 25 files changed, 1412 insertions(+), 715 deletions(-) create mode 100644 integration-tests/emulated/tests/people/people-kusama/src/tests/claim_assets.rs create mode 100644 integration-tests/emulated/tests/people/people-polkadot/src/tests/claim_assets.rs diff --git a/integration-tests/emulated/chains/parachains/assets/asset-hub-kusama/src/genesis.rs b/integration-tests/emulated/chains/parachains/assets/asset-hub-kusama/src/genesis.rs index 0da714d34a..5880e98368 100644 --- a/integration-tests/emulated/chains/parachains/assets/asset-hub-kusama/src/genesis.rs +++ b/integration-tests/emulated/chains/parachains/assets/asset-hub-kusama/src/genesis.rs @@ -28,6 +28,7 @@ use xcm::prelude::*; pub const PARA_ID: u32 = 1000; pub const ED: Balance = asset_hub_kusama_runtime::ExistentialDeposit::get(); +pub const USDT_ID: u32 = 1984; frame_support::parameter_types! { pub AssetHubKusamaAssetOwner: AccountId = get_account_id_from_seed::("Alice"); @@ -77,7 +78,10 @@ pub fn genesis() -> Storage { ..Default::default() }, assets: asset_hub_kusama_runtime::AssetsConfig { - assets: vec![(RESERVABLE_ASSET_ID, AssetHubKusamaAssetOwner::get(), true, ED)], + assets: vec![ + (RESERVABLE_ASSET_ID, AssetHubKusamaAssetOwner::get(), false, ED), + (USDT_ID, AssetHubKusamaAssetOwner::get(), true, ED), + ], ..Default::default() }, foreign_assets: asset_hub_kusama_runtime::ForeignAssetsConfig { @@ -86,7 +90,7 @@ pub fn genesis() -> Storage { ( PenpalATeleportableAssetLocation::get().try_into().unwrap(), PenpalASiblingSovereignAccount::get(), - true, + false, ED, ), ], diff --git a/integration-tests/emulated/chains/parachains/assets/asset-hub-polkadot/src/genesis.rs b/integration-tests/emulated/chains/parachains/assets/asset-hub-polkadot/src/genesis.rs index 38bb6309d2..1a4054839d 100644 --- a/integration-tests/emulated/chains/parachains/assets/asset-hub-polkadot/src/genesis.rs +++ b/integration-tests/emulated/chains/parachains/assets/asset-hub-polkadot/src/genesis.rs @@ -29,6 +29,7 @@ use xcm::prelude::*; pub const PARA_ID: u32 = 1000; pub const ED: Balance = asset_hub_polkadot_runtime::ExistentialDeposit::get(); +pub const USDT_ID: u32 = 1984; frame_support::parameter_types! { pub AssetHubPolkadotAssetOwner: AccountId = get_account_id_from_seed::("Alice"); @@ -103,7 +104,10 @@ pub fn genesis() -> Storage { ..Default::default() }, assets: asset_hub_polkadot_runtime::AssetsConfig { - assets: vec![(RESERVABLE_ASSET_ID, AssetHubPolkadotAssetOwner::get(), true, ED)], + assets: vec![ + (RESERVABLE_ASSET_ID, AssetHubPolkadotAssetOwner::get(), false, ED), + (USDT_ID, AssetHubPolkadotAssetOwner::get(), true, ED), + ], ..Default::default() }, foreign_assets: asset_hub_polkadot_runtime::ForeignAssetsConfig { @@ -112,13 +116,13 @@ pub fn genesis() -> Storage { ( PenpalATeleportableAssetLocation::get().try_into().unwrap(), PenpalASiblingSovereignAccount::get(), - true, + false, ED, ), ( PenpalBTeleportableAssetLocation::get().try_into().unwrap(), PenpalBSiblingSovereignAccount::get(), - true, + false, ED, ), ], diff --git a/integration-tests/emulated/tests/assets/asset-hub-kusama/src/lib.rs b/integration-tests/emulated/tests/assets/asset-hub-kusama/src/lib.rs index eb274ac988..4b9857cd69 100644 --- a/integration-tests/emulated/tests/assets/asset-hub-kusama/src/lib.rs +++ b/integration-tests/emulated/tests/assets/asset-hub-kusama/src/lib.rs @@ -18,10 +18,12 @@ pub use codec::Encode; // Substrate pub use frame_support::{ assert_err, assert_ok, + dispatch::RawOrigin, pallet_prelude::Weight, sp_runtime::{AccountId32, DispatchError, DispatchResult}, traits::fungibles::Inspect, }; +pub use sp_runtime::traits::Dispatchable; // Polkadot pub use xcm::{ @@ -41,6 +43,9 @@ pub use emulated_integration_tests_common::{ xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution}, PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, RESERVABLE_ASSET_ID, XCM_V3, }; +pub use integration_tests_helpers::{ + test_parachain_is_trusted_teleporter_for_relay, test_relay_is_trusted_teleporter, +}; pub use kusama_runtime::xcm_config::UniversalLocation as KusamaUniversalLocation; pub use kusama_system_emulated_network::{ asset_hub_kusama_emulated_chain::{ @@ -67,8 +72,8 @@ pub const ASSET_MIN_BALANCE: u128 = 1000; // `Assets` pallet index pub const ASSETS_PALLET_ID: u8 = 50; -pub type RelayToSystemParaTest = Test; pub type RelayToParaTest = Test; +pub type ParaToRelayTest = Test; pub type SystemParaToRelayTest = Test; pub type SystemParaToParaTest = Test; pub type ParaToSystemParaTest = Test; diff --git a/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/hybrid_transfers.rs b/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/hybrid_transfers.rs index 893a79315c..f6f8999f0c 100644 --- a/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/hybrid_transfers.rs +++ b/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/hybrid_transfers.rs @@ -161,30 +161,29 @@ fn transfer_foreign_assets_from_asset_hub_to_para() { let native_asset_location = KsmLocation::get(); let receiver = PenpalAReceiver::get(); let assets_owner = PenpalAssetOwner::get(); - // Foreign asset used: bridged WND + // Foreign asset used: bridged DOT let foreign_amount_to_send = ASSET_HUB_KUSAMA_ED * 10_000_000; - let wnd_at_rococo_parachains = - Location::new(2, [Junction::GlobalConsensus(NetworkId::Westend)]); + let dot_at_kusama_parachains = Location::new(2, [GlobalConsensus(Polkadot)]); - // Configure destination chain to trust AH as reserve of WND + // Configure destination chain to trust AH as reserve of DOT PenpalA::execute_with(|| { assert_ok!(::System::set_storage( ::RuntimeOrigin::root(), vec![( CustomizableAssetFromSystemAssetHub::key().to_vec(), - Location::new(2, [GlobalConsensus(Westend)]).encode(), + Location::new(2, [GlobalConsensus(Polkadot)]).encode(), )], )); }); PenpalA::force_create_foreign_asset( - wnd_at_rococo_parachains.clone(), + dot_at_kusama_parachains.clone(), assets_owner.clone(), false, ASSET_MIN_BALANCE, vec![], ); AssetHubKusama::force_create_foreign_asset( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + dot_at_kusama_parachains.clone().try_into().unwrap(), assets_owner.clone(), false, ASSET_MIN_BALANCE, @@ -192,7 +191,7 @@ fn transfer_foreign_assets_from_asset_hub_to_para() { ); AssetHubKusama::mint_foreign_asset( ::RuntimeOrigin::signed(assets_owner), - wnd_at_rococo_parachains.clone().try_into().unwrap(), + dot_at_kusama_parachains.clone().try_into().unwrap(), sender.clone(), foreign_amount_to_send * 2, ); @@ -200,7 +199,7 @@ fn transfer_foreign_assets_from_asset_hub_to_para() { // Assets to send let assets: Vec = vec![ (Parent, native_amount_to_send).into(), - (wnd_at_rococo_parachains.clone(), foreign_amount_to_send).into(), + (dot_at_kusama_parachains.clone(), foreign_amount_to_send).into(), ]; let fee_asset_id = AssetId(Parent.into()); let fee_asset_item = assets.iter().position(|a| a.id == fee_asset_id).unwrap() as u32; @@ -222,10 +221,10 @@ fn transfer_foreign_assets_from_asset_hub_to_para() { // Query initial balances let sender_balance_before = test.sender.balance; - let sender_wnds_before = AssetHubKusama::execute_with(|| { + let sender_dots_before = AssetHubKusama::execute_with(|| { type ForeignAssets = ::ForeignAssets; >::balance( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + dot_at_kusama_parachains.clone().try_into().unwrap(), &sender, ) }); @@ -233,9 +232,9 @@ fn transfer_foreign_assets_from_asset_hub_to_para() { type ForeignAssets = ::ForeignAssets; >::balance(native_asset_location.clone(), &receiver) }); - let receiver_wnds_before = PenpalA::execute_with(|| { + let receiver_dots_before = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(wnd_at_rococo_parachains.clone(), &receiver) + >::balance(dot_at_kusama_parachains.clone(), &receiver) }); // Set assertions and dispatchables @@ -246,10 +245,10 @@ fn transfer_foreign_assets_from_asset_hub_to_para() { // Query final balances let sender_balance_after = test.sender.balance; - let sender_wnds_after = AssetHubKusama::execute_with(|| { + let sender_dots_after = AssetHubKusama::execute_with(|| { type ForeignAssets = ::ForeignAssets; >::balance( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + dot_at_kusama_parachains.clone().try_into().unwrap(), &sender, ) }); @@ -257,15 +256,15 @@ fn transfer_foreign_assets_from_asset_hub_to_para() { type ForeignAssets = ::ForeignAssets; >::balance(native_asset_location, &receiver) }); - let receiver_wnds_after = PenpalA::execute_with(|| { + let receiver_dots_after = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(wnd_at_rococo_parachains, &receiver) + >::balance(dot_at_kusama_parachains, &receiver) }); // Sender's balance is reduced by amount sent plus delivery fees assert!(sender_balance_after < sender_balance_before - native_amount_to_send); // Sender's balance is reduced by foreign amount sent - assert_eq!(sender_wnds_after, sender_wnds_before - foreign_amount_to_send); + assert_eq!(sender_dots_after, sender_dots_before - foreign_amount_to_send); // Receiver's assets is increased assert!(receiver_assets_after > receiver_assets_before); // Receiver's assets increased by `amount_to_send - delivery_fees - bought_execution`; @@ -273,7 +272,7 @@ fn transfer_foreign_assets_from_asset_hub_to_para() { // should be non-zero assert!(receiver_assets_after < receiver_assets_before + native_amount_to_send); // Receiver's balance is increased by foreign amount sent - assert_eq!(receiver_wnds_after, receiver_wnds_before + foreign_amount_to_send); + assert_eq!(receiver_dots_after, receiver_dots_before + foreign_amount_to_send); } /// Reserve Transfers of native asset from Parachain to System Parachain should work @@ -291,30 +290,29 @@ fn transfer_foreign_assets_from_para_to_asset_hub() { let native_asset_location = KsmLocation::get(); let assets_owner = PenpalAssetOwner::get(); - // Foreign asset used: bridged WND + // Foreign asset used: bridged DOT let foreign_amount_to_send = ASSET_HUB_KUSAMA_ED * 10_000_000; - let wnd_at_rococo_parachains = - Location::new(2, [Junction::GlobalConsensus(NetworkId::Westend)]); + let dot_at_kusama_parachains = Location::new(2, [GlobalConsensus(Polkadot)]); - // Configure destination chain to trust AH as reserve of WND + // Configure destination chain to trust AH as reserve of DOT PenpalA::execute_with(|| { assert_ok!(::System::set_storage( ::RuntimeOrigin::root(), vec![( CustomizableAssetFromSystemAssetHub::key().to_vec(), - Location::new(2, [GlobalConsensus(Westend)]).encode(), + Location::new(2, [GlobalConsensus(Polkadot)]).encode(), )], )); }); PenpalA::force_create_foreign_asset( - wnd_at_rococo_parachains.clone(), + dot_at_kusama_parachains.clone(), assets_owner.clone(), false, ASSET_MIN_BALANCE, vec![], ); AssetHubKusama::force_create_foreign_asset( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + dot_at_kusama_parachains.clone().try_into().unwrap(), assets_owner.clone(), false, ASSET_MIN_BALANCE, @@ -330,29 +328,29 @@ fn transfer_foreign_assets_from_para_to_asset_hub() { ); PenpalA::mint_foreign_asset( ::RuntimeOrigin::signed(assets_owner.clone()), - wnd_at_rococo_parachains.clone(), + dot_at_kusama_parachains.clone(), sender.clone(), foreign_amount_to_send * 2, ); // Init values for System Parachain let receiver = AssetHubKusamaReceiver::get(); - let penpal_location_as_seen_by_ahr = AssetHubKusama::sibling_location_of(PenpalA::para_id()); - let sov_penpal_on_ahr = AssetHubKusama::sovereign_account_id_of(penpal_location_as_seen_by_ahr); + let penpal_location_as_seen_by_ahk = AssetHubKusama::sibling_location_of(PenpalA::para_id()); + let sov_penpal_on_ahk = AssetHubKusama::sovereign_account_id_of(penpal_location_as_seen_by_ahk); // fund Parachain's SA on AssetHub with the assets held in reserve - AssetHubKusama::fund_accounts(vec![(sov_penpal_on_ahr.clone(), native_amount_to_send * 2)]); + AssetHubKusama::fund_accounts(vec![(sov_penpal_on_ahk.clone(), native_amount_to_send * 2)]); AssetHubKusama::mint_foreign_asset( ::RuntimeOrigin::signed(assets_owner), - wnd_at_rococo_parachains.clone().try_into().unwrap(), - sov_penpal_on_ahr, + dot_at_kusama_parachains.clone().try_into().unwrap(), + sov_penpal_on_ahk, foreign_amount_to_send * 2, ); // Assets to send let assets: Vec = vec![ (Parent, native_amount_to_send).into(), - (wnd_at_rococo_parachains.clone(), foreign_amount_to_send).into(), + (dot_at_kusama_parachains.clone(), foreign_amount_to_send).into(), ]; let fee_asset_id = AssetId(Parent.into()); let fee_asset_item = assets.iter().position(|a| a.id == fee_asset_id).unwrap() as u32; @@ -377,15 +375,15 @@ fn transfer_foreign_assets_from_para_to_asset_hub() { type ForeignAssets = ::ForeignAssets; >::balance(native_asset_location.clone(), &sender) }); - let sender_wnds_before = PenpalA::execute_with(|| { + let sender_dots_before = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(wnd_at_rococo_parachains.clone(), &sender) + >::balance(dot_at_kusama_parachains.clone(), &sender) }); let receiver_native_before = test.receiver.balance; - let receiver_wnds_before = AssetHubKusama::execute_with(|| { + let receiver_dots_before = AssetHubKusama::execute_with(|| { type ForeignAssets = ::ForeignAssets; >::balance( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + dot_at_kusama_parachains.clone().try_into().unwrap(), &receiver, ) }); @@ -401,15 +399,15 @@ fn transfer_foreign_assets_from_para_to_asset_hub() { type ForeignAssets = ::ForeignAssets; >::balance(native_asset_location, &sender) }); - let sender_wnds_after = PenpalA::execute_with(|| { + let sender_dots_after = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(wnd_at_rococo_parachains.clone(), &sender) + >::balance(dot_at_kusama_parachains.clone(), &sender) }); let receiver_native_after = test.receiver.balance; - let receiver_wnds_after = AssetHubKusama::execute_with(|| { + let receiver_dots_after = AssetHubKusama::execute_with(|| { type ForeignAssets = ::ForeignAssets; >::balance( - wnd_at_rococo_parachains.try_into().unwrap(), + dot_at_kusama_parachains.try_into().unwrap(), &receiver, ) }); @@ -417,7 +415,7 @@ fn transfer_foreign_assets_from_para_to_asset_hub() { // Sender's balance is reduced by amount sent plus delivery fees assert!(sender_native_after < sender_native_before - native_amount_to_send); // Sender's balance is reduced by foreign amount sent - assert_eq!(sender_wnds_after, sender_wnds_before - foreign_amount_to_send); + assert_eq!(sender_dots_after, sender_dots_before - foreign_amount_to_send); // Receiver's balance is increased assert!(receiver_native_after > receiver_native_before); // Receiver's balance increased by `amount_to_send - delivery_fees - bought_execution`; @@ -425,7 +423,7 @@ fn transfer_foreign_assets_from_para_to_asset_hub() { // should be non-zero assert!(receiver_native_after < receiver_native_before + native_amount_to_send); // Receiver's balance is increased by foreign amount sent - assert_eq!(receiver_wnds_after, receiver_wnds_before + foreign_amount_to_send); + assert_eq!(receiver_dots_after, receiver_dots_before + foreign_amount_to_send); } // ============================================================================== @@ -438,45 +436,44 @@ fn transfer_foreign_assets_from_para_to_para_through_asset_hub() { // Init values for Parachain Origin let destination = PenpalA::sibling_location_of(PenpalB::para_id()); let sender = PenpalASender::get(); - let roc_to_send: Balance = KUSAMA_ED * 10000; + let ksm_to_send: Balance = KUSAMA_ED * 10000; let assets_owner = PenpalAssetOwner::get(); - let roc_location = KsmLocation::get(); + let ksm_location = KsmLocation::get(); let sender_as_seen_by_ah = AssetHubKusama::sibling_location_of(PenpalA::para_id()); let sov_of_sender_on_ah = AssetHubKusama::sovereign_account_id_of(sender_as_seen_by_ah); let receiver_as_seen_by_ah = AssetHubKusama::sibling_location_of(PenpalB::para_id()); let sov_of_receiver_on_ah = AssetHubKusama::sovereign_account_id_of(receiver_as_seen_by_ah); - let wnd_to_send = ASSET_HUB_KUSAMA_ED * 10_000_000; + let dot_to_send = ASSET_HUB_KUSAMA_ED * 10_000_000; - // Configure destination chain to trust AH as reserve of WND + // Configure destination chain to trust AH as reserve of DOT PenpalB::execute_with(|| { assert_ok!(::System::set_storage( ::RuntimeOrigin::root(), vec![( CustomizableAssetFromSystemAssetHub::key().to_vec(), - Location::new(2, [GlobalConsensus(Westend)]).encode(), + Location::new(2, [GlobalConsensus(Polkadot)]).encode(), )], )); }); - // Register WND as foreign asset and transfer it around the Kusama ecosystem - let wnd_at_rococo_parachains = - Location::new(2, [Junction::GlobalConsensus(NetworkId::Westend)]); + // Register DOT as foreign asset and transfer it around the Kusama ecosystem + let dot_at_kusama_parachains = Location::new(2, [GlobalConsensus(Polkadot)]); AssetHubKusama::force_create_foreign_asset( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + dot_at_kusama_parachains.clone().try_into().unwrap(), assets_owner.clone(), false, ASSET_MIN_BALANCE, vec![], ); PenpalA::force_create_foreign_asset( - wnd_at_rococo_parachains.clone(), + dot_at_kusama_parachains.clone(), assets_owner.clone(), false, ASSET_MIN_BALANCE, vec![], ); PenpalB::force_create_foreign_asset( - wnd_at_rococo_parachains.clone(), + dot_at_kusama_parachains.clone(), assets_owner.clone(), false, ASSET_MIN_BALANCE, @@ -486,23 +483,23 @@ fn transfer_foreign_assets_from_para_to_para_through_asset_hub() { // fund Parachain's sender account PenpalA::mint_foreign_asset( ::RuntimeOrigin::signed(assets_owner.clone()), - roc_location.clone(), + ksm_location.clone(), sender.clone(), - roc_to_send * 2, + ksm_to_send * 2, ); PenpalA::mint_foreign_asset( ::RuntimeOrigin::signed(assets_owner.clone()), - wnd_at_rococo_parachains.clone(), + dot_at_kusama_parachains.clone(), sender.clone(), - wnd_to_send * 2, + dot_to_send * 2, ); // fund the Parachain Origin's SA on Asset Hub with the assets held in reserve - AssetHubKusama::fund_accounts(vec![(sov_of_sender_on_ah.clone(), roc_to_send * 2)]); + AssetHubKusama::fund_accounts(vec![(sov_of_sender_on_ah.clone(), ksm_to_send * 2)]); AssetHubKusama::mint_foreign_asset( ::RuntimeOrigin::signed(assets_owner), - wnd_at_rococo_parachains.clone().try_into().unwrap(), + dot_at_kusama_parachains.clone().try_into().unwrap(), sov_of_sender_on_ah.clone(), - wnd_to_send * 2, + dot_to_send * 2, ); // Init values for Parachain Destination @@ -510,10 +507,10 @@ fn transfer_foreign_assets_from_para_to_para_through_asset_hub() { // Assets to send let assets: Vec = vec![ - (roc_location.clone(), roc_to_send).into(), - (wnd_at_rococo_parachains.clone(), wnd_to_send).into(), + (ksm_location.clone(), ksm_to_send).into(), + (dot_at_kusama_parachains.clone(), dot_to_send).into(), ]; - let fee_asset_id: AssetId = roc_location.clone().into(); + let fee_asset_id: AssetId = ksm_location.clone().into(); let fee_asset_item = assets.iter().position(|a| a.id == fee_asset_id).unwrap() as u32; // Init Test @@ -523,7 +520,7 @@ fn transfer_foreign_assets_from_para_to_para_through_asset_hub() { args: TestArgs::new_para( destination, receiver.clone(), - roc_to_send, + ksm_to_send, assets.into(), None, fee_asset_item, @@ -532,39 +529,39 @@ fn transfer_foreign_assets_from_para_to_para_through_asset_hub() { let mut test = ParaToParaThroughAHTest::new(test_args); // Query initial balances - let sender_rocs_before = PenpalA::execute_with(|| { + let sender_ksms_before = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(roc_location.clone(), &sender) + >::balance(ksm_location.clone(), &sender) }); - let sender_wnds_before = PenpalA::execute_with(|| { + let sender_dots_before = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(wnd_at_rococo_parachains.clone(), &sender) + >::balance(dot_at_kusama_parachains.clone(), &sender) }); - let rocs_in_sender_reserve_on_ahr_before = + let ksms_in_sender_reserve_on_ahk_before = ::account_data_of(sov_of_sender_on_ah.clone()).free; - let wnds_in_sender_reserve_on_ahr_before = AssetHubKusama::execute_with(|| { + let dots_in_sender_reserve_on_ahk_before = AssetHubKusama::execute_with(|| { type Assets = ::ForeignAssets; >::balance( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + dot_at_kusama_parachains.clone().try_into().unwrap(), &sov_of_sender_on_ah, ) }); - let rocs_in_receiver_reserve_on_ahr_before = + let ksms_in_receiver_reserve_on_ahk_before = ::account_data_of(sov_of_receiver_on_ah.clone()).free; - let wnds_in_receiver_reserve_on_ahr_before = AssetHubKusama::execute_with(|| { + let dots_in_receiver_reserve_on_ahk_before = AssetHubKusama::execute_with(|| { type Assets = ::ForeignAssets; >::balance( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + dot_at_kusama_parachains.clone().try_into().unwrap(), &sov_of_receiver_on_ah, ) }); - let receiver_rocs_before = PenpalB::execute_with(|| { + let receiver_ksms_before = PenpalB::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(roc_location.clone(), &receiver) + >::balance(ksm_location.clone(), &receiver) }); - let receiver_wnds_before = PenpalB::execute_with(|| { + let receiver_dots_before = PenpalB::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(wnd_at_rococo_parachains.clone(), &receiver) + >::balance(dot_at_kusama_parachains.clone(), &receiver) }); // Set assertions and dispatchables @@ -575,61 +572,61 @@ fn transfer_foreign_assets_from_para_to_para_through_asset_hub() { test.assert(); // Query final balances - let sender_rocs_after = PenpalA::execute_with(|| { + let sender_ksms_after = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(roc_location.clone(), &sender) + >::balance(ksm_location.clone(), &sender) }); - let sender_wnds_after = PenpalA::execute_with(|| { + let sender_dots_after = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(wnd_at_rococo_parachains.clone(), &sender) + >::balance(dot_at_kusama_parachains.clone(), &sender) }); - let wnds_in_sender_reserve_on_ahr_after = AssetHubKusama::execute_with(|| { + let dots_in_sender_reserve_on_ahk_after = AssetHubKusama::execute_with(|| { type Assets = ::ForeignAssets; >::balance( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + dot_at_kusama_parachains.clone().try_into().unwrap(), &sov_of_sender_on_ah, ) }); - let rocs_in_sender_reserve_on_ahr_after = + let ksms_in_sender_reserve_on_ahk_after = ::account_data_of(sov_of_sender_on_ah).free; - let wnds_in_receiver_reserve_on_ahr_after = AssetHubKusama::execute_with(|| { + let dots_in_receiver_reserve_on_ahk_after = AssetHubKusama::execute_with(|| { type Assets = ::ForeignAssets; >::balance( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + dot_at_kusama_parachains.clone().try_into().unwrap(), &sov_of_receiver_on_ah, ) }); - let rocs_in_receiver_reserve_on_ahr_after = + let ksms_in_receiver_reserve_on_ahk_after = ::account_data_of(sov_of_receiver_on_ah).free; - let receiver_rocs_after = PenpalB::execute_with(|| { + let receiver_ksms_after = PenpalB::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(roc_location, &receiver) + >::balance(ksm_location, &receiver) }); - let receiver_wnds_after = PenpalB::execute_with(|| { + let receiver_dots_after = PenpalB::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(wnd_at_rococo_parachains, &receiver) + >::balance(dot_at_kusama_parachains, &receiver) }); // Sender's balance is reduced by amount sent plus delivery fees - assert!(sender_rocs_after < sender_rocs_before - roc_to_send); - assert_eq!(sender_wnds_after, sender_wnds_before - wnd_to_send); + assert!(sender_ksms_after < sender_ksms_before - ksm_to_send); + assert_eq!(sender_dots_after, sender_dots_before - dot_to_send); // Sovereign accounts on reserve are changed accordingly assert_eq!( - rocs_in_sender_reserve_on_ahr_after, - rocs_in_sender_reserve_on_ahr_before - roc_to_send + ksms_in_sender_reserve_on_ahk_after, + ksms_in_sender_reserve_on_ahk_before - ksm_to_send ); assert_eq!( - wnds_in_sender_reserve_on_ahr_after, - wnds_in_sender_reserve_on_ahr_before - wnd_to_send + dots_in_sender_reserve_on_ahk_after, + dots_in_sender_reserve_on_ahk_before - dot_to_send ); - assert!(rocs_in_receiver_reserve_on_ahr_after > rocs_in_receiver_reserve_on_ahr_before); + assert!(ksms_in_receiver_reserve_on_ahk_after > ksms_in_receiver_reserve_on_ahk_before); assert_eq!( - wnds_in_receiver_reserve_on_ahr_after, - wnds_in_receiver_reserve_on_ahr_before + wnd_to_send + dots_in_receiver_reserve_on_ahk_after, + dots_in_receiver_reserve_on_ahk_before + dot_to_send ); // Receiver's balance is increased - assert!(receiver_rocs_after > receiver_rocs_before); - assert_eq!(receiver_wnds_after, receiver_wnds_before + wnd_to_send); + assert!(receiver_ksms_after > receiver_ksms_before); + assert_eq!(receiver_dots_after, receiver_dots_before + dot_to_send); } // ============================================================================================== diff --git a/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/reserve_transfer.rs b/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/reserve_transfer.rs index 1c5b9b6d57..11d886d0e6 100644 --- a/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/reserve_transfer.rs +++ b/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/reserve_transfer.rs @@ -38,6 +38,24 @@ fn relay_to_para_sender_assertions(t: RelayToParaTest) { ); } +fn para_to_relay_sender_assertions(t: ParaToRelayTest) { + type RuntimeEvent = ::RuntimeEvent; + PenpalA::assert_xcm_pallet_attempted_complete(None); + assert_expected_events!( + PenpalA, + vec![ + // Amount to reserve transfer is transferred to Parachain's Sovereign account + RuntimeEvent::ForeignAssets( + pallet_assets::Event::Burned { asset_id, owner, balance, .. } + ) => { + asset_id: *asset_id == KsmLocation::get(), + owner: *owner == t.sender.account_id, + balance: *balance == t.args.amount, + }, + ] + ); +} + pub fn system_para_to_para_sender_assertions(t: SystemParaToParaTest) { type RuntimeEvent = ::RuntimeEvent; AssetHubKusama::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts( @@ -97,6 +115,30 @@ fn relay_to_para_assets_receiver_assertions(t: RelayToParaTest) { ); } +fn para_to_relay_receiver_assertions(t: ParaToRelayTest) { + type RuntimeEvent = ::RuntimeEvent; + let sov_penpal_on_relay = + Kusama::sovereign_account_id_of(Kusama::child_location_of(PenpalA::para_id())); + + Kusama::assert_ump_queue_processed(true, Some(PenpalA::para_id()), None); + assert_expected_events!( + Kusama, + vec![ + // Amount to reserve transfer is withdrawn from Parachain's Sovereign account + RuntimeEvent::Balances( + pallet_balances::Event::Burned { who, amount } + ) => { + who: *who == sov_penpal_on_relay.clone(), + amount: *amount == t.args.amount, + }, + RuntimeEvent::Balances(pallet_balances::Event::Minted { .. }) => {}, + RuntimeEvent::MessageQueue( + pallet_message_queue::Event::Processed { success: true, .. } + ) => {}, + ] + ); +} + pub fn para_to_system_para_sender_assertions(t: ParaToSystemParaTest) { type RuntimeEvent = ::RuntimeEvent; @@ -177,6 +219,37 @@ fn system_para_to_para_assets_sender_assertions(t: SystemParaToParaTest) { ); } +fn para_to_system_para_assets_sender_assertions(t: ParaToSystemParaTest) { + type RuntimeEvent = ::RuntimeEvent; + let system_para_native_asset_location = KsmLocation::get(); + let reservable_asset_location = PenpalLocalReservableFromAssetHub::get(); + PenpalA::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(864_610_000, 8799))); + assert_expected_events!( + PenpalA, + vec![ + // Fees amount to reserve transfer is burned from Parachains's sender account + RuntimeEvent::ForeignAssets( + pallet_assets::Event::Burned { asset_id, owner, .. } + ) => { + asset_id: *asset_id == system_para_native_asset_location, + owner: *owner == t.sender.account_id, + }, + // Amount to reserve transfer is burned from Parachains's sender account + RuntimeEvent::ForeignAssets( + pallet_assets::Event::Burned { asset_id, owner, balance } + ) => { + asset_id: *asset_id == reservable_asset_location, + owner: *owner == t.sender.account_id, + balance: *balance == t.args.amount, + }, + // Transport fees are paid + RuntimeEvent::PolkadotXcm( + pallet_xcm::Event::FeesPaid { .. } + ) => {}, + ] + ); +} + fn system_para_to_para_assets_receiver_assertions(t: SystemParaToParaTest) { type RuntimeEvent = ::RuntimeEvent; @@ -198,6 +271,39 @@ fn system_para_to_para_assets_receiver_assertions(t: SystemParaToParaTest) { ); } +fn para_to_system_para_assets_receiver_assertions(t: ParaToSystemParaTest) { + type RuntimeEvent = ::RuntimeEvent; + let sov_penpal_on_ahr = AssetHubKusama::sovereign_account_id_of( + AssetHubKusama::sibling_location_of(PenpalA::para_id()), + ); + AssetHubKusama::assert_xcmp_queue_success(None); + assert_expected_events!( + AssetHubKusama, + vec![ + // Amount to reserve transfer is burned from Parachain's Sovereign account + RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => { + asset_id: *asset_id == RESERVABLE_ASSET_ID, + owner: *owner == sov_penpal_on_ahr, + balance: *balance == t.args.amount, + }, + // Fee amount is burned from Parachain's Sovereign account + RuntimeEvent::Balances(pallet_balances::Event::Burned { who, .. }) => { + who: *who == sov_penpal_on_ahr, + }, + // Amount to reserve transfer is issued for beneficiary + RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, owner, amount }) => { + asset_id: *asset_id == RESERVABLE_ASSET_ID, + owner: *owner == t.receiver.account_id, + amount: *amount == t.args.amount, + }, + // Remaining fee amount is minted for for beneficiary + RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. }) => { + who: *who == t.receiver.account_id, + }, + ] + ); +} + pub fn para_to_para_through_hop_sender_assertions(t: Test) { type RuntimeEvent = ::RuntimeEvent; @@ -279,6 +385,17 @@ fn relay_to_para_reserve_transfer_assets(t: RelayToParaTest) -> DispatchResult { ) } +fn para_to_relay_reserve_transfer_assets(t: ParaToRelayTest) -> DispatchResult { + ::PolkadotXcm::limited_reserve_transfer_assets( + t.signed_origin, + bx!(t.args.dest.into()), + bx!(t.args.beneficiary.into()), + bx!(t.args.assets.into()), + t.args.fee_asset_item, + t.args.weight_limit, + ) +} + fn system_para_to_para_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult { ::PolkadotXcm::limited_reserve_transfer_assets( t.signed_origin, @@ -314,9 +431,9 @@ fn para_to_para_through_relay_limited_reserve_transfer_assets( ) } -/// Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work +/// Reserve Transfers of KSM from Relay Chain to the Asset Hub shouldn't work #[test] -fn reserve_transfer_native_asset_from_relay_to_system_para_fails() { +fn reserve_transfer_ksm_from_relay_to_asset_hub_fails() { let signed_origin = ::RuntimeOrigin::signed(KusamaSender::get()); let destination = Kusama::child_location_of(AssetHubKusama::para_id()); let beneficiary: Location = @@ -346,10 +463,10 @@ fn reserve_transfer_native_asset_from_relay_to_system_para_fails() { }); } -/// Reserve Transfers of native asset from System Parachain to Relay Chain shouldn't work +/// Reserve Transfers of KSM from Asset Hub to Relay Chain shouldn't work #[test] -fn reserve_transfer_native_asset_from_system_para_to_relay_fails() { - // Init values for System Parachain +fn reserve_transfer_ksm_from_asset_hub_to_relay_fails() { + // Init values for Asset Hub let signed_origin = ::RuntimeOrigin::signed(AssetHubKusamaSender::get()); let destination = AssetHubKusama::parent_location(); @@ -383,9 +500,9 @@ fn reserve_transfer_native_asset_from_system_para_to_relay_fails() { }); } -/// Reserve Transfers of native asset from Relay to Parachain should work +/// Reserve Transfers of KSM from Relay to Parachain should work #[test] -fn reserve_transfer_native_asset_from_relay_to_para() { +fn reserve_transfer_ksm_from_relay_to_para() { // Init values for Relay let destination = Kusama::child_location_of(PenpalA::para_id()); let sender = KusamaSender::get(); @@ -433,10 +550,82 @@ fn reserve_transfer_native_asset_from_relay_to_para() { assert!(receiver_assets_after < receiver_assets_before + amount_to_send); } -/// Reserve Transfers of native asset from System Parachain to Parachain should work +/// Reserve Transfers of KSM from Parachain to Relay should work +#[test] +fn reserve_transfer_ksm_from_para_to_relay() { + // Init values for Parachain + let destination = PenpalA::parent_location(); + let sender = PenpalASender::get(); + let amount_to_send: Balance = KUSAMA_ED * 1000; + let assets: Assets = (Parent, amount_to_send).into(); + let asset_owner = PenpalAssetOwner::get(); + let relay_native_asset_location = KsmLocation::get(); + + // fund Parachain's sender account + PenpalA::mint_foreign_asset( + ::RuntimeOrigin::signed(asset_owner), + relay_native_asset_location.clone(), + sender.clone(), + amount_to_send * 2, + ); + + // Init values for Relay + let receiver = KusamaReceiver::get(); + let penpal_location_as_seen_by_relay = Kusama::child_location_of(PenpalA::para_id()); + let sov_penpal_on_relay = Kusama::sovereign_account_id_of(penpal_location_as_seen_by_relay); + + // fund Parachain's SA on Relay with the native tokens held in reserve + Kusama::fund_accounts(vec![(sov_penpal_on_relay, amount_to_send * 2)]); + + // Init Test + let test_args = TestContext { + sender: sender.clone(), + receiver: receiver.clone(), + args: TestArgs::new_para( + destination.clone(), + receiver, + amount_to_send, + assets.clone(), + None, + 0, + ), + }; + let mut test = ParaToRelayTest::new(test_args); + + // Query initial balances + let sender_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location.clone(), &sender) + }); + let receiver_balance_before = test.receiver.balance; + + // Set assertions and dispatchables + test.set_assertion::(para_to_relay_sender_assertions); + test.set_assertion::(para_to_relay_receiver_assertions); + test.set_dispatchable::(para_to_relay_reserve_transfer_assets); + test.assert(); + + // Query final balances + let sender_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location, &sender) + }); + let receiver_balance_after = test.receiver.balance; + + // Sender's balance is reduced by amount sent plus delivery fees + assert!(sender_assets_after < sender_assets_before - amount_to_send); + // Receiver's asset balance is increased + assert!(receiver_balance_after > receiver_balance_before); + // Receiver's asset balance increased by `amount_to_send - delivery_fees - bought_execution`; + // `delivery_fees` might be paid from transfer or JIT, also `bought_execution` is unknown but + // should be non-zero + assert!(receiver_balance_after < receiver_balance_before + amount_to_send); +} + +/// Reserve Transfers of KSM from Asset Hub to Parachain should work #[test] -fn reserve_transfer_native_asset_from_system_para_to_para() { - // Init values for System Parachain +fn reserve_transfer_ksm_from_asset_hub_to_para() { + // Init values for Asset Hub let destination = AssetHubKusama::sibling_location_of(PenpalA::para_id()); let sender = AssetHubKusamaSender::get(); let amount_to_send: Balance = ASSET_HUB_KUSAMA_ED * 10000; @@ -491,9 +680,9 @@ fn reserve_transfer_native_asset_from_system_para_to_para() { assert!(receiver_assets_after < receiver_assets_before + amount_to_send); } -/// Reserve Transfers of native asset from Parachain to System Parachain should work +/// Reserve Transfers of KSM from Parachain to Asset Hub should work #[test] -fn reserve_transfer_native_asset_from_para_to_system_para() { +fn reserve_transfer_ksm_from_para_to_asset_hub() { // Init values for Parachain let destination = PenpalA::sibling_location_of(AssetHubKusama::para_id()); let sender = PenpalASender::get(); @@ -510,12 +699,12 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { amount_to_send * 2, ); - // Init values for System Parachain + // Init values for Asset Hub let receiver = AssetHubKusamaReceiver::get(); let penpal_location_as_seen_by_ahr = AssetHubKusama::sibling_location_of(PenpalA::para_id()); let sov_penpal_on_ahr = AssetHubKusama::sovereign_account_id_of(penpal_location_as_seen_by_ahr); - // fund Parachain's SA on System Parachain with the native tokens held in reserve + // fund Parachain's SA on Asset Hub with the native tokens held in reserve AssetHubKusama::fund_accounts(vec![(sov_penpal_on_ahr, amount_to_send * 2)]); // Init Test @@ -563,11 +752,10 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { assert!(receiver_balance_after < receiver_balance_before + amount_to_send); } -/// Reserve Transfers of a local asset and native asset from System Parachain to Parachain should -/// work +/// Reserve Transfers of a local asset and KSM from Asset Hub to Parachain should work #[test] -fn reserve_transfer_assets_from_system_para_to_para() { - // Init values for System Parachain +fn reserve_transfer_multiple_assets_from_asset_hub_to_para() { + // Init values for Asset Hub let destination = AssetHubKusama::sibling_location_of(PenpalA::para_id()); let sov_penpal_on_ahr = AssetHubKusama::sovereign_account_id_of(destination.clone()); let sender = AssetHubKusamaSender::get(); @@ -678,10 +866,131 @@ fn reserve_transfer_assets_from_system_para_to_para() { ); } -/// Reserve Transfers of native asset from Parachain to Parachain (through Relay reserve) should -/// work +/// Reserve Transfers of a random asset and KSM from Parachain to Asset Hub should work +#[test] +fn reserve_transfer_multiple_assets_from_para_to_asset_hub() { + // Init values for Parachain + let destination = PenpalA::sibling_location_of(AssetHubKusama::para_id()); + let sender = PenpalASender::get(); + let fee_amount_to_send = ASSET_HUB_KUSAMA_ED * 10000; + let asset_amount_to_send = ASSET_HUB_KUSAMA_ED * 10000; + let penpal_asset_owner = PenpalAssetOwner::get(); + let penpal_asset_owner_signer = ::RuntimeOrigin::signed(penpal_asset_owner); + let asset_location_on_penpal = PenpalLocalReservableFromAssetHub::get(); + let system_asset_location_on_penpal = KsmLocation::get(); + let assets: Assets = vec![ + (Parent, fee_amount_to_send).into(), + (asset_location_on_penpal.clone(), asset_amount_to_send).into(), + ] + .into(); + let fee_asset_index = assets + .inner() + .iter() + .position(|r| r == &(Parent, fee_amount_to_send).into()) + .unwrap() as u32; + // Fund Parachain's sender account with some foreign assets + PenpalA::mint_foreign_asset( + penpal_asset_owner_signer.clone(), + asset_location_on_penpal.clone(), + sender.clone(), + asset_amount_to_send * 2, + ); + // Fund Parachain's sender account with some system assets + PenpalA::mint_foreign_asset( + penpal_asset_owner_signer, + system_asset_location_on_penpal.clone(), + sender.clone(), + fee_amount_to_send * 2, + ); + + // Init values for Asset Hub + let receiver = AssetHubKusamaReceiver::get(); + let penpal_location_as_seen_by_ahr = AssetHubKusama::sibling_location_of(PenpalA::para_id()); + let sov_penpal_on_ahr = AssetHubKusama::sovereign_account_id_of(penpal_location_as_seen_by_ahr); + let ah_asset_owner = AssetHubKusamaAssetOwner::get(); + let ah_asset_owner_signer = ::RuntimeOrigin::signed(ah_asset_owner); + + // Fund SA-of-Penpal-on-AHR to be able to pay for the fees. + AssetHubKusama::fund_accounts(vec![( + sov_penpal_on_ahr.clone(), + ASSET_HUB_KUSAMA_ED * 10000000, + )]); + // Fund SA-of-Penpal-on-AHR to be able to pay for the sent amount. + AssetHubKusama::mint_asset( + ah_asset_owner_signer, + RESERVABLE_ASSET_ID, + sov_penpal_on_ahr, + asset_amount_to_send * 2, + ); + + // Init Test + let para_test_args = TestContext { + sender: sender.clone(), + receiver: receiver.clone(), + args: TestArgs::new_para( + destination, + receiver.clone(), + asset_amount_to_send, + assets, + None, + fee_asset_index, + ), + }; + let mut test = ParaToSystemParaTest::new(para_test_args); + + // Query initial balances + let sender_system_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_asset_location_on_penpal.clone(), &sender) + }); + let sender_foreign_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(asset_location_on_penpal.clone(), &sender) + }); + let receiver_balance_before = test.receiver.balance; + let receiver_assets_before = AssetHubKusama::execute_with(|| { + type Assets = ::Assets; + >::balance(RESERVABLE_ASSET_ID, &receiver) + }); + + // Set assertions and dispatchables + test.set_assertion::(para_to_system_para_assets_sender_assertions); + test.set_assertion::(para_to_system_para_assets_receiver_assertions); + test.set_dispatchable::(para_to_system_para_reserve_transfer_assets); + test.assert(); + + // Query final balances + let sender_system_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_asset_location_on_penpal, &sender) + }); + let sender_foreign_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(asset_location_on_penpal, &sender) + }); + let receiver_balance_after = test.receiver.balance; + let receiver_assets_after = AssetHubKusama::execute_with(|| { + type Assets = ::Assets; + >::balance(RESERVABLE_ASSET_ID, &receiver) + }); + // Sender's system asset balance is reduced + assert!(sender_system_assets_after < sender_system_assets_before); + // Receiver's balance is increased + assert!(receiver_balance_after > receiver_balance_before); + // Receiver's balance increased by `amount_to_send - delivery_fees - bought_execution`; + // `delivery_fees` might be paid from transfer or JIT, also `bought_execution` is unknown but + // should be non-zero + assert!(receiver_balance_after < receiver_balance_before + fee_amount_to_send); + + // Sender's asset balance is reduced by exact amount + assert_eq!(sender_foreign_assets_before - asset_amount_to_send, sender_foreign_assets_after); + // Receiver's foreign asset balance is increased by exact amount + assert_eq!(receiver_assets_after, receiver_assets_before + asset_amount_to_send); +} + +/// Reserve Transfers of KSM from Parachain to Parachain (through Relay reserve) should work #[test] -fn reserve_transfer_native_asset_from_para_to_para_through_relay() { +fn reserve_transfer_ksm_from_para_to_para_through_relay() { // Init values for Parachain Origin let destination = PenpalA::sibling_location_of(PenpalB::para_id()); let sender = PenpalASender::get(); diff --git a/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/send.rs b/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/send.rs index 2188318aa7..e4f1051177 100644 --- a/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/send.rs +++ b/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/send.rs @@ -18,7 +18,7 @@ use crate::*; /// Relay Chain should be able to execute `Transact` instructions in System Parachain /// when `OriginKind::Superuser`. #[test] -fn send_transact_as_superuser_from_relay_to_system_para_works() { +fn send_transact_as_superuser_from_relay_to_asset_hub_works() { AssetHubKusama::force_create_asset_from_relay_as_root( ASSET_ID, ASSET_MIN_BALANCE, @@ -28,15 +28,97 @@ fn send_transact_as_superuser_from_relay_to_system_para_works() { ) } -/// Parachain should be able to send XCM paying its fee with sufficient asset -/// in the System Parachain +/// We tests two things here: +/// - Parachain should be able to send XCM paying its fee at Asset Hub using KSM +/// - Parachain should be able to create a new Foreign Asset at Asset Hub #[test] -fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() { +fn send_xcm_from_para_to_asset_hub_paying_fee_with_system_asset() { let para_sovereign_account = AssetHubKusama::sovereign_account_id_of( AssetHubKusama::sibling_location_of(PenpalA::para_id()), ); + let asset_location_on_penpal = v3::Location::new( + 0, + [ + v3::Junction::PalletInstance(ASSETS_PALLET_ID), + v3::Junction::GeneralIndex(ASSET_ID.into()), + ], + ); + let foreign_asset_at_asset_hub = + v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())]) + .appended_with(asset_location_on_penpal) + .unwrap(); + + // Encoded `create_asset` call to be executed in AssetHub + let call = AssetHubKusama::create_foreign_asset_call( + foreign_asset_at_asset_hub, + ASSET_MIN_BALANCE, + para_sovereign_account.clone(), + ); + + let origin_kind = OriginKind::Xcm; + let fee_amount = ASSET_HUB_KUSAMA_ED * 1000000; + let system_asset = (Parent, fee_amount).into(); + + let root_origin = ::RuntimeOrigin::root(); + let system_para_destination = PenpalA::sibling_location_of(AssetHubKusama::para_id()).into(); + let xcm = xcm_transact_paid_execution( + call, + origin_kind, + system_asset, + para_sovereign_account.clone(), + ); + + // SA-of-Penpal-on-AHK needs to have balance to pay for fees and asset creation deposit + AssetHubKusama::fund_accounts(vec![( + para_sovereign_account.clone(), + ASSET_HUB_KUSAMA_ED * 10000000000, + )]); + + PenpalA::execute_with(|| { + assert_ok!(::PolkadotXcm::send( + root_origin, + bx!(system_para_destination), + bx!(xcm), + )); - // Force create and mint assets for Parachain's sovereign account + PenpalA::assert_xcm_pallet_sent(); + }); + + AssetHubKusama::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + AssetHubKusama::assert_xcmp_queue_success(None); + assert_expected_events!( + AssetHubKusama, + vec![ + // Burned the fee + RuntimeEvent::Balances(pallet_balances::Event::Burned { who, amount }) => { + who: *who == para_sovereign_account, + amount: *amount == fee_amount, + }, + // Foreign Asset created + RuntimeEvent::ForeignAssets(pallet_assets::Event::Created { asset_id, creator, owner }) => { + asset_id: *asset_id == foreign_asset_at_asset_hub, + creator: *creator == para_sovereign_account.clone(), + owner: *owner == para_sovereign_account, + }, + ] + ); + + type ForeignAssets = ::ForeignAssets; + assert!(ForeignAssets::asset_exists(foreign_asset_at_asset_hub)); + }); +} + +/// We tests two things here: +/// - Parachain should be able to send XCM paying its fee at Asset Hub using sufficient asset +/// - Parachain should be able to create a new Asset at Asset Hub +#[test] +fn send_xcm_from_para_to_asset_hub_paying_fee_with_sufficient_asset() { + let para_sovereign_account = AssetHubKusama::sovereign_account_id_of( + AssetHubKusama::sibling_location_of(PenpalA::para_id()), + ); + + // Force create and mint sufficient assets for Parachain's sovereign account AssetHubKusama::force_create_and_mint_asset( ASSET_ID, ASSET_MIN_BALANCE, @@ -46,28 +128,30 @@ fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() { ASSET_MIN_BALANCE * 1000000000, ); - // We just need a call that can pass the `SafeCallFilter` - // Call values are not relevant - let call = AssetHubKusama::force_create_asset_call( - ASSET_ID, - para_sovereign_account.clone(), - true, + // Just a different `asset_id`` that does not exist yet + let new_asset_id = ASSET_ID + 1; + + // Encoded `create_asset` call to be executed in AssetHub + let call = AssetHubKusama::create_asset_call( + new_asset_id, ASSET_MIN_BALANCE, + para_sovereign_account.clone(), ); let origin_kind = OriginKind::SovereignAccount; let fee_amount = ASSET_MIN_BALANCE * 1000000; - let native_asset = + let asset = ([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], fee_amount).into(); let root_origin = ::RuntimeOrigin::root(); let system_para_destination = PenpalA::sibling_location_of(AssetHubKusama::para_id()).into(); - let xcm = xcm_transact_paid_execution( - call, - origin_kind, - native_asset, + let xcm = xcm_transact_paid_execution(call, origin_kind, asset, para_sovereign_account.clone()); + + // SA-of-Penpal-on-AHK needs to have balance to pay for asset creation deposit + AssetHubKusama::fund_accounts(vec![( para_sovereign_account.clone(), - ); + ASSET_HUB_KUSAMA_ED * 10000000000, + )]); PenpalA::execute_with(|| { assert_ok!(::PolkadotXcm::send( @@ -81,22 +165,21 @@ fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() { AssetHubKusama::execute_with(|| { type RuntimeEvent = ::RuntimeEvent; - - AssetHubKusama::assert_xcmp_queue_success(Some(Weight::from_parts( - 15_594_564_000, - 562_893, - ))); - + AssetHubKusama::assert_xcmp_queue_success(None); assert_expected_events!( AssetHubKusama, vec![ + // Burned the fee RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => { asset_id: *asset_id == ASSET_ID, owner: *owner == para_sovereign_account, balance: *balance == fee_amount, }, - RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, .. }) => { - asset_id: *asset_id == ASSET_ID, + // Asset created + RuntimeEvent::Assets(pallet_assets::Event::Created { asset_id, creator, owner }) => { + asset_id: *asset_id == new_asset_id, + creator: *creator == para_sovereign_account.clone(), + owner: *owner == para_sovereign_account, }, ] ); diff --git a/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/teleport.rs b/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/teleport.rs index e24c443265..fefae99ab6 100644 --- a/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/teleport.rs +++ b/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/teleport.rs @@ -16,55 +16,12 @@ use crate::*; use asset_hub_kusama_runtime::xcm_config::{KsmLocation, XcmConfig as AssetHubKusamaXcmConfig}; use emulated_integration_tests_common::xcm_helpers::non_fee_asset; -use kusama_runtime::xcm_config::XcmConfig as KusamaXcmConfig; +use frame_support::traits::fungible::Mutate; use kusama_system_emulated_network::penpal_emulated_chain::LocalTeleportableToAssetHub as PenpalLocalTeleportableToAssetHub; - -fn relay_origin_assertions(t: RelayToSystemParaTest) { - type RuntimeEvent = ::RuntimeEvent; - - Kusama::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(631_531_000, 7_186))); - - assert_expected_events!( - Kusama, - vec![ - // Amount to teleport is withdrawn from Sender - RuntimeEvent::Balances(pallet_balances::Event::Burned { who, amount }) => { - who: *who == t.sender.account_id, - amount: *amount == t.args.amount, - }, - // Amount to teleport is deposited in Relay's `CheckAccount` - RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount }) => { - who: *who == ::XcmPallet::check_account(), - amount: *amount == t.args.amount, - }, - ] - ); -} - -fn relay_dest_assertions(t: SystemParaToRelayTest) { - type RuntimeEvent = ::RuntimeEvent; - - Kusama::assert_ump_queue_processed( - true, - Some(AssetHubKusama::para_id()), - Some(Weight::from_parts(307_225_000, 7_186)), - ); - - assert_expected_events!( - Kusama, - vec![ - // Amount is withdrawn from Relay Chain's `CheckAccount` - RuntimeEvent::Balances(pallet_balances::Event::Burned { who, amount }) => { - who: *who == ::XcmPallet::check_account(), - amount: *amount == t.args.amount, - }, - // Amount minus fees are deposited in Receiver's account - RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. }) => { - who: *who == t.receiver.account_id, - }, - ] - ); -} +use xcm_runtime_apis::{ + dry_run::runtime_decl_for_dry_run_api::DryRunApiV1, + fees::runtime_decl_for_xcm_payment_api::XcmPaymentApiV1, +}; fn relay_dest_assertions_fail(_t: SystemParaToRelayTest) { Kusama::assert_ump_queue_processed( @@ -96,22 +53,6 @@ fn para_origin_assertions(t: SystemParaToRelayTest) { ); } -fn para_dest_assertions(t: RelayToSystemParaTest) { - type RuntimeEvent = ::RuntimeEvent; - - AssetHubKusama::assert_dmp_queue_complete(Some(Weight::from_parts(157_718_000, 3593))); - - assert_expected_events!( - AssetHubKusama, - vec![ - // Amount minus fees are deposited in Receiver's account - RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. }) => { - who: *who == t.receiver.account_id, - }, - ] - ); -} - fn penpal_to_ah_foreign_assets_sender_assertions(t: ParaToSystemParaTest) { type RuntimeEvent = ::RuntimeEvent; let system_para_native_asset_location = KsmLocation::get(); @@ -234,17 +175,6 @@ fn ah_to_penpal_foreign_assets_receiver_assertions(t: SystemParaToParaTest) { ); } -fn relay_limited_teleport_assets(t: RelayToSystemParaTest) -> DispatchResult { - ::XcmPallet::limited_teleport_assets( - t.signed_origin, - bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), - bx!(t.args.assets.into()), - t.args.fee_asset_item, - t.args.weight_limit, - ) -} - fn system_para_limited_teleport_assets(t: SystemParaToRelayTest) -> DispatchResult { ::PolkadotXcm::limited_teleport_assets( t.signed_origin, @@ -278,90 +208,41 @@ fn system_para_to_para_transfer_assets(t: SystemParaToParaTest) -> DispatchResul ) } -/// Limited Teleport of native asset from Relay Chain to the System Parachain should work #[test] -fn limited_teleport_native_assets_from_relay_to_system_para_works() { - // Init values for Relay Chain - let amount_to_send: Balance = KUSAMA_ED * 1000; - let dest = Kusama::child_location_of(AssetHubKusama::para_id()); - let beneficiary_id = AssetHubKusamaReceiver::get(); - let test_args = TestContext { - sender: KusamaSender::get(), - receiver: AssetHubKusamaReceiver::get(), - args: TestArgs::new_relay(dest, beneficiary_id, amount_to_send), - }; - - let mut test = RelayToSystemParaTest::new(test_args); - - let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; - - test.set_assertion::(relay_origin_assertions); - test.set_assertion::(para_dest_assertions); - test.set_dispatchable::(relay_limited_teleport_assets); - test.assert(); - - let delivery_fees = Kusama::execute_with(|| { - xcm_helpers::teleport_assets_delivery_fees::< - ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) - }); - - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; +fn teleport_to_other_system_parachains_works() { + let amount = ASSET_HUB_KUSAMA_ED * 100; + let native_asset: Assets = (Parent, amount).into(); - // Sender's balance is reduced - assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); - // Receiver's balance is increased - assert!(receiver_balance_after > receiver_balance_before); + test_parachain_is_trusted_teleporter!( + AssetHubKusama, // Origin + AssetHubKusamaXcmConfig, // XCM Configuration + vec![BridgeHubKusama], // Destinations + (native_asset, amount) + ); } -/// Limited Teleport of native asset from System Parachain to Relay Chain -/// should work when there is enough balance in Relay Chain's `CheckAccount` #[test] -fn limited_teleport_native_assets_back_from_system_para_to_relay_works() { - // Dependency - Relay Chain's `CheckAccount` should have enough balance - limited_teleport_native_assets_from_relay_to_system_para_works(); - - // Init values for Relay Chain - let amount_to_send: Balance = ASSET_HUB_KUSAMA_ED * 1000; - let destination = AssetHubKusama::parent_location(); - let beneficiary_id = KusamaReceiver::get(); - let assets = (Parent, amount_to_send).into(); +fn teleport_from_and_to_relay() { + let amount = KUSAMA_ED * 100; + let native_asset: Assets = (Here, amount).into(); - let test_args = TestContext { - sender: AssetHubKusamaSender::get(), - receiver: KusamaReceiver::get(), - args: TestArgs::new_para(destination, beneficiary_id, amount_to_send, assets, None, 0), - }; - - let mut test = SystemParaToRelayTest::new(test_args); - - let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; - - test.set_assertion::(para_origin_assertions); - test.set_assertion::(relay_dest_assertions); - test.set_dispatchable::(system_para_limited_teleport_assets); - test.assert(); - - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - - let delivery_fees = AssetHubKusama::execute_with(|| { - xcm_helpers::teleport_assets_delivery_fees::< - ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) - }); + test_relay_is_trusted_teleporter!( + Kusama, + KusamaXcmConfig, + vec![AssetHubKusama], + (native_asset, amount) + ); - // Sender's balance is reduced - assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); - // Receiver's balance is increased - assert!(receiver_balance_after > receiver_balance_before); + test_parachain_is_trusted_teleporter_for_relay!( + AssetHubKusama, + AssetHubKusamaXcmConfig, + Kusama, + amount + ); } /// Limited Teleport of native asset from System Parachain to Relay Chain -/// should't work when there is not enough balance in Relay Chain's `CheckAccount` +/// shouldn't work when there is not enough balance in Relay Chain's `CheckAccount` #[test] fn limited_teleport_native_assets_from_system_para_to_relay_fails() { // Init values for Relay Chain @@ -401,19 +282,6 @@ fn limited_teleport_native_assets_from_system_para_to_relay_fails() { assert_eq!(receiver_balance_after, receiver_balance_before); } -#[test] -fn teleport_to_other_system_parachains_works() { - let amount = ASSET_HUB_KUSAMA_ED * 100; - let native_asset: Assets = (Parent, amount).into(); - - test_parachain_is_trusted_teleporter!( - AssetHubKusama, // Origin - AssetHubKusamaXcmConfig, // XCM Configuration - vec![BridgeHubKusama], // Destinations - (native_asset, amount) - ); -} - /// Bidirectional teleports of local Penpal assets to Asset Hub as foreign assets while paying /// fees using (reserve transferred) native asset. pub fn do_bidirectional_teleport_foreign_assets_between_para_and_asset_hub_using_xt( diff --git a/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/treasury.rs b/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/treasury.rs index 317b1a5f67..5f830b41ef 100644 --- a/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/treasury.rs +++ b/integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/treasury.rs @@ -22,7 +22,7 @@ use frame_support::{ sp_runtime::traits::Dispatchable, traits::{ fungible::Inspect, - fungibles::{Create, Inspect as FungiblesInspect, Mutate}, + fungibles::{Inspect as FungiblesInspect, Mutate}, }, }; use kusama_runtime::OriginCaller; @@ -164,8 +164,8 @@ fn spend_ksm_on_asset_hub() { #[test] fn create_and_claim_treasury_spend_in_usdt() { - const ASSET_ID: u32 = 1984; - const SPEND_AMOUNT: u128 = 1_000_000; + const USDT_ID: u32 = 1984; + const SPEND_AMOUNT: u128 = 10_000_000; // treasury location from a sibling parachain. let treasury_location: Location = Location::new(1, PalletInstance(18)); // treasury account on a sibling parachain. @@ -181,7 +181,7 @@ fn create_and_claim_treasury_spend_in_usdt() { let asset_kind = VersionedLocatableAsset::V3 { location: asset_hub_location, asset_id: v3::AssetId::Concrete( - (v3::Junction::PalletInstance(50), v3::Junction::GeneralIndex(ASSET_ID.into())).into(), + (v3::Junction::PalletInstance(50), v3::Junction::GeneralIndex(USDT_ID.into())).into(), ), }; // treasury spend beneficiary. @@ -192,16 +192,10 @@ fn create_and_claim_treasury_spend_in_usdt() { AssetHubKusama::execute_with(|| { type Assets = ::Assets; - // create an asset class and mint some assets to the treasury account. - assert_ok!(>::create( - ASSET_ID, - treasury_account.clone(), - true, - SPEND_AMOUNT / 2 - )); - assert_ok!(>::mint_into(ASSET_ID, &treasury_account, SPEND_AMOUNT * 4)); + // USDT created at genesis, mint some assets to the treasury account. + assert_ok!(>::mint_into(USDT_ID, &treasury_account, SPEND_AMOUNT * 4)); // beneficiary has zero balance. - assert_eq!(>::balance(ASSET_ID, &alice,), 0u128,); + assert_eq!(>::balance(USDT_ID, &alice,), 0u128,); }); Kusama::execute_with(|| { @@ -243,7 +237,7 @@ fn create_and_claim_treasury_spend_in_usdt() { AssetHubKusama, vec![ RuntimeEvent::Assets(pallet_assets::Event::Transferred { asset_id: id, from, to, amount }) => { - id: id == &ASSET_ID, + id: id == &USDT_ID, from: from == &treasury_account, to: to == &alice, amount: amount == &SPEND_AMOUNT, @@ -253,7 +247,7 @@ fn create_and_claim_treasury_spend_in_usdt() { ] ); // beneficiary received the assets from the treasury. - assert_eq!(>::balance(ASSET_ID, &alice,), SPEND_AMOUNT,); + assert_eq!(>::balance(USDT_ID, &alice,), SPEND_AMOUNT,); }); Kusama::execute_with(|| { diff --git a/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/lib.rs b/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/lib.rs index be401c5145..c6c84dbfc0 100644 --- a/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/lib.rs +++ b/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/lib.rs @@ -18,12 +18,14 @@ pub use codec::Encode; // Substrate pub use frame_support::{ assert_err, assert_ok, + dispatch::RawOrigin, instances::Instance2, pallet_prelude::Weight, sp_runtime::{AccountId32, DispatchError, DispatchResult, ModuleError}, traits::fungibles::Inspect, BoundedVec, }; +pub use sp_runtime::traits::Dispatchable; // Polkadot pub use xcm::{ @@ -43,6 +45,9 @@ pub use emulated_integration_tests_common::{ xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution}, PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3, }; +pub use integration_tests_helpers::{ + test_parachain_is_trusted_teleporter_for_relay, test_relay_is_trusted_teleporter, +}; pub use parachains_common::{AccountId, Balance}; pub use polkadot_runtime::xcm_config::UniversalLocation as PolkadotUniversalLocation; pub use polkadot_system_emulated_network::{ @@ -76,8 +81,8 @@ pub const ASSET_MIN_BALANCE: u128 = 1000; // `Assets` pallet index pub const ASSETS_PALLET_ID: u8 = 50; -pub type RelayToSystemParaTest = Test; pub type RelayToParaTest = Test; +pub type ParaToRelayTest = Test; pub type SystemParaToRelayTest = Test; pub type SystemParaToParaTest = Test; pub type ParaToSystemParaTest = Test; diff --git a/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/fellowship_treasury.rs b/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/fellowship_treasury.rs index 2670a1128b..9fbcba4e00 100644 --- a/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/fellowship_treasury.rs +++ b/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/fellowship_treasury.rs @@ -15,14 +15,14 @@ use crate::*; use emulated_integration_tests_common::accounts::{ALICE, BOB}; -use frame_support::traits::fungibles::{Create, Mutate}; +use frame_support::traits::fungibles::Mutate; use polkadot_runtime_common::impls::VersionedLocatableAsset; use xcm_executor::traits::ConvertLocation; #[test] -fn create_and_claim_treasury_spend() { - const ASSET_ID: u32 = 1984; - const SPEND_AMOUNT: u128 = 1_000_000; +fn create_and_claim_treasury_spend_in_usdt() { + const USDT_ID: u32 = 1984; + const SPEND_AMOUNT: u128 = 1_000_000_000; // treasury location from a sibling parachain. let treasury_location: Location = Location::new( 1, @@ -46,7 +46,7 @@ fn create_and_claim_treasury_spend() { let asset_kind = VersionedLocatableAsset::V3 { location: asset_hub_location, asset_id: v3::AssetId::Concrete( - (v3::Junction::PalletInstance(50), v3::Junction::GeneralIndex(ASSET_ID.into())).into(), + (v3::Junction::PalletInstance(50), v3::Junction::GeneralIndex(USDT_ID.into())).into(), ), }; // treasury spend beneficiary. @@ -57,16 +57,10 @@ fn create_and_claim_treasury_spend() { AssetHubPolkadot::execute_with(|| { type Assets = ::Assets; - // create an asset class and mint some assets to the treasury account. - assert_ok!(>::create( - ASSET_ID, - treasury_account.clone(), - true, - SPEND_AMOUNT / 2 - )); - assert_ok!(>::mint_into(ASSET_ID, &treasury_account, SPEND_AMOUNT * 4)); + // USDT created at genesis, mint some assets to the treasury account. + assert_ok!(>::mint_into(USDT_ID, &treasury_account, SPEND_AMOUNT * 4)); // beneficiary has zero balance. - assert_eq!(>::balance(ASSET_ID, &alice,), 0u128,); + assert_eq!(>::balance(USDT_ID, &alice,), 0u128,); }); CollectivesPolkadot::execute_with(|| { @@ -109,7 +103,7 @@ fn create_and_claim_treasury_spend() { AssetHubPolkadot, vec![ RuntimeEvent::Assets(pallet_assets::Event::Transferred { asset_id: id, from, to, amount }) => { - id: id == &ASSET_ID, + id: id == &USDT_ID, from: from == &treasury_account, to: to == &alice, amount: amount == &SPEND_AMOUNT, @@ -119,7 +113,7 @@ fn create_and_claim_treasury_spend() { ] ); // beneficiary received the assets from the treasury. - assert_eq!(>::balance(ASSET_ID, &alice,), SPEND_AMOUNT,); + assert_eq!(>::balance(USDT_ID, &alice,), SPEND_AMOUNT,); }); CollectivesPolkadot::execute_with(|| { diff --git a/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/hybrid_transfers.rs b/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/hybrid_transfers.rs index 42ce5d721c..27c0cb34b6 100644 --- a/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/hybrid_transfers.rs +++ b/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/hybrid_transfers.rs @@ -161,30 +161,29 @@ fn transfer_foreign_assets_from_asset_hub_to_para() { let native_asset_location = DotLocation::get(); let receiver = PenpalBReceiver::get(); let assets_owner = PenpalAssetOwner::get(); - // Foreign asset used: bridged WND + // Foreign asset used: bridged KSM let foreign_amount_to_send = ASSET_HUB_POLKADOT_ED * 10_000_000; - let wnd_at_rococo_parachains = - Location::new(2, [Junction::GlobalConsensus(NetworkId::Westend)]); + let ksm_at_polkadot_parachains = Location::new(2, [GlobalConsensus(Kusama)]); - // Configure destination chain to trust AH as reserve of WND + // Configure destination chain to trust AH as reserve of KSM PenpalB::execute_with(|| { assert_ok!(::System::set_storage( ::RuntimeOrigin::root(), vec![( CustomizableAssetFromSystemAssetHub::key().to_vec(), - Location::new(2, [GlobalConsensus(Westend)]).encode(), + Location::new(2, [GlobalConsensus(Kusama)]).encode(), )], )); }); PenpalB::force_create_foreign_asset( - wnd_at_rococo_parachains.clone(), + ksm_at_polkadot_parachains.clone(), assets_owner.clone(), false, ASSET_MIN_BALANCE, vec![], ); AssetHubPolkadot::force_create_foreign_asset( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + ksm_at_polkadot_parachains.clone().try_into().unwrap(), assets_owner.clone(), false, ASSET_MIN_BALANCE, @@ -192,7 +191,7 @@ fn transfer_foreign_assets_from_asset_hub_to_para() { ); AssetHubPolkadot::mint_foreign_asset( ::RuntimeOrigin::signed(assets_owner), - wnd_at_rococo_parachains.clone().try_into().unwrap(), + ksm_at_polkadot_parachains.clone().try_into().unwrap(), sender.clone(), foreign_amount_to_send * 2, ); @@ -200,7 +199,7 @@ fn transfer_foreign_assets_from_asset_hub_to_para() { // Assets to send let assets: Vec = vec![ (Parent, native_amount_to_send).into(), - (wnd_at_rococo_parachains.clone(), foreign_amount_to_send).into(), + (ksm_at_polkadot_parachains.clone(), foreign_amount_to_send).into(), ]; let fee_asset_id = AssetId(Parent.into()); let fee_asset_item = assets.iter().position(|a| a.id == fee_asset_id).unwrap() as u32; @@ -222,10 +221,10 @@ fn transfer_foreign_assets_from_asset_hub_to_para() { // Query initial balances let sender_balance_before = test.sender.balance; - let sender_wnds_before = AssetHubPolkadot::execute_with(|| { + let sender_ksm_before = AssetHubPolkadot::execute_with(|| { type ForeignAssets = ::ForeignAssets; >::balance( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + ksm_at_polkadot_parachains.clone().try_into().unwrap(), &sender, ) }); @@ -233,9 +232,9 @@ fn transfer_foreign_assets_from_asset_hub_to_para() { type ForeignAssets = ::ForeignAssets; >::balance(native_asset_location.clone(), &receiver) }); - let receiver_wnds_before = PenpalB::execute_with(|| { + let receiver_ksm_before = PenpalB::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(wnd_at_rococo_parachains.clone(), &receiver) + >::balance(ksm_at_polkadot_parachains.clone(), &receiver) }); // Set assertions and dispatchables @@ -246,10 +245,10 @@ fn transfer_foreign_assets_from_asset_hub_to_para() { // Query final balances let sender_balance_after = test.sender.balance; - let sender_wnds_after = AssetHubPolkadot::execute_with(|| { + let sender_ksm_after = AssetHubPolkadot::execute_with(|| { type ForeignAssets = ::ForeignAssets; >::balance( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + ksm_at_polkadot_parachains.clone().try_into().unwrap(), &sender, ) }); @@ -257,15 +256,15 @@ fn transfer_foreign_assets_from_asset_hub_to_para() { type ForeignAssets = ::ForeignAssets; >::balance(native_asset_location, &receiver) }); - let receiver_wnds_after = PenpalB::execute_with(|| { + let receiver_ksm_after = PenpalB::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(wnd_at_rococo_parachains, &receiver) + >::balance(ksm_at_polkadot_parachains, &receiver) }); // Sender's balance is reduced by amount sent plus delivery fees assert!(sender_balance_after < sender_balance_before - native_amount_to_send); // Sender's balance is reduced by foreign amount sent - assert_eq!(sender_wnds_after, sender_wnds_before - foreign_amount_to_send); + assert_eq!(sender_ksm_after, sender_ksm_before - foreign_amount_to_send); // Receiver's assets is increased assert!(receiver_assets_after > receiver_assets_before); // Receiver's assets increased by `amount_to_send - delivery_fees - bought_execution`; @@ -273,7 +272,7 @@ fn transfer_foreign_assets_from_asset_hub_to_para() { // should be non-zero assert!(receiver_assets_after < receiver_assets_before + native_amount_to_send); // Receiver's balance is increased by foreign amount sent - assert_eq!(receiver_wnds_after, receiver_wnds_before + foreign_amount_to_send); + assert_eq!(receiver_ksm_after, receiver_ksm_before + foreign_amount_to_send); } /// Reserve Transfers of native asset from Parachain to System Parachain should work @@ -291,30 +290,29 @@ fn transfer_foreign_assets_from_para_to_asset_hub() { let native_asset_location = DotLocation::get(); let assets_owner = PenpalAssetOwner::get(); - // Foreign asset used: bridged WND + // Foreign asset used: bridged KSM let foreign_amount_to_send = ASSET_HUB_POLKADOT_ED * 10_000_000; - let wnd_at_rococo_parachains = - Location::new(2, [Junction::GlobalConsensus(NetworkId::Westend)]); + let ksm_at_polkadot_parachains = Location::new(2, [GlobalConsensus(Kusama)]); - // Configure destination chain to trust AH as reserve of WND + // Configure destination chain to trust AH as reserve of KSM PenpalB::execute_with(|| { assert_ok!(::System::set_storage( ::RuntimeOrigin::root(), vec![( CustomizableAssetFromSystemAssetHub::key().to_vec(), - Location::new(2, [GlobalConsensus(Westend)]).encode(), + Location::new(2, [GlobalConsensus(Kusama)]).encode(), )], )); }); PenpalB::force_create_foreign_asset( - wnd_at_rococo_parachains.clone(), + ksm_at_polkadot_parachains.clone(), assets_owner.clone(), false, ASSET_MIN_BALANCE, vec![], ); AssetHubPolkadot::force_create_foreign_asset( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + ksm_at_polkadot_parachains.clone().try_into().unwrap(), assets_owner.clone(), false, ASSET_MIN_BALANCE, @@ -330,30 +328,30 @@ fn transfer_foreign_assets_from_para_to_asset_hub() { ); PenpalB::mint_foreign_asset( ::RuntimeOrigin::signed(assets_owner.clone()), - wnd_at_rococo_parachains.clone(), + ksm_at_polkadot_parachains.clone(), sender.clone(), foreign_amount_to_send * 2, ); // Init values for System Parachain let receiver = AssetHubPolkadotReceiver::get(); - let penpal_location_as_seen_by_ahr = AssetHubPolkadot::sibling_location_of(PenpalB::para_id()); - let sov_penpal_on_ahr = - AssetHubPolkadot::sovereign_account_id_of(penpal_location_as_seen_by_ahr); + let penpal_location_as_seen_by_ahp = AssetHubPolkadot::sibling_location_of(PenpalB::para_id()); + let sov_penpal_on_ahp = + AssetHubPolkadot::sovereign_account_id_of(penpal_location_as_seen_by_ahp); // fund Parachain's SA on AssetHub with the assets held in reserve - AssetHubPolkadot::fund_accounts(vec![(sov_penpal_on_ahr.clone(), native_amount_to_send * 2)]); + AssetHubPolkadot::fund_accounts(vec![(sov_penpal_on_ahp.clone(), native_amount_to_send * 2)]); AssetHubPolkadot::mint_foreign_asset( ::RuntimeOrigin::signed(assets_owner), - wnd_at_rococo_parachains.clone().try_into().unwrap(), - sov_penpal_on_ahr, + ksm_at_polkadot_parachains.clone().try_into().unwrap(), + sov_penpal_on_ahp, foreign_amount_to_send * 2, ); // Assets to send let assets: Vec = vec![ (Parent, native_amount_to_send).into(), - (wnd_at_rococo_parachains.clone(), foreign_amount_to_send).into(), + (ksm_at_polkadot_parachains.clone(), foreign_amount_to_send).into(), ]; let fee_asset_id = AssetId(Parent.into()); let fee_asset_item = assets.iter().position(|a| a.id == fee_asset_id).unwrap() as u32; @@ -378,15 +376,15 @@ fn transfer_foreign_assets_from_para_to_asset_hub() { type ForeignAssets = ::ForeignAssets; >::balance(native_asset_location.clone(), &sender) }); - let sender_wnds_before = PenpalB::execute_with(|| { + let sender_ksm_before = PenpalB::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(wnd_at_rococo_parachains.clone(), &sender) + >::balance(ksm_at_polkadot_parachains.clone(), &sender) }); let receiver_native_before = test.receiver.balance; - let receiver_wnds_before = AssetHubPolkadot::execute_with(|| { + let receiver_ksm_before = AssetHubPolkadot::execute_with(|| { type ForeignAssets = ::ForeignAssets; >::balance( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + ksm_at_polkadot_parachains.clone().try_into().unwrap(), &receiver, ) }); @@ -402,15 +400,15 @@ fn transfer_foreign_assets_from_para_to_asset_hub() { type ForeignAssets = ::ForeignAssets; >::balance(native_asset_location, &sender) }); - let sender_wnds_after = PenpalB::execute_with(|| { + let sender_ksm_after = PenpalB::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(wnd_at_rococo_parachains.clone(), &sender) + >::balance(ksm_at_polkadot_parachains.clone(), &sender) }); let receiver_native_after = test.receiver.balance; - let receiver_wnds_after = AssetHubPolkadot::execute_with(|| { + let receiver_ksm_after = AssetHubPolkadot::execute_with(|| { type ForeignAssets = ::ForeignAssets; >::balance( - wnd_at_rococo_parachains.try_into().unwrap(), + ksm_at_polkadot_parachains.try_into().unwrap(), &receiver, ) }); @@ -418,7 +416,7 @@ fn transfer_foreign_assets_from_para_to_asset_hub() { // Sender's balance is reduced by amount sent plus delivery fees assert!(sender_native_after < sender_native_before - native_amount_to_send); // Sender's balance is reduced by foreign amount sent - assert_eq!(sender_wnds_after, sender_wnds_before - foreign_amount_to_send); + assert_eq!(sender_ksm_after, sender_ksm_before - foreign_amount_to_send); // Receiver's balance is increased assert!(receiver_native_after > receiver_native_before); // Receiver's balance increased by `amount_to_send - delivery_fees - bought_execution`; @@ -426,7 +424,7 @@ fn transfer_foreign_assets_from_para_to_asset_hub() { // should be non-zero assert!(receiver_native_after < receiver_native_before + native_amount_to_send); // Receiver's balance is increased by foreign amount sent - assert_eq!(receiver_wnds_after, receiver_wnds_before + foreign_amount_to_send); + assert_eq!(receiver_ksm_after, receiver_ksm_before + foreign_amount_to_send); } // ============================================================================== @@ -439,45 +437,44 @@ fn transfer_foreign_assets_from_para_to_para_through_asset_hub() { // Init values for Parachain Origin let destination = PenpalB::sibling_location_of(PenpalA::para_id()); let sender = PenpalBSender::get(); - let roc_to_send: Balance = POLKADOT_ED * 10000; + let dot_to_send: Balance = POLKADOT_ED * 10000; let assets_owner = PenpalAssetOwner::get(); - let roc_location = DotLocation::get(); + let dot_location = DotLocation::get(); let sender_as_seen_by_ah = AssetHubPolkadot::sibling_location_of(PenpalB::para_id()); let sov_of_sender_on_ah = AssetHubPolkadot::sovereign_account_id_of(sender_as_seen_by_ah); let receiver_as_seen_by_ah = AssetHubPolkadot::sibling_location_of(PenpalA::para_id()); let sov_of_receiver_on_ah = AssetHubPolkadot::sovereign_account_id_of(receiver_as_seen_by_ah); - let wnd_to_send = ASSET_HUB_POLKADOT_ED * 10_000_000; + let ksm_to_send = ASSET_HUB_POLKADOT_ED * 10_000_000; - // Configure destination chain to trust AH as reserve of WND + // Configure destination chain to trust AH as reserve of KSM PenpalA::execute_with(|| { assert_ok!(::System::set_storage( ::RuntimeOrigin::root(), vec![( CustomizableAssetFromSystemAssetHub::key().to_vec(), - Location::new(2, [GlobalConsensus(Westend)]).encode(), + Location::new(2, [GlobalConsensus(Kusama)]).encode(), )], )); }); - // Register WND as foreign asset and transfer it around the Polkadot ecosystem - let wnd_at_rococo_parachains = - Location::new(2, [Junction::GlobalConsensus(NetworkId::Westend)]); + // Register KSM as foreign asset and transfer it around the Polkadot ecosystem + let ksm_at_polkadot_parachains = Location::new(2, [GlobalConsensus(Kusama)]); AssetHubPolkadot::force_create_foreign_asset( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + ksm_at_polkadot_parachains.clone().try_into().unwrap(), assets_owner.clone(), false, ASSET_MIN_BALANCE, vec![], ); PenpalB::force_create_foreign_asset( - wnd_at_rococo_parachains.clone(), + ksm_at_polkadot_parachains.clone(), assets_owner.clone(), false, ASSET_MIN_BALANCE, vec![], ); PenpalA::force_create_foreign_asset( - wnd_at_rococo_parachains.clone(), + ksm_at_polkadot_parachains.clone(), assets_owner.clone(), false, ASSET_MIN_BALANCE, @@ -487,23 +484,23 @@ fn transfer_foreign_assets_from_para_to_para_through_asset_hub() { // fund Parachain's sender account PenpalB::mint_foreign_asset( ::RuntimeOrigin::signed(assets_owner.clone()), - roc_location.clone(), + dot_location.clone(), sender.clone(), - roc_to_send * 2, + dot_to_send * 2, ); PenpalB::mint_foreign_asset( ::RuntimeOrigin::signed(assets_owner.clone()), - wnd_at_rococo_parachains.clone(), + ksm_at_polkadot_parachains.clone(), sender.clone(), - wnd_to_send * 2, + ksm_to_send * 2, ); // fund the Parachain Origin's SA on Asset Hub with the assets held in reserve - AssetHubPolkadot::fund_accounts(vec![(sov_of_sender_on_ah.clone(), roc_to_send * 2)]); + AssetHubPolkadot::fund_accounts(vec![(sov_of_sender_on_ah.clone(), dot_to_send * 2)]); AssetHubPolkadot::mint_foreign_asset( ::RuntimeOrigin::signed(assets_owner), - wnd_at_rococo_parachains.clone().try_into().unwrap(), + ksm_at_polkadot_parachains.clone().try_into().unwrap(), sov_of_sender_on_ah.clone(), - wnd_to_send * 2, + ksm_to_send * 2, ); // Init values for Parachain Destination @@ -511,10 +508,10 @@ fn transfer_foreign_assets_from_para_to_para_through_asset_hub() { // Assets to send let assets: Vec = vec![ - (roc_location.clone(), roc_to_send).into(), - (wnd_at_rococo_parachains.clone(), wnd_to_send).into(), + (dot_location.clone(), dot_to_send).into(), + (ksm_at_polkadot_parachains.clone(), ksm_to_send).into(), ]; - let fee_asset_id: AssetId = roc_location.clone().into(); + let fee_asset_id: AssetId = dot_location.clone().into(); let fee_asset_item = assets.iter().position(|a| a.id == fee_asset_id).unwrap() as u32; // Init Test @@ -524,7 +521,7 @@ fn transfer_foreign_assets_from_para_to_para_through_asset_hub() { args: TestArgs::new_para( destination, receiver.clone(), - roc_to_send, + dot_to_send, assets.into(), None, fee_asset_item, @@ -533,39 +530,39 @@ fn transfer_foreign_assets_from_para_to_para_through_asset_hub() { let mut test = ParaToParaThroughAHTest::new(test_args); // Query initial balances - let sender_rocs_before = PenpalB::execute_with(|| { + let sender_dot_before = PenpalB::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(roc_location.clone(), &sender) + >::balance(dot_location.clone(), &sender) }); - let sender_wnds_before = PenpalB::execute_with(|| { + let sender_ksm_before = PenpalB::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(wnd_at_rococo_parachains.clone(), &sender) + >::balance(ksm_at_polkadot_parachains.clone(), &sender) }); - let rocs_in_sender_reserve_on_ahr_before = + let dot_in_sender_reserve_on_ahp_before = ::account_data_of(sov_of_sender_on_ah.clone()).free; - let wnds_in_sender_reserve_on_ahr_before = AssetHubPolkadot::execute_with(|| { + let ksm_in_sender_reserve_on_ahp_before = AssetHubPolkadot::execute_with(|| { type Assets = ::ForeignAssets; >::balance( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + ksm_at_polkadot_parachains.clone().try_into().unwrap(), &sov_of_sender_on_ah, ) }); - let rocs_in_receiver_reserve_on_ahr_before = + let dot_in_receiver_reserve_on_ahp_before = ::account_data_of(sov_of_receiver_on_ah.clone()).free; - let wnds_in_receiver_reserve_on_ahr_before = AssetHubPolkadot::execute_with(|| { + let ksm_in_receiver_reserve_on_ahp_before = AssetHubPolkadot::execute_with(|| { type Assets = ::ForeignAssets; >::balance( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + ksm_at_polkadot_parachains.clone().try_into().unwrap(), &sov_of_receiver_on_ah, ) }); - let receiver_rocs_before = PenpalA::execute_with(|| { + let receiver_dot_before = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(roc_location.clone(), &receiver) + >::balance(dot_location.clone(), &receiver) }); - let receiver_wnds_before = PenpalA::execute_with(|| { + let receiver_ksm_before = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(wnd_at_rococo_parachains.clone(), &receiver) + >::balance(ksm_at_polkadot_parachains.clone(), &receiver) }); // Set assertions and dispatchables @@ -576,61 +573,61 @@ fn transfer_foreign_assets_from_para_to_para_through_asset_hub() { test.assert(); // Query final balances - let sender_rocs_after = PenpalB::execute_with(|| { + let sender_dot_after = PenpalB::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(roc_location.clone(), &sender) + >::balance(dot_location.clone(), &sender) }); - let sender_wnds_after = PenpalB::execute_with(|| { + let sender_ksm_after = PenpalB::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(wnd_at_rococo_parachains.clone(), &sender) + >::balance(ksm_at_polkadot_parachains.clone(), &sender) }); - let wnds_in_sender_reserve_on_ahr_after = AssetHubPolkadot::execute_with(|| { + let ksm_in_sender_reserve_on_ahp_after = AssetHubPolkadot::execute_with(|| { type Assets = ::ForeignAssets; >::balance( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + ksm_at_polkadot_parachains.clone().try_into().unwrap(), &sov_of_sender_on_ah, ) }); - let rocs_in_sender_reserve_on_ahr_after = + let dot_in_sender_reserve_on_ahp_after = ::account_data_of(sov_of_sender_on_ah).free; - let wnds_in_receiver_reserve_on_ahr_after = AssetHubPolkadot::execute_with(|| { + let ksm_in_receiver_reserve_on_ahp_after = AssetHubPolkadot::execute_with(|| { type Assets = ::ForeignAssets; >::balance( - wnd_at_rococo_parachains.clone().try_into().unwrap(), + ksm_at_polkadot_parachains.clone().try_into().unwrap(), &sov_of_receiver_on_ah, ) }); - let rocs_in_receiver_reserve_on_ahr_after = + let dot_in_receiver_reserve_on_ahp_after = ::account_data_of(sov_of_receiver_on_ah).free; - let receiver_rocs_after = PenpalA::execute_with(|| { + let receiver_dot_after = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(roc_location, &receiver) + >::balance(dot_location, &receiver) }); - let receiver_wnds_after = PenpalA::execute_with(|| { + let receiver_ksm_after = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; - >::balance(wnd_at_rococo_parachains, &receiver) + >::balance(ksm_at_polkadot_parachains, &receiver) }); // Sender's balance is reduced by amount sent plus delivery fees - assert!(sender_rocs_after < sender_rocs_before - roc_to_send); - assert_eq!(sender_wnds_after, sender_wnds_before - wnd_to_send); + assert!(sender_dot_after < sender_dot_before - dot_to_send); + assert_eq!(sender_ksm_after, sender_ksm_before - ksm_to_send); // Sovereign accounts on reserve are changed accordingly assert_eq!( - rocs_in_sender_reserve_on_ahr_after, - rocs_in_sender_reserve_on_ahr_before - roc_to_send + dot_in_sender_reserve_on_ahp_after, + dot_in_sender_reserve_on_ahp_before - dot_to_send ); assert_eq!( - wnds_in_sender_reserve_on_ahr_after, - wnds_in_sender_reserve_on_ahr_before - wnd_to_send + ksm_in_sender_reserve_on_ahp_after, + ksm_in_sender_reserve_on_ahp_before - ksm_to_send ); - assert!(rocs_in_receiver_reserve_on_ahr_after > rocs_in_receiver_reserve_on_ahr_before); + assert!(dot_in_receiver_reserve_on_ahp_after > dot_in_receiver_reserve_on_ahp_before); assert_eq!( - wnds_in_receiver_reserve_on_ahr_after, - wnds_in_receiver_reserve_on_ahr_before + wnd_to_send + ksm_in_receiver_reserve_on_ahp_after, + ksm_in_receiver_reserve_on_ahp_before + ksm_to_send ); // Receiver's balance is increased - assert!(receiver_rocs_after > receiver_rocs_before); - assert_eq!(receiver_wnds_after, receiver_wnds_before + wnd_to_send); + assert!(receiver_dot_after > receiver_dot_before); + assert_eq!(receiver_ksm_after, receiver_ksm_before + ksm_to_send); } // ============================================================================================== diff --git a/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/reserve_transfer.rs b/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/reserve_transfer.rs index 7961e4c14f..79c7ace374 100644 --- a/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/reserve_transfer.rs +++ b/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/reserve_transfer.rs @@ -39,6 +39,24 @@ fn relay_to_para_sender_assertions(t: RelayToParaTest) { ); } +fn para_to_relay_sender_assertions(t: ParaToRelayTest) { + type RuntimeEvent = ::RuntimeEvent; + PenpalA::assert_xcm_pallet_attempted_complete(None); + assert_expected_events!( + PenpalA, + vec![ + // Amount to reserve transfer is transferred to Parachain's Sovereign account + RuntimeEvent::ForeignAssets( + pallet_assets::Event::Burned { asset_id, owner, balance, .. } + ) => { + asset_id: *asset_id == DotLocation::get(), + owner: *owner == t.sender.account_id, + balance: *balance == t.args.amount, + }, + ] + ); +} + pub fn system_para_to_para_sender_assertions(t: SystemParaToParaTest) { type RuntimeEvent = ::RuntimeEvent; AssetHubPolkadot::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts( @@ -98,6 +116,30 @@ fn relay_to_para_assets_receiver_assertions(t: RelayToParaTest) { ); } +fn para_to_relay_receiver_assertions(t: ParaToRelayTest) { + type RuntimeEvent = ::RuntimeEvent; + let sov_penpal_on_relay = + Polkadot::sovereign_account_id_of(Polkadot::child_location_of(PenpalA::para_id())); + + Polkadot::assert_ump_queue_processed(true, Some(PenpalA::para_id()), None); + assert_expected_events!( + Polkadot, + vec![ + // Amount to reserve transfer is withdrawn from Parachain's Sovereign account + RuntimeEvent::Balances( + pallet_balances::Event::Burned { who, amount } + ) => { + who: *who == sov_penpal_on_relay.clone(), + amount: *amount == t.args.amount, + }, + RuntimeEvent::Balances(pallet_balances::Event::Minted { .. }) => {}, + RuntimeEvent::MessageQueue( + pallet_message_queue::Event::Processed { success: true, .. } + ) => {}, + ] + ); +} + pub fn para_to_system_para_sender_assertions(t: ParaToSystemParaTest) { type RuntimeEvent = ::RuntimeEvent; @@ -169,6 +211,37 @@ fn system_para_to_para_assets_sender_assertions(t: SystemParaToParaTest) { ); } +fn para_to_system_para_assets_sender_assertions(t: ParaToSystemParaTest) { + type RuntimeEvent = ::RuntimeEvent; + let system_para_native_asset_location = DotLocation::get(); + let reservable_asset_location = PenpalLocalReservableFromAssetHub::get(); + PenpalB::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(864_610_000, 8799))); + assert_expected_events!( + PenpalB, + vec![ + // Fees amount to reserve transfer is burned from Parachains's sender account + RuntimeEvent::ForeignAssets( + pallet_assets::Event::Burned { asset_id, owner, .. } + ) => { + asset_id: *asset_id == system_para_native_asset_location, + owner: *owner == t.sender.account_id, + }, + // Amount to reserve transfer is burned from Parachains's sender account + RuntimeEvent::ForeignAssets( + pallet_assets::Event::Burned { asset_id, owner, balance } + ) => { + asset_id: *asset_id == reservable_asset_location, + owner: *owner == t.sender.account_id, + balance: *balance == t.args.amount, + }, + // Transport fees are paid + RuntimeEvent::PolkadotXcm( + pallet_xcm::Event::FeesPaid { .. } + ) => {}, + ] + ); +} + fn system_para_to_para_assets_receiver_assertions(t: SystemParaToParaTest) { type RuntimeEvent = ::RuntimeEvent; @@ -190,6 +263,39 @@ fn system_para_to_para_assets_receiver_assertions(t: SystemParaToParaTest) { ); } +fn para_to_system_para_assets_receiver_assertions(t: ParaToSystemParaTest) { + type RuntimeEvent = ::RuntimeEvent; + let sov_penpal_on_ahr = AssetHubPolkadot::sovereign_account_id_of( + AssetHubPolkadot::sibling_location_of(PenpalA::para_id()), + ); + AssetHubPolkadot::assert_xcmp_queue_success(None); + assert_expected_events!( + AssetHubPolkadot, + vec![ + // Amount to reserve transfer is burned from Parachain's Sovereign account + RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => { + asset_id: *asset_id == RESERVABLE_ASSET_ID, + owner: *owner == sov_penpal_on_ahr, + balance: *balance == t.args.amount, + }, + // Fee amount is burned from Parachain's Sovereign account + RuntimeEvent::Balances(pallet_balances::Event::Burned { who, .. }) => { + who: *who == sov_penpal_on_ahr, + }, + // Amount to reserve transfer is issued for beneficiary + RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, owner, amount }) => { + asset_id: *asset_id == RESERVABLE_ASSET_ID, + owner: *owner == t.receiver.account_id, + amount: *amount == t.args.amount, + }, + // Remaining fee amount is minted for for beneficiary + RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. }) => { + who: *who == t.receiver.account_id, + }, + ] + ); +} + pub fn para_to_para_through_hop_sender_assertions(t: Test) { type RuntimeEvent = ::RuntimeEvent; @@ -271,6 +377,17 @@ fn relay_to_para_reserve_transfer_assets(t: RelayToParaTest) -> DispatchResult { ) } +fn para_to_relay_reserve_transfer_assets(t: ParaToRelayTest) -> DispatchResult { + ::PolkadotXcm::limited_reserve_transfer_assets( + t.signed_origin, + bx!(t.args.dest.into()), + bx!(t.args.beneficiary.into()), + bx!(t.args.assets.into()), + t.args.fee_asset_item, + t.args.weight_limit, + ) +} + fn system_para_to_para_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult { ::PolkadotXcm::limited_reserve_transfer_assets( t.signed_origin, @@ -306,9 +423,9 @@ fn para_to_para_through_relay_limited_reserve_transfer_assets( ) } -/// Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work +/// Reserve Transfers of DOT from Relay Chain to the Asset Hub shouldn't work #[test] -fn reserve_transfer_native_asset_from_relay_to_system_para_fails() { +fn reserve_transfer_dot_from_relay_to_asset_hub_fails() { let signed_origin = ::RuntimeOrigin::signed(PolkadotSender::get()); let destination = Polkadot::child_location_of(AssetHubPolkadot::para_id()); let beneficiary: Location = @@ -338,10 +455,10 @@ fn reserve_transfer_native_asset_from_relay_to_system_para_fails() { }); } -/// Reserve Transfers of native asset from System Parachain to Relay Chain shouldn't work +/// Reserve Transfers of DOT from Asset Hub to Relay Chain shouldn't work #[test] -fn reserve_transfer_native_asset_from_system_para_to_relay_fails() { - // Init values for System Parachain +fn reserve_transfer_dot_from_asset_hub_to_relay_fails() { + // Init values for Asset Hub let signed_origin = ::RuntimeOrigin::signed(AssetHubPolkadotSender::get()); let destination = AssetHubPolkadot::parent_location(); @@ -375,9 +492,9 @@ fn reserve_transfer_native_asset_from_system_para_to_relay_fails() { }); } -/// Reserve Transfers of native asset from Relay to Parachain should work +/// Reserve Transfers of DOT from Relay to Parachain should work #[test] -fn reserve_transfer_native_asset_from_relay_to_para() { +fn reserve_transfer_dot_from_relay_to_para() { // Init values for Relay let destination = Polkadot::child_location_of(PenpalB::para_id()); let sender = PolkadotSender::get(); @@ -425,10 +542,82 @@ fn reserve_transfer_native_asset_from_relay_to_para() { assert!(receiver_assets_after < receiver_assets_before + amount_to_send); } -/// Reserve Transfers of native asset from System Parachain to Parachain should work +/// Reserve Transfers of DOT from Parachain to Relay should work +#[test] +fn reserve_transfer_dot_from_para_to_relay() { + // Init values for Parachain + let destination = PenpalA::parent_location(); + let sender = PenpalASender::get(); + let amount_to_send: Balance = POLKADOT_ED * 1000; + let assets: Assets = (Parent, amount_to_send).into(); + let asset_owner = PenpalAssetOwner::get(); + let relay_native_asset_location = DotLocation::get(); + + // fund Parachain's sender account + PenpalA::mint_foreign_asset( + ::RuntimeOrigin::signed(asset_owner), + relay_native_asset_location.clone(), + sender.clone(), + amount_to_send * 2, + ); + + // Init values for Relay + let receiver = PolkadotReceiver::get(); + let penpal_location_as_seen_by_relay = Polkadot::child_location_of(PenpalA::para_id()); + let sov_penpal_on_relay = Polkadot::sovereign_account_id_of(penpal_location_as_seen_by_relay); + + // fund Parachain's SA on Relay with the native tokens held in reserve + Polkadot::fund_accounts(vec![(sov_penpal_on_relay, amount_to_send * 2)]); + + // Init Test + let test_args = TestContext { + sender: sender.clone(), + receiver: receiver.clone(), + args: TestArgs::new_para( + destination.clone(), + receiver, + amount_to_send, + assets.clone(), + None, + 0, + ), + }; + let mut test = ParaToRelayTest::new(test_args); + + // Query initial balances + let sender_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location.clone(), &sender) + }); + let receiver_balance_before = test.receiver.balance; + + // Set assertions and dispatchables + test.set_assertion::(para_to_relay_sender_assertions); + test.set_assertion::(para_to_relay_receiver_assertions); + test.set_dispatchable::(para_to_relay_reserve_transfer_assets); + test.assert(); + + // Query final balances + let sender_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location, &sender) + }); + let receiver_balance_after = test.receiver.balance; + + // Sender's balance is reduced by amount sent plus delivery fees + assert!(sender_assets_after < sender_assets_before - amount_to_send); + // Receiver's asset balance is increased + assert!(receiver_balance_after > receiver_balance_before); + // Receiver's asset balance increased by `amount_to_send - delivery_fees - bought_execution`; + // `delivery_fees` might be paid from transfer or JIT, also `bought_execution` is unknown but + // should be non-zero + assert!(receiver_balance_after < receiver_balance_before + amount_to_send); +} + +/// Reserve Transfers of DOT from Asset Hub to Parachain should work #[test] -fn reserve_transfer_native_asset_from_system_para_to_para() { - // Init values for System Parachain +fn reserve_transfer_dot_from_asset_hub_to_para() { + // Init values for Asset Hub let destination = AssetHubPolkadot::sibling_location_of(PenpalB::para_id()); let sender = AssetHubPolkadotSender::get(); let amount_to_send: Balance = ASSET_HUB_POLKADOT_ED * 10000; @@ -484,9 +673,9 @@ fn reserve_transfer_native_asset_from_system_para_to_para() { assert!(receiver_assets_after < receiver_assets_before + amount_to_send); } -/// Reserve Transfers of native asset from Parachain to System Parachain should work +/// Reserve Transfers of DOT from Parachain to Asset Hub should work #[test] -fn reserve_transfer_native_asset_from_para_to_system_para() { +fn reserve_transfer_dot_from_para_to_asset_hub() { // Init values for Parachain let destination = PenpalB::sibling_location_of(AssetHubPolkadot::para_id()); let sender = PenpalBSender::get(); @@ -503,14 +692,14 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { amount_to_send * 2, ); - // Init values for System Parachain + // Init values for Asset Hub let receiver = AssetHubPolkadotReceiver::get(); - let penpal_location_as_seen_by_ahr = AssetHubPolkadot::sibling_location_of(PenpalB::para_id()); - let sov_penpal_on_ahr = - AssetHubPolkadot::sovereign_account_id_of(penpal_location_as_seen_by_ahr); + let penpal_location_as_seen_by_ahp = AssetHubPolkadot::sibling_location_of(PenpalB::para_id()); + let sov_penpal_on_ahp = + AssetHubPolkadot::sovereign_account_id_of(penpal_location_as_seen_by_ahp); - // fund Parachain's SA on System Parachain with the native tokens held in reserve - AssetHubPolkadot::fund_accounts(vec![(sov_penpal_on_ahr, amount_to_send * 2)]); + // fund Parachain's SA on Asset Hub with the native tokens held in reserve + AssetHubPolkadot::fund_accounts(vec![(sov_penpal_on_ahp, amount_to_send * 2)]); // Init Test let test_args = TestContext { @@ -557,13 +746,12 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { assert!(receiver_balance_after < receiver_balance_before + amount_to_send); } -/// Reserve Transfers of a local asset and native asset from System Parachain to Parachain should -/// work +/// Reserve Transfers of a local asset and DOT from Asset Hub to Parachain should work #[test] -fn reserve_transfer_assets_from_system_para_to_para() { - // Init values for System Parachain +fn reserve_transfer_multiple_assets_from_asset_hub_to_para() { + // Init values for Asset Hub let destination = AssetHubPolkadot::sibling_location_of(PenpalB::para_id()); - let sov_penpal_on_ahr = AssetHubPolkadot::sovereign_account_id_of(destination.clone()); + let sov_penpal_on_ahp = AssetHubPolkadot::sovereign_account_id_of(destination.clone()); let sender = AssetHubPolkadotSender::get(); let fee_amount_to_send = ASSET_HUB_POLKADOT_ED * 10000; let asset_amount_to_send = PENPAL_ED * 10000; @@ -591,8 +779,8 @@ fn reserve_transfer_assets_from_system_para_to_para() { asset_amount_to_send * 2, ); - // Create SA-of-Penpal-on-AHR with ED. - AssetHubPolkadot::fund_accounts(vec![(sov_penpal_on_ahr, ASSET_HUB_POLKADOT_ED)]); + // Create SA-of-Penpal-on-AHP with ED. + AssetHubPolkadot::fund_accounts(vec![(sov_penpal_on_ahp, ASSET_HUB_POLKADOT_ED)]); // Init values for Parachain let receiver = PenpalBReceiver::get(); @@ -673,10 +861,132 @@ fn reserve_transfer_assets_from_system_para_to_para() { ); } -/// Reserve Transfers of native asset from Parachain to Parachain (through Relay reserve) should -/// work +/// Reserve Transfers of a random asset and DOT asset from Parachain to Asset Hub should work +#[test] +fn reserve_transfer_multiple_assets_from_para_to_asset_hub() { + // Init values for Parachain + let destination = PenpalB::sibling_location_of(AssetHubPolkadot::para_id()); + let sender = PenpalBSender::get(); + let fee_amount_to_send = ASSET_HUB_POLKADOT_ED * 10000; + let asset_amount_to_send = ASSET_HUB_POLKADOT_ED * 10000; + let penpal_asset_owner = PenpalAssetOwner::get(); + let penpal_asset_owner_signer = ::RuntimeOrigin::signed(penpal_asset_owner); + let asset_location_on_penpal = PenpalLocalReservableFromAssetHub::get(); + let system_asset_location_on_penpal = DotLocation::get(); + let assets: Assets = vec![ + (Parent, fee_amount_to_send).into(), + (asset_location_on_penpal.clone(), asset_amount_to_send).into(), + ] + .into(); + let fee_asset_index = assets + .inner() + .iter() + .position(|r| r == &(Parent, fee_amount_to_send).into()) + .unwrap() as u32; + // Fund Parachain's sender account with some foreign assets + PenpalB::mint_foreign_asset( + penpal_asset_owner_signer.clone(), + asset_location_on_penpal.clone(), + sender.clone(), + asset_amount_to_send * 2, + ); + // Fund Parachain's sender account with some system assets + PenpalB::mint_foreign_asset( + penpal_asset_owner_signer, + system_asset_location_on_penpal.clone(), + sender.clone(), + fee_amount_to_send * 2, + ); + + // Init values for Asset Hub + let receiver = AssetHubPolkadotReceiver::get(); + let penpal_location_as_seen_by_ahp = AssetHubPolkadot::sibling_location_of(PenpalB::para_id()); + let sov_penpal_on_ahp = + AssetHubPolkadot::sovereign_account_id_of(penpal_location_as_seen_by_ahp); + let ah_asset_owner = AssetHubPolkadotAssetOwner::get(); + let ah_asset_owner_signer = ::RuntimeOrigin::signed(ah_asset_owner); + + // Fund SA-of-Penpal-on-AHP to be able to pay for the fees. + AssetHubPolkadot::fund_accounts(vec![( + sov_penpal_on_ahp.clone(), + ASSET_HUB_POLKADOT_ED * 10000000, + )]); + // Fund SA-of-Penpal-on-AHP to be able to pay for the sent amount. + AssetHubPolkadot::mint_asset( + ah_asset_owner_signer, + RESERVABLE_ASSET_ID, + sov_penpal_on_ahp, + asset_amount_to_send * 2, + ); + + // Init Test + let para_test_args = TestContext { + sender: sender.clone(), + receiver: receiver.clone(), + args: TestArgs::new_para( + destination, + receiver.clone(), + asset_amount_to_send, + assets, + None, + fee_asset_index, + ), + }; + let mut test = ParaToSystemParaTest::new(para_test_args); + + // Query initial balances + let sender_system_assets_before = PenpalB::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_asset_location_on_penpal.clone(), &sender) + }); + let sender_foreign_assets_before = PenpalB::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(asset_location_on_penpal.clone(), &sender) + }); + let receiver_balance_before = test.receiver.balance; + let receiver_assets_before = AssetHubPolkadot::execute_with(|| { + type Assets = ::Assets; + >::balance(RESERVABLE_ASSET_ID, &receiver) + }); + + // Set assertions and dispatchables + test.set_assertion::(para_to_system_para_assets_sender_assertions); + test.set_assertion::(para_to_system_para_assets_receiver_assertions); + test.set_dispatchable::(para_to_system_para_reserve_transfer_assets); + test.assert(); + + // Query final balances + let sender_system_assets_after = PenpalB::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_asset_location_on_penpal, &sender) + }); + let sender_foreign_assets_after = PenpalB::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(asset_location_on_penpal, &sender) + }); + let receiver_balance_after = test.receiver.balance; + let receiver_assets_after = AssetHubPolkadot::execute_with(|| { + type Assets = ::Assets; + >::balance(RESERVABLE_ASSET_ID, &receiver) + }); + // Sender's system asset balance is reduced + assert!(sender_system_assets_after < sender_system_assets_before); + // Receiver's balance is increased + assert!(receiver_balance_after > receiver_balance_before); + // Receiver's balance increased by `amount_to_send - delivery_fees - bought_execution`; + // `delivery_fees` might be paid from transfer or JIT, also `bought_execution` is unknown but + // should be non-zero + assert!(receiver_balance_after < receiver_balance_before + fee_amount_to_send); + + // Sender's asset balance is reduced by exact amount + assert_eq!(sender_foreign_assets_before - asset_amount_to_send, sender_foreign_assets_after); + // Receiver's foreign asset balance is increased by exact amount + assert_eq!(receiver_assets_after, receiver_assets_before + asset_amount_to_send); +} + +/// Reserve Transfers of DOT from Parachain to Parachain (through Relay reserve) should work #[test] -fn reserve_transfer_native_asset_from_para_to_para_through_relay() { +fn reserve_transfer_dot_from_para_to_para_through_relay() { // Init values for Parachain Origin let destination = PenpalB::sibling_location_of(PenpalA::para_id()); let sender = PenpalBSender::get(); diff --git a/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/send.rs b/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/send.rs index 623264b25b..c8542c8ece 100644 --- a/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/send.rs +++ b/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/send.rs @@ -18,7 +18,7 @@ use crate::*; /// Relay Chain should be able to execute `Transact` instructions in System Parachain /// when `OriginKind::Superuser`. #[test] -fn send_transact_as_superuser_from_relay_to_system_para_works() { +fn send_transact_as_superuser_from_relay_to_asset_hub_works() { AssetHubPolkadot::force_create_asset_from_relay_as_root( ASSET_ID, ASSET_MIN_BALANCE, @@ -28,15 +28,97 @@ fn send_transact_as_superuser_from_relay_to_system_para_works() { ) } -/// Parachain should be able to send XCM paying its fee with sufficient asset -/// in the System Parachain +/// We tests two things here: +/// - Parachain should be able to send XCM paying its fee at Asset Hub using DOT +/// - Parachain should be able to create a new Foreign Asset at Asset Hub #[test] -fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() { +fn send_xcm_from_para_to_asset_hub_paying_fee_with_system_asset() { let para_sovereign_account = AssetHubPolkadot::sovereign_account_id_of( - AssetHubPolkadot::sibling_location_of(PenpalB::para_id()), + AssetHubPolkadot::sibling_location_of(PenpalA::para_id()), ); + let asset_location_on_penpal = v3::Location::new( + 0, + [ + v3::Junction::PalletInstance(ASSETS_PALLET_ID), + v3::Junction::GeneralIndex(ASSET_ID.into()), + ], + ); + let foreign_asset_at_asset_hub = + v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())]) + .appended_with(asset_location_on_penpal) + .unwrap(); + + // Encoded `create_asset` call to be executed in AssetHub + let call = AssetHubPolkadot::create_foreign_asset_call( + foreign_asset_at_asset_hub, + ASSET_MIN_BALANCE, + para_sovereign_account.clone(), + ); + + let origin_kind = OriginKind::Xcm; + let fee_amount = ASSET_HUB_POLKADOT_ED * 1000000; + let system_asset = (Parent, fee_amount).into(); + + let root_origin = ::RuntimeOrigin::root(); + let system_para_destination = PenpalA::sibling_location_of(AssetHubPolkadot::para_id()).into(); + let xcm = xcm_transact_paid_execution( + call, + origin_kind, + system_asset, + para_sovereign_account.clone(), + ); + + // SA-of-Penpal-on-AHP needs to have balance to pay for fees and asset creation deposit + AssetHubPolkadot::fund_accounts(vec![( + para_sovereign_account.clone(), + ASSET_HUB_POLKADOT_ED * 10000000000, + )]); - // Force create and mint assets for Parachain's sovereign account + PenpalA::execute_with(|| { + assert_ok!(::PolkadotXcm::send( + root_origin, + bx!(system_para_destination), + bx!(xcm), + )); + + PenpalA::assert_xcm_pallet_sent(); + }); + + AssetHubPolkadot::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + AssetHubPolkadot::assert_xcmp_queue_success(None); + assert_expected_events!( + AssetHubPolkadot, + vec![ + // Burned the fee + RuntimeEvent::Balances(pallet_balances::Event::Burned { who, amount }) => { + who: *who == para_sovereign_account, + amount: *amount == fee_amount, + }, + // Foreign Asset created + RuntimeEvent::ForeignAssets(pallet_assets::Event::Created { asset_id, creator, owner }) => { + asset_id: *asset_id == foreign_asset_at_asset_hub, + creator: *creator == para_sovereign_account.clone(), + owner: *owner == para_sovereign_account, + }, + ] + ); + + type ForeignAssets = ::ForeignAssets; + assert!(ForeignAssets::asset_exists(foreign_asset_at_asset_hub)); + }); +} + +/// We tests two things here: +/// - Parachain should be able to send XCM paying its fee at Asset Hub using sufficient asset +/// - Parachain should be able to create a new Asset at Asset Hub +#[test] +fn send_xcm_from_para_to_asset_hub_paying_fee_with_sufficient_asset() { + let para_sovereign_account = AssetHubPolkadot::sovereign_account_id_of( + AssetHubPolkadot::sibling_location_of(PenpalA::para_id()), + ); + + // Force create and mint sufficient assets for Parachain's sovereign account AssetHubPolkadot::force_create_and_mint_asset( ASSET_ID, ASSET_MIN_BALANCE, @@ -46,57 +128,58 @@ fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() { ASSET_MIN_BALANCE * 1000000000, ); - // We just need a call that can pass the `SafeCallFilter` - // Call values are not relevant - let call = AssetHubPolkadot::force_create_asset_call( - ASSET_ID, - para_sovereign_account.clone(), - true, + // Just a different `asset_id`` that does not exist yet + let new_asset_id = ASSET_ID + 1; + + // Encoded `create_asset` call to be executed in AssetHub + let call = AssetHubPolkadot::create_asset_call( + new_asset_id, ASSET_MIN_BALANCE, + para_sovereign_account.clone(), ); let origin_kind = OriginKind::SovereignAccount; let fee_amount = ASSET_MIN_BALANCE * 1000000; - let native_asset = + let asset = ([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], fee_amount).into(); - let root_origin = ::RuntimeOrigin::root(); - let system_para_destination = PenpalB::sibling_location_of(AssetHubPolkadot::para_id()).into(); - let xcm = xcm_transact_paid_execution( - call, - origin_kind, - native_asset, + let root_origin = ::RuntimeOrigin::root(); + let system_para_destination = PenpalA::sibling_location_of(AssetHubPolkadot::para_id()).into(); + let xcm = xcm_transact_paid_execution(call, origin_kind, asset, para_sovereign_account.clone()); + + // SA-of-Penpal-on-AHP needs to have balance to pay for asset creation deposit + AssetHubPolkadot::fund_accounts(vec![( para_sovereign_account.clone(), - ); + ASSET_HUB_POLKADOT_ED * 10000000000, + )]); - PenpalB::execute_with(|| { - assert_ok!(::PolkadotXcm::send( + PenpalA::execute_with(|| { + assert_ok!(::PolkadotXcm::send( root_origin, bx!(system_para_destination), bx!(xcm), )); - PenpalB::assert_xcm_pallet_sent(); + PenpalA::assert_xcm_pallet_sent(); }); AssetHubPolkadot::execute_with(|| { type RuntimeEvent = ::RuntimeEvent; - - AssetHubPolkadot::assert_xcmp_queue_success(Some(Weight::from_parts( - 16_290_336_000, - 562_893, - ))); - + AssetHubPolkadot::assert_xcmp_queue_success(None); assert_expected_events!( AssetHubPolkadot, vec![ + // Burned the fee RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => { asset_id: *asset_id == ASSET_ID, owner: *owner == para_sovereign_account, balance: *balance == fee_amount, }, - RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, .. }) => { - asset_id: *asset_id == ASSET_ID, + // Asset created + RuntimeEvent::Assets(pallet_assets::Event::Created { asset_id, creator, owner }) => { + asset_id: *asset_id == new_asset_id, + creator: *creator == para_sovereign_account.clone(), + owner: *owner == para_sovereign_account, }, ] ); diff --git a/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/teleport.rs b/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/teleport.rs index 66fd4f3bff..882543cc1b 100644 --- a/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/teleport.rs +++ b/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/teleport.rs @@ -16,55 +16,12 @@ use crate::*; use asset_hub_polkadot_runtime::xcm_config::{DotLocation, XcmConfig as AssetHubPolkadotXcmConfig}; use emulated_integration_tests_common::xcm_helpers::non_fee_asset; -use polkadot_runtime::xcm_config::XcmConfig as PolkadotXcmConfig; +use frame_support::traits::fungible::Mutate; use polkadot_system_emulated_network::penpal_emulated_chain::LocalTeleportableToAssetHub as PenpalLocalTeleportableToAssetHub; - -fn relay_origin_assertions(t: RelayToSystemParaTest) { - type RuntimeEvent = ::RuntimeEvent; - - Polkadot::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(632_207_000, 7_186))); - - assert_expected_events!( - Polkadot, - vec![ - // Amount to teleport is withdrawn from Sender - RuntimeEvent::Balances(pallet_balances::Event::Burned { who, amount }) => { - who: *who == t.sender.account_id, - amount: *amount == t.args.amount, - }, - // Amount to teleport is deposited in Relay's `CheckAccount` - RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount }) => { - who: *who == ::XcmPallet::check_account(), - amount: *amount == t.args.amount, - }, - ] - ); -} - -fn relay_dest_assertions(t: SystemParaToRelayTest) { - type RuntimeEvent = ::RuntimeEvent; - - Polkadot::assert_ump_queue_processed( - true, - Some(AssetHubPolkadot::para_id()), - Some(Weight::from_parts(308_222_000, 7_186)), - ); - - assert_expected_events!( - Polkadot, - vec![ - // Amount is withdrawn from Relay Chain's `CheckAccount` - RuntimeEvent::Balances(pallet_balances::Event::Burned { who, amount }) => { - who: *who == ::XcmPallet::check_account(), - amount: *amount == t.args.amount, - }, - // Amount minus fees are deposited in Receiver's account - RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. }) => { - who: *who == t.receiver.account_id, - }, - ] - ); -} +use xcm_runtime_apis::{ + dry_run::runtime_decl_for_dry_run_api::DryRunApiV1, + fees::runtime_decl_for_xcm_payment_api::XcmPaymentApiV1, +}; fn relay_dest_assertions_fail(_t: SystemParaToRelayTest) { Polkadot::assert_ump_queue_processed( @@ -96,22 +53,6 @@ fn para_origin_assertions(t: SystemParaToRelayTest) { ); } -fn para_dest_assertions(t: RelayToSystemParaTest) { - type RuntimeEvent = ::RuntimeEvent; - - AssetHubPolkadot::assert_dmp_queue_complete(Some(Weight::from_parts(164_793_000, 3593))); - - assert_expected_events!( - AssetHubPolkadot, - vec![ - // Amount minus fees are deposited in Receiver's account - RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. }) => { - who: *who == t.receiver.account_id, - }, - ] - ); -} - fn penpal_to_ah_foreign_assets_sender_assertions(t: ParaToSystemParaTest) { type RuntimeEvent = ::RuntimeEvent; let system_para_native_asset_location = DotLocation::get(); @@ -233,17 +174,6 @@ fn ah_to_penpal_foreign_assets_receiver_assertions(t: SystemParaToParaTest) { ); } -fn relay_limited_teleport_assets(t: RelayToSystemParaTest) -> DispatchResult { - ::XcmPallet::limited_teleport_assets( - t.signed_origin, - bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), - bx!(t.args.assets.into()), - t.args.fee_asset_item, - t.args.weight_limit, - ) -} - fn system_para_limited_teleport_assets(t: SystemParaToRelayTest) -> DispatchResult { ::PolkadotXcm::limited_teleport_assets( t.signed_origin, @@ -277,90 +207,41 @@ fn para_to_system_para_transfer_assets(t: ParaToSystemParaTest) -> DispatchResul ) } -/// Limited Teleport of native asset from Relay Chain to the System Parachain should work #[test] -fn limited_teleport_native_assets_from_relay_to_system_para_works() { - // Init values for Relay Chain - let amount_to_send: Balance = POLKADOT_ED * 1000; - let dest = Polkadot::child_location_of(AssetHubPolkadot::para_id()); - let beneficiary = AssetHubPolkadotReceiver::get(); - let test_args = TestContext { - sender: PolkadotSender::get(), - receiver: beneficiary.clone(), - args: TestArgs::new_relay(dest, beneficiary, amount_to_send), - }; - - let mut test = RelayToSystemParaTest::new(test_args); - - let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; - - test.set_assertion::(relay_origin_assertions); - test.set_assertion::(para_dest_assertions); - test.set_dispatchable::(relay_limited_teleport_assets); - test.assert(); - - let delivery_fees = Polkadot::execute_with(|| { - xcm_helpers::teleport_assets_delivery_fees::< - ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) - }); - - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; +fn teleport_to_other_system_parachains_works() { + let amount = ASSET_HUB_POLKADOT_ED * 100; + let native_asset: Assets = (Parent, amount).into(); - // Sender's balance is reduced - assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); - // Receiver's balance is increased - assert!(receiver_balance_after > receiver_balance_before); + test_parachain_is_trusted_teleporter!( + AssetHubPolkadot, // Origin + AssetHubPolkadotXcmConfig, // XCM Configuration + vec![BridgeHubPolkadot], // Destinations + (native_asset, amount) + ); } -/// Limited Teleport of native asset from System Parachain to Relay Chain -/// should work when there is enough balance in Relay Chain's `CheckAccount` #[test] -fn limited_teleport_native_assets_back_from_system_para_to_relay_works() { - // Dependency - Relay Chain's `CheckAccount` should have enough balance - limited_teleport_native_assets_from_relay_to_system_para_works(); - - // Init values for Relay Chain - let amount_to_send: Balance = ASSET_HUB_POLKADOT_ED * 1000; - let destination = AssetHubPolkadot::parent_location(); - let beneficiary_id = PolkadotReceiver::get(); - let assets = (Parent, amount_to_send).into(); +fn teleport_from_and_to_relay() { + let amount = POLKADOT_ED * 100; + let native_asset: Assets = (Here, amount).into(); - let test_args = TestContext { - sender: AssetHubPolkadotSender::get(), - receiver: PolkadotReceiver::get(), - args: TestArgs::new_para(destination, beneficiary_id, amount_to_send, assets, None, 0), - }; - - let mut test = SystemParaToRelayTest::new(test_args); - - let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; - - test.set_assertion::(para_origin_assertions); - test.set_assertion::(relay_dest_assertions); - test.set_dispatchable::(system_para_limited_teleport_assets); - test.assert(); - - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - - let delivery_fees = AssetHubPolkadot::execute_with(|| { - xcm_helpers::teleport_assets_delivery_fees::< - ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) - }); + test_relay_is_trusted_teleporter!( + Polkadot, + PolkadotXcmConfig, + vec![AssetHubPolkadot], + (native_asset, amount) + ); - // Sender's balance is reduced - assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); - // Receiver's balance is increased - assert!(receiver_balance_after > receiver_balance_before); + test_parachain_is_trusted_teleporter_for_relay!( + AssetHubPolkadot, + AssetHubPolkadotXcmConfig, + Polkadot, + amount + ); } /// Limited Teleport of native asset from System Parachain to Relay Chain -/// should't work when there is not enough balance in Relay Chain's `CheckAccount` +/// shouldn't work when there is not enough balance in Relay Chain's `CheckAccount` #[test] fn limited_teleport_native_assets_from_system_para_to_relay_fails() { // Init values for Relay Chain @@ -400,19 +281,6 @@ fn limited_teleport_native_assets_from_system_para_to_relay_fails() { assert_eq!(receiver_balance_after, receiver_balance_before); } -#[test] -fn teleport_to_other_system_parachains_works() { - let amount = ASSET_HUB_POLKADOT_ED * 100; - let native_asset: Assets = (Parent, amount).into(); - - test_parachain_is_trusted_teleporter!( - AssetHubPolkadot, // Origin - AssetHubPolkadotXcmConfig, // XCM Configuration - vec![BridgeHubPolkadot], // Destinations - (native_asset, amount) - ); -} - /// Bidirectional teleports of local Penpal assets to Asset Hub as foreign assets while paying /// fees using (reserve transferred) native asset. pub fn do_bidirectional_teleport_foreign_assets_between_para_and_asset_hub_using_xt( diff --git a/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/treasury.rs b/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/treasury.rs index 213b9c0f1f..b9d1786667 100644 --- a/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/treasury.rs +++ b/integration-tests/emulated/tests/assets/asset-hub-polkadot/src/tests/treasury.rs @@ -15,14 +15,14 @@ use crate::*; use emulated_integration_tests_common::accounts::{ALICE, BOB}; -use frame_support::traits::fungibles::{Create, Mutate}; +use frame_support::traits::fungibles::Mutate; use polkadot_runtime_common::impls::VersionedLocatableAsset; use xcm_executor::traits::ConvertLocation; #[test] -fn create_and_claim_treasury_spend() { - const ASSET_ID: u32 = 1984; - const SPEND_AMOUNT: u128 = 1_000_000; +fn create_and_claim_treasury_spend_in_usdt() { + const USDT_ID: u32 = 1984; + const SPEND_AMOUNT: u128 = 1_000_000_000; // treasury location from a sibling parachain. let treasury_location: Location = Location::new(1, PalletInstance(19)); // treasury account on a sibling parachain. @@ -38,7 +38,7 @@ fn create_and_claim_treasury_spend() { let asset_kind = VersionedLocatableAsset::V3 { location: asset_hub_location, asset_id: v3::AssetId::Concrete( - (v3::Junction::PalletInstance(50), v3::Junction::GeneralIndex(ASSET_ID.into())).into(), + (v3::Junction::PalletInstance(50), v3::Junction::GeneralIndex(USDT_ID.into())).into(), ), }; // treasury spend beneficiary. @@ -49,16 +49,10 @@ fn create_and_claim_treasury_spend() { AssetHubPolkadot::execute_with(|| { type Assets = ::Assets; - // create an asset class and mint some assets to the treasury account. - assert_ok!(>::create( - ASSET_ID, - treasury_account.clone(), - true, - SPEND_AMOUNT / 2 - )); - assert_ok!(>::mint_into(ASSET_ID, &treasury_account, SPEND_AMOUNT * 4)); + // USDT created at genesis, mint some assets to the treasury account. + assert_ok!(>::mint_into(USDT_ID, &treasury_account, SPEND_AMOUNT * 4)); // beneficiary has zero balance. - assert_eq!(>::balance(ASSET_ID, &alice,), 0u128,); + assert_eq!(>::balance(USDT_ID, &alice,), 0u128,); }); Polkadot::execute_with(|| { @@ -100,7 +94,7 @@ fn create_and_claim_treasury_spend() { AssetHubPolkadot, vec![ RuntimeEvent::Assets(pallet_assets::Event::Transferred { asset_id: id, from, to, amount }) => { - id: id == &ASSET_ID, + id: id == &USDT_ID, from: from == &treasury_account, to: to == &alice, amount: amount == &SPEND_AMOUNT, @@ -110,7 +104,7 @@ fn create_and_claim_treasury_spend() { ] ); // beneficiary received the assets from the treasury. - assert_eq!(>::balance(ASSET_ID, &alice,), SPEND_AMOUNT,); + assert_eq!(>::balance(USDT_ID, &alice,), SPEND_AMOUNT,); }); Polkadot::execute_with(|| { diff --git a/integration-tests/emulated/tests/bridges/bridge-hub-polkadot/src/tests/snowbridge.rs b/integration-tests/emulated/tests/bridges/bridge-hub-polkadot/src/tests/snowbridge.rs index 3b85c63595..0cbbc31350 100644 --- a/integration-tests/emulated/tests/bridges/bridge-hub-polkadot/src/tests/snowbridge.rs +++ b/integration-tests/emulated/tests/bridges/bridge-hub-polkadot/src/tests/snowbridge.rs @@ -833,3 +833,132 @@ fn make_register_token_message() -> InboundQueueFixture { block_roots_root: hex!("3adb5c78afd49ef17160ca7fc38b47228cbb13a317709c86bb6f51d799ba9ab6").into(), } } + +fn send_token_from_ethereum_to_asset_hub_with_fee(account_id: [u8; 32], fee: u128) { + let weth_asset_location: Location = Location::new( + 2, + [EthereumNetwork::get().into(), AccountKey20 { network: None, key: WETH }], + ); + // Fund asset hub sovereign on bridge hub + let asset_hub_sovereign = BridgeHubPolkadot::sovereign_account_id_of(Location::new( + 1, + [Parachain(AssetHubPolkadot::para_id().into())], + )); + BridgeHubPolkadot::fund_accounts(vec![(asset_hub_sovereign.clone(), INITIAL_FUND)]); + + // Register WETH + AssetHubPolkadot::execute_with(|| { + type RuntimeOrigin = ::RuntimeOrigin; + + assert_ok!(::ForeignAssets::force_create( + RuntimeOrigin::root(), + weth_asset_location.clone().try_into().unwrap(), + asset_hub_sovereign.into(), + false, + 1, + )); + + assert!(::ForeignAssets::asset_exists( + weth_asset_location.clone().try_into().unwrap(), + )); + }); + + // Send WETH to an existent account on asset hub + BridgeHubPolkadot::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + type EthereumInboundQueue = + ::EthereumInboundQueue; + let message_id: H256 = [0; 32].into(); + let message = VersionedMessage::V1(MessageV1 { + chain_id: CHAIN_ID, + command: Command::SendToken { + token: WETH.into(), + destination: Destination::AccountId32 { id: account_id }, + amount: 1_000_000, + fee, + }, + }); + let (xcm, _) = EthereumInboundQueue::do_convert(message_id, message).unwrap(); + assert_ok!(EthereumInboundQueue::send_xcm(xcm, AssetHubPolkadot::para_id())); + + // Check that the message was sent + assert_expected_events!( + BridgeHubPolkadot, + vec![ + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {}, + ] + ); + }); +} + +#[test] +fn send_token_from_ethereum_to_existent_account_on_asset_hub() { + send_token_from_ethereum_to_asset_hub_with_fee(AssetHubPolkadotSender::get().into(), XCM_FEE); + + AssetHubPolkadot::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + // Check that the token was received and issued as a foreign asset on AssetHub + assert_expected_events!( + AssetHubPolkadot, + vec![ + RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { .. }) => {}, + ] + ); + }); +} + +#[test] +fn send_token_from_ethereum_to_non_existent_account_on_asset_hub() { + send_token_from_ethereum_to_asset_hub_with_fee([1; 32], XCM_FEE); + + AssetHubPolkadot::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + // Check that the token was received and issued as a foreign asset on AssetHub + assert_expected_events!( + AssetHubPolkadot, + vec![ + RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { .. }) => {}, + ] + ); + }); +} + +#[test] +fn send_token_from_ethereum_to_non_existent_account_on_asset_hub_with_insufficient_fee() { + send_token_from_ethereum_to_asset_hub_with_fee([1; 32], INSUFFICIENT_XCM_FEE); + + AssetHubPolkadot::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + // Check that the message was not processed successfully due to insufficient fee + + assert_expected_events!( + AssetHubPolkadot, + vec![ + RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success:false, .. }) => {}, + ] + ); + }); +} + +#[test] +fn send_token_from_ethereum_to_non_existent_account_on_asset_hub_with_sufficient_fee_but_do_not_satisfy_ed( +) { + // On AH the xcm fee is 26_789_690 and the ED is 3_300_000 + send_token_from_ethereum_to_asset_hub_with_fee([1; 32], 30_000_000); + + AssetHubPolkadot::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + // Check that the message was not processed successfully due to insufficient ED + assert_expected_events!( + AssetHubPolkadot, + vec![ + RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success:false, .. }) => {}, + ] + ); + }); +} diff --git a/integration-tests/emulated/tests/collectives/collectives-polkadot/src/tests/fellowship_salary.rs b/integration-tests/emulated/tests/collectives/collectives-polkadot/src/tests/fellowship_salary.rs index d4ab5a83d6..150163a6c9 100644 --- a/integration-tests/emulated/tests/collectives/collectives-polkadot/src/tests/fellowship_salary.rs +++ b/integration-tests/emulated/tests/collectives/collectives-polkadot/src/tests/fellowship_salary.rs @@ -18,10 +18,7 @@ use asset_hub_polkadot_runtime::xcm_config::LocationToAccountId; use collectives_polkadot_runtime::fellowship::FellowshipSalaryPaymaster; use frame_support::{ assert_ok, - traits::{ - fungibles::{Create, Mutate}, - tokens::Pay, - }, + traits::{fungibles::Mutate, tokens::Pay}, }; use xcm_executor::traits::ConvertLocation; @@ -30,7 +27,7 @@ const FELLOWSHIP_SALARY_PALLET_ID: u8 = #[test] fn pay_salary() { - let asset_id: u32 = 1984; + const USDT_ID: u32 = 1984; let fellowship_salary = ( Parent, Parachain(CollectivesPolkadot::para_id().into()), @@ -38,18 +35,12 @@ fn pay_salary() { ); let pay_from = LocationToAccountId::convert_location(&fellowship_salary.into()).unwrap(); let pay_to = Polkadot::account_id_of(ALICE); - let pay_amount = 9000; + let pay_amount = 9_000_000_000; AssetHubPolkadot::execute_with(|| { type AssetHubAssets = ::Assets; - - assert_ok!(>::create( - asset_id, - pay_to.clone(), - true, - pay_amount / 2 - )); - assert_ok!(>::mint_into(asset_id, &pay_from, pay_amount * 2)); + // USDT registered in genesis, now mint some into the payer's account + assert_ok!(>::mint_into(USDT_ID, &pay_from, pay_amount * 2)); }); CollectivesPolkadot::execute_with(|| { @@ -69,9 +60,9 @@ fn pay_salary() { assert_expected_events!( AssetHubPolkadot, vec![ - RuntimeEvent::Assets(pallet_assets::Event::Transferred { .. }) => {}, - RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true ,.. }) => {}, - ] + RuntimeEvent::Assets(pallet_assets::Event::Transferred { .. }) => {}, + RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true ,.. }) => {}, + ] ); }); } diff --git a/integration-tests/emulated/tests/people/people-kusama/src/lib.rs b/integration-tests/emulated/tests/people/people-kusama/src/lib.rs index dac9c8d372..b59472d2df 100644 --- a/integration-tests/emulated/tests/people/people-kusama/src/lib.rs +++ b/integration-tests/emulated/tests/people/people-kusama/src/lib.rs @@ -49,6 +49,7 @@ pub use kusama_system_emulated_network::{ PeopleKusamaParaReceiver as PeopleKusamaReceiver, PeopleKusamaParaSender as PeopleKusamaSender, }; pub use parachains_common::{AccountId, Balance}; +pub use people_kusama_runtime::ExistentialDeposit as PeopleKusamaExistentialDeposit; pub type RelayToSystemParaTest = Test; pub type RelayToParaTest = Test; diff --git a/integration-tests/emulated/tests/people/people-kusama/src/tests/claim_assets.rs b/integration-tests/emulated/tests/people/people-kusama/src/tests/claim_assets.rs new file mode 100644 index 0000000000..919b6332b8 --- /dev/null +++ b/integration-tests/emulated/tests/people/people-kusama/src/tests/claim_assets.rs @@ -0,0 +1,29 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Tests related to claiming assets trapped during XCM execution. + +use crate::*; + +use integration_tests_helpers::test_chain_can_claim_assets; +use xcm_executor::traits::DropAssets; + +#[test] +fn assets_can_be_claimed() { + let amount = PeopleKusamaExistentialDeposit::get(); + let assets: Assets = (Parent, amount).into(); + + test_chain_can_claim_assets!(PeopleKusama, RuntimeCall, NetworkId::Kusama, assets, amount); +} diff --git a/integration-tests/emulated/tests/people/people-kusama/src/tests/mod.rs b/integration-tests/emulated/tests/people/people-kusama/src/tests/mod.rs index 40ee1de643..b9ad9e3db4 100644 --- a/integration-tests/emulated/tests/people/people-kusama/src/tests/mod.rs +++ b/integration-tests/emulated/tests/people/people-kusama/src/tests/mod.rs @@ -13,5 +13,6 @@ // See the License for the specific language governing permissions and // limitations under the License. +mod claim_assets; mod governance; mod teleport; diff --git a/integration-tests/emulated/tests/people/people-kusama/src/tests/teleport.rs b/integration-tests/emulated/tests/people/people-kusama/src/tests/teleport.rs index 25b0a187ae..7bcf0fdedd 100644 --- a/integration-tests/emulated/tests/people/people-kusama/src/tests/teleport.rs +++ b/integration-tests/emulated/tests/people/people-kusama/src/tests/teleport.rs @@ -88,7 +88,7 @@ fn system_para_limited_teleport_assets(t: SystemParaToRelayTest) -> DispatchResu } /// Limited Teleport of native asset from System Parachain to Relay Chain -/// should't work when there is not enough balance in Relay Chain's `CheckAccount` +/// shouldn't work when there is not enough balance in Relay Chain's `CheckAccount` #[test] fn limited_teleport_native_assets_from_system_para_to_relay_fails() { // Init values for Relay Chain diff --git a/integration-tests/emulated/tests/people/people-polkadot/src/lib.rs b/integration-tests/emulated/tests/people/people-polkadot/src/lib.rs index 2f80c85e69..23144ab8f1 100644 --- a/integration-tests/emulated/tests/people/people-polkadot/src/lib.rs +++ b/integration-tests/emulated/tests/people/people-polkadot/src/lib.rs @@ -40,11 +40,12 @@ pub use emulated_integration_tests_common::{ PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3, }; pub use parachains_common::{AccountId, Balance}; +pub use people_polkadot_runtime::ExistentialDeposit as PeoplePolkadotExistentialDeposit; pub use polkadot_system_emulated_network::{ people_polkadot_emulated_chain::{ genesis::ED as PEOPLE_KUSAMA_ED, PeoplePolkadotParaPallet as PeoplePolkadotPallet, }, - polkadot_emulated_chain::{genesis::ED as KUSAMA_ED, PolkadotRelayPallet as PolkadotPallet}, + polkadot_emulated_chain::{genesis::ED as POLKADOT_ED, PolkadotRelayPallet as PolkadotPallet}, PenpalAPara as PenpalA, PeoplePolkadotPara as PeoplePolkadot, PeoplePolkadotParaReceiver as PeoplePolkadotReceiver, PeoplePolkadotParaSender as PeoplePolkadotSender, PolkadotRelay as Polkadot, diff --git a/integration-tests/emulated/tests/people/people-polkadot/src/tests/claim_assets.rs b/integration-tests/emulated/tests/people/people-polkadot/src/tests/claim_assets.rs new file mode 100644 index 0000000000..ff7de41858 --- /dev/null +++ b/integration-tests/emulated/tests/people/people-polkadot/src/tests/claim_assets.rs @@ -0,0 +1,29 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Tests related to claiming assets trapped during XCM execution. + +use crate::*; + +use integration_tests_helpers::test_chain_can_claim_assets; +use xcm_executor::traits::DropAssets; + +#[test] +fn assets_can_be_claimed() { + let amount = PeoplePolkadotExistentialDeposit::get(); + let assets: Assets = (Parent, amount).into(); + + test_chain_can_claim_assets!(PeoplePolkadot, RuntimeCall, NetworkId::Polkadot, assets, amount); +} diff --git a/integration-tests/emulated/tests/people/people-polkadot/src/tests/mod.rs b/integration-tests/emulated/tests/people/people-polkadot/src/tests/mod.rs index 40ee1de643..b9ad9e3db4 100644 --- a/integration-tests/emulated/tests/people/people-polkadot/src/tests/mod.rs +++ b/integration-tests/emulated/tests/people/people-polkadot/src/tests/mod.rs @@ -13,5 +13,6 @@ // See the License for the specific language governing permissions and // limitations under the License. +mod claim_assets; mod governance; mod teleport; diff --git a/integration-tests/emulated/tests/people/people-polkadot/src/tests/teleport.rs b/integration-tests/emulated/tests/people/people-polkadot/src/tests/teleport.rs index bcdd036b71..c10d8c777f 100644 --- a/integration-tests/emulated/tests/people/people-polkadot/src/tests/teleport.rs +++ b/integration-tests/emulated/tests/people/people-polkadot/src/tests/teleport.rs @@ -28,7 +28,7 @@ use xcm_runtime_apis::{ #[test] fn teleport_from_and_to_relay() { - let amount = KUSAMA_ED * 1000; + let amount = POLKADOT_ED * 1000; let native_asset: Assets = (Here, amount).into(); test_relay_is_trusted_teleporter!( @@ -88,17 +88,17 @@ fn system_para_limited_teleport_assets(t: SystemParaToRelayTest) -> DispatchResu } /// Limited Teleport of native asset from System Parachain to Relay Chain -/// should't work when there is not enough balance in Relay Chain's `CheckAccount` +/// shouldn't work when there is not enough balance in Relay Chain's `CheckAccount` #[test] fn limited_teleport_native_assets_from_system_para_to_relay_fails() { // Init values for Relay Chain - let amount_to_send: Balance = KUSAMA_ED * 1000; + let amount_to_send: Balance = POLKADOT_ED * 1000; let destination = PeoplePolkadot::parent_location(); let beneficiary_id = PolkadotReceiver::get(); let assets = (Parent, amount_to_send).into(); // Fund a sender - PeoplePolkadot::fund_accounts(vec![(PeoplePolkadotSender::get(), KUSAMA_ED * 2_000u128)]); + PeoplePolkadot::fund_accounts(vec![(PeoplePolkadotSender::get(), POLKADOT_ED * 2_000u128)]); let test_args = TestContext { sender: PeoplePolkadotSender::get(), From 790ef91d8ba3215df1b6d76b49547d404f07e83f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=B3nal=20Murray?= Date: Tue, 20 Aug 2024 16:37:34 +0200 Subject: [PATCH 3/3] Trigger release v1.3.0 (#438) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trigger the v1.3.0 release with the following additional changes: - Bump `polkadot-runtime-parachains` version to get https://github.com/paritytech/polkadot-sdk/pull/5369 in [63cb34d](https://github.com/polkadot-fellows/runtimes/pull/438/commits/63cb34da7dd2437c1c2d47efd5b00c0820059db6) and update tests in [e718c64](https://github.com/polkadot-fellows/runtimes/pull/438/commits/e718c649ebd520a38f1990a40b5c31ed01f20c13). - Filter calls to `interlace` on the Polkadot Coretime Chain until the relay implementation matures in [1126cf7](https://github.com/polkadot-fellows/runtimes/pull/438/commits/1126cf7c0fce7a4e1e4e3894f1a17c905116a1cc). - Update all runtime versions to `1_003_000` in [08744df](https://github.com/polkadot-fellows/runtimes/pull/438/commits/08744dfba94fb341114bf5c8fdaec59848415854) TODO: - [x] Finalise changelog - [x] Wait for https://github.com/polkadot-fellows/runtimes/pull/433 - [x] Wait for https://github.com/polkadot-fellows/runtimes/pull/364 Closes #186 --------- Co-authored-by: Bastian Köcher Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> Co-authored-by: fellowship-merge-bot[bot] <151052383+fellowship-merge-bot[bot]@users.noreply.github.com> --- CHANGELOG.md | 19 ++++++--------- Cargo.lock | 16 ++++++------- Cargo.toml | 2 +- .../src/tests/coretime_interface.rs | 23 +++++++++++++++++-- .../src/tests/coretime_interface.rs | 23 +++++++++++++++++-- relay/kusama/src/lib.rs | 2 +- relay/polkadot/src/lib.rs | 2 +- .../asset-hubs/asset-hub-kusama/src/lib.rs | 4 ++-- .../asset-hubs/asset-hub-polkadot/src/lib.rs | 2 +- .../bridge-hubs/bridge-hub-kusama/src/lib.rs | 2 +- .../bridge-hub-polkadot/src/lib.rs | 2 +- .../collectives-polkadot/src/lib.rs | 2 +- .../coretime/coretime-kusama/src/lib.rs | 2 +- .../coretime/coretime-polkadot/src/lib.rs | 13 +++++++---- system-parachains/encointer/src/lib.rs | 2 +- .../gluttons/glutton-kusama/src/lib.rs | 2 +- .../people/people-kusama/src/lib.rs | 2 +- .../people/people-polkadot/src/lib.rs | 2 +- 18 files changed, 80 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d351bea8b..813ae52939 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ Changelog for the runtimes governed by the Polkadot Fellowship. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). -## [Unreleased] +## [1.3.0] 20.08.2024 ### Added @@ -15,15 +15,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Core-Fellowship: new `promote_fast` call ([runtimes#381](https://github.com/polkadot-fellows/runtimes/pull/381), [SDK v1.14 #4877](https://github.com/paritytech/polkadot-sdk/pull/4877)). - Pallet ranked collective: max member count per rank ([runtimes#381](https://github.com/polkadot-fellows/runtimes/pull/381), [SDK v1.14 #4807](https://github.com/paritytech/polkadot-sdk/pull/4807)). - All runtimes: XcmPaymentApi and DryRunApi ([polkadot-fellows/runtimes#380](https://github.com/polkadot-fellows/runtimes/pull/380)) +- Fast promotion tracks for the Fellowship ranks I-III ([polkadot-fellows/runtimes#356](https://github.com/polkadot-fellows/runtimes/pull/356)). - All runtimes: add `LocationToAccountApi` ([polkadot-fellows/runtimes#413](https://github.com/polkadot-fellows/runtimes/pull/413)) - Enable Agile Coretime on Polkadot ([polkadot-fellows/runtimes#401](https://github.com/polkadot-fellows/runtimes/pull/401)) - Add the Polkadot Coretime Chain runtime ([polkadot-fellows/runtimes#410](https://github.com/polkadot-fellows/runtimes/pull/410)) - Kusama: Add a "Spokesperson" proxy type only allowed to send remarks ([polkadot-fellows/runtimes#430](https://github.com/polkadot-fellows/runtimes/pull/430)) - Add the Polkadot and Kusama Coretime Chain specs ([polkadot-fellows/runtimes#432](https://github.com/polkadot-fellows/runtimes/pull/432)) +- Migration to remove all but the 21 first elected Head Ambassador members from the Program ([polkadot-fellows/runtimes#422](https://github.com/polkadot-fellows/runtimes/pull/422)). - Kusama: Make the current inflation formula adjustable ([polkadot-fellows/runtimes#364](https://github.com/polkadot-fellows/runtimes/pull/364)) - Port Agile Coretime migration from polkadot-sdk in order to fix leases with gaps handling([polkadot-fellows/runtimes#426](https://github.com/polkadot-fellows/runtimes/pull/426)) - #### From [#322](https://github.com/polkadot-fellows/runtimes/pull/322): - Add `claim_assets` extrinsic to `pallet-xcm` ([SDK v1.9 #3403](https://github.com/paritytech/polkadot-sdk/pull/3403)). @@ -49,17 +50,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Ranked collective introduce `Add` and `Remove` origins ([SDK v1.8 #3212](https://github.com/paritytech/polkadot-sdk/pull/3212)). - Runtime apis to help with delegate-stake based Nomination Pools ([SDK v1.13 #4537](https://github.com/paritytech/polkadot-sdk/pull/4537)). -### Added - -- Fast promotion tracks for the Fellowship ranks I-III ([polkadot-fellows/runtimes#356](https://github.com/polkadot-fellows/runtimes/pull/356)). -- Migration to remove all but the 21 first elected Head Ambassador members from the Program ([polkadot-fellows/runtimes#422](https://github.com/polkadot-fellows/runtimes/pull/422)). - ### Changed - Polkadot chains: allow arbitrary XCM execution ([polkadot-fellows/runtimes#345](https://github.com/polkadot-fellows/runtimes/pull/345)). - Bounties: Remove payout delay ([polkadot-fellows/runtimes#386](https://github.com/polkadot-fellows/runtimes/pull/386)). - Polkadot System Chains: Reduce the base transaction fee by half ([polkadot-fellows/runtimes#398](https://github.com/polkadot-fellows/runtimes/pull/398)). - Asset Hubs: setup auto incremented asset id to 50_000_000 for trust backed assets ([polkadot-fellows/runtimes#414](https://github.com/polkadot-fellows/runtimes/pull/414)). +- Upgrade dependencies to the [polkadot-sdk@1.13.0](https://github.com/paritytech/polkadot-sdk/releases/tag/polkadot-v1.13.0) release ([polkadot-fellows/runtimes#332](https://github.com/polkadot-fellows/runtimes/pull/332)). +- Filter `interlace` calls on the Polkadot Coretime Chain until the Relay chain implementation is more mature ([polkadot-fellows/runtimes#438](https://github.com/polkadot-fellows/runtimes/pull/438)). #### From [#322](https://github.com/polkadot-fellows/runtimes/pull/322): @@ -82,6 +80,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - `pallet-referenda`: Ensure to schedule referenda earliest at the next block ([runtimes#381](https://github.com/polkadot-fellows/runtimes/pull/381), [SDK v1.14 #4823](https://github.com/paritytech/polkadot-sdk/pull/4823)). - Don't partially modify HRMP pages ([runtimes#381](https://github.com/polkadot-fellows/runtimes/pull/381), [SDK v1.14 #4710](https://github.com/paritytech/polkadot-sdk/pull/4710)). - Coretime Chain: mitigate behaviour with many assignments on one core ([runtimes#434][https://github.com/polkadot-fellows/runtimes/pull/434]). +- Port Agile Coretime migration from polkadot-sdk in order to fix leases with gaps handling([polkadot-fellows/runtimes#426](https://github.com/polkadot-fellows/runtimes/pull/426)) #### From [#322](https://github.com/polkadot-fellows/runtimes/pull/322): @@ -120,7 +119,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Remove deprecated calls from treasury pallet ([runtimes#381](https://github.com/polkadot-fellows/runtimes/pull/381), [SDK v1.14 #3820](https://github.com/paritytech/polkadot-sdk/pull/3820)). - Treasury pallet: - remove unused config parameters ([runtimes#381](https://github.com/polkadot-fellows/runtimes/pull/381), [SDK v1.14 #4831](https://github.com/paritytech/polkadot-sdk/pull/4831)). - Remove Identity from Polkadot Relay Chain ([runtimes#415](https://github.com/polkadot-fellows/runtimes/pull/415)) -- Kusama: Remove unused Snowbridge code and configs ([polkadot-fellows/runtimes#411](https://github.com/polkadot-fellows/runtimes/pull/411) +- Kusama: Remove unused Snowbridge code and configs ([polkadot-fellows/runtimes#411](https://github.com/polkadot-fellows/runtimes/pull/411)). - Remove the identity ops pallet after the invalid judgments have been cleared ([polkadot-fellows/runtimes#408](https://github.com/polkadot-fellows/runtimes/pull/408)). #### From [#322](https://github.com/polkadot-fellows/runtimes/pull/322): @@ -132,10 +131,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Pallet-xcm: deprecate transfer extrinsics without weight limit ([SDK v1.10 #3927](https://github.com/paritytech/polkadot-sdk/pull/3927)). - Remove `parametrized-consensus-hook` feature ([SDK v1.13 #4380](https://github.com/paritytech/polkadot-sdk/pull/4380)). -### Based on Polkadot-SDK - -- Upgrade dependencies to the [polkadot-sdk@1.13.0](https://github.com/paritytech/polkadot-sdk/releases/tag/polkadot-v1.13.0) release ([polkadot-fellows/runtimes#332](https://github.com/polkadot-fellows/runtimes/pull/332)) - ## [1.2.8] 03.07.2024 ### Changed diff --git a/Cargo.lock b/Cargo.lock index 207caffac2..5afde4035a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4597,9 +4597,9 @@ dependencies = [ [[package]] name = "frame-system" -version = "36.0.0" +version = "36.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c2f10b6943da5d00f45b1b07b101bea49647d0e6c7e755b2852fd947072d7ee" +checksum = "d19f388280c14dbabcee2a817e1123c59c55847c6d07a5b5ca901b34a5910093" dependencies = [ "cfg-if", "docify", @@ -10176,9 +10176,9 @@ dependencies = [ [[package]] name = "polkadot-runtime-parachains" -version = "15.0.1" +version = "15.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3df740bff0b29ba4cd8c8874d7f8fb90e5722c24a7354d2e96d15e7121c1525e" +checksum = "a6cb1cf1fa41c64b0b515a33d7bd388c3af0de31e5f93bd4c2b220e408f7f968" dependencies = [ "bitflags 1.3.2", "bitvec", @@ -14435,9 +14435,9 @@ dependencies = [ [[package]] name = "staging-xcm" -version = "14.0.1" +version = "14.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "536c5c8f8f25589e714a3be6b068d174debcc882e648dc9b0c3bd6ce45434de3" +checksum = "f2b7b5f531c6bf9629514ef8e5fda0e9e80dd84516957f710940d0e01d3fb36c" dependencies = [ "array-bytes", "bounded-collections", @@ -16649,9 +16649,9 @@ dependencies = [ [[package]] name = "xcm-procedural" -version = "10.0.0" +version = "10.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0fd01495dfeb643167557631b34b54d312c1e70cf7eb64249ab687d84fd6045" +checksum = "87fb4f14094d65c500a59bcf540cf42b99ee82c706edd6226a92e769ad60563e" dependencies = [ "Inflector", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 8c6e70033a..4170bed995 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -187,7 +187,7 @@ polkadot-system-emulated-network = { path = "integration-tests/emulated/networks primitive-types = { version = "0.12.2", default-features = false } frame-metadata-hash-extension = { version = "0.4.0", default-features = false } remote-externalities = { version = "0.43.0", package = "frame-remote-externalities" } -runtime-parachains = { version = "15.0.1", default-features = false, package = "polkadot-runtime-parachains" } +runtime-parachains = { version = "15.0.2", default-features = false, package = "polkadot-runtime-parachains" } sc-chain-spec = { version = "35.0.0" } sc-network = { version = "0.42.0" } scale-info = { version = "2.10.0", default-features = false } diff --git a/integration-tests/emulated/tests/coretime/coretime-kusama/src/tests/coretime_interface.rs b/integration-tests/emulated/tests/coretime/coretime-kusama/src/tests/coretime_interface.rs index 435bde8dba..1f7d513829 100644 --- a/integration-tests/emulated/tests/coretime/coretime-kusama/src/tests/coretime_interface.rs +++ b/integration-tests/emulated/tests/coretime/coretime-kusama/src/tests/coretime_interface.rs @@ -137,8 +137,6 @@ fn transact_hardcoded_weights_are_sane() { Kusama::ext_wrapper(|| { block_number_cursor = ::System::block_number(); }); - - dbg!(&block_number_cursor); } // In this block we trigger assign core. @@ -201,4 +199,25 @@ fn transact_hardcoded_weights_are_sane() { ] ); }); + + // Here we receive and process the notify_revenue XCM with zero revenue. + CoretimeKusama::execute_with(|| { + // Hooks don't run in emulated tests - workaround. + ::Broker::on_initialize( + ::System::block_number(), + ); + + assert_expected_events!( + CoretimeKusama, + vec![ + CoretimeEvent::MessageQueue( + pallet_message_queue::Event::Processed { success: true, .. } + ) => {}, + // Zero revenue in first timeslice so history is immediately dropped. + CoretimeEvent::Broker( + pallet_broker::Event::HistoryDropped { when: 0, revenue: 0 } + ) => {}, + ] + ); + }); } diff --git a/integration-tests/emulated/tests/coretime/coretime-polkadot/src/tests/coretime_interface.rs b/integration-tests/emulated/tests/coretime/coretime-polkadot/src/tests/coretime_interface.rs index 144bd37fa9..c0317301f2 100644 --- a/integration-tests/emulated/tests/coretime/coretime-polkadot/src/tests/coretime_interface.rs +++ b/integration-tests/emulated/tests/coretime/coretime-polkadot/src/tests/coretime_interface.rs @@ -137,8 +137,6 @@ fn transact_hardcoded_weights_are_sane() { Polkadot::ext_wrapper(|| { block_number_cursor = ::System::block_number(); }); - - dbg!(&block_number_cursor); } // In this block we trigger assign core. @@ -201,4 +199,25 @@ fn transact_hardcoded_weights_are_sane() { ] ); }); + + // Here we receive and process the notify_revenue XCM with zero revenue. + CoretimePolkadot::execute_with(|| { + // Hooks don't run in emulated tests - workaround. + ::Broker::on_initialize( + ::System::block_number(), + ); + + assert_expected_events!( + CoretimePolkadot, + vec![ + CoretimeEvent::MessageQueue( + pallet_message_queue::Event::Processed { success: true, .. } + ) => {}, + // Zero revenue in first timeslice so history is immediately dropped. + CoretimeEvent::Broker( + pallet_broker::Event::HistoryDropped { when: 0, revenue: 0 } + ) => {}, + ] + ); + }); } diff --git a/relay/kusama/src/lib.rs b/relay/kusama/src/lib.rs index 1be9dc612c..f36bbe75cc 100644 --- a/relay/kusama/src/lib.rs +++ b/relay/kusama/src/lib.rs @@ -172,7 +172,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("kusama"), impl_name: create_runtime_str!("parity-kusama"), authoring_version: 2, - spec_version: 1_002_008, + spec_version: 1_003_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 26, diff --git a/relay/polkadot/src/lib.rs b/relay/polkadot/src/lib.rs index 52c7a33280..bb7ec1344f 100644 --- a/relay/polkadot/src/lib.rs +++ b/relay/polkadot/src/lib.rs @@ -158,7 +158,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("polkadot"), impl_name: create_runtime_str!("parity-polkadot"), authoring_version: 0, - spec_version: 1_002_008, + spec_version: 1_003_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 26, diff --git a/system-parachains/asset-hubs/asset-hub-kusama/src/lib.rs b/system-parachains/asset-hubs/asset-hub-kusama/src/lib.rs index 1dc644fb8a..0e3db3440f 100644 --- a/system-parachains/asset-hubs/asset-hub-kusama/src/lib.rs +++ b/system-parachains/asset-hubs/asset-hub-kusama/src/lib.rs @@ -121,7 +121,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("statemine"), impl_name: create_runtime_str!("statemine"), authoring_version: 1, - spec_version: 1_002_006, + spec_version: 1_003_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 15, @@ -137,7 +137,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("statemine"), impl_name: create_runtime_str!("statemine"), authoring_version: 1, - spec_version: 1_002_008, + spec_version: 1_003_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 15, diff --git a/system-parachains/asset-hubs/asset-hub-polkadot/src/lib.rs b/system-parachains/asset-hubs/asset-hub-polkadot/src/lib.rs index 73fb67cd59..67522fcd60 100644 --- a/system-parachains/asset-hubs/asset-hub-polkadot/src/lib.rs +++ b/system-parachains/asset-hubs/asset-hub-polkadot/src/lib.rs @@ -155,7 +155,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("statemint"), impl_name: create_runtime_str!("statemint"), authoring_version: 1, - spec_version: 1_002_008, + spec_version: 1_003_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 15, diff --git a/system-parachains/bridge-hubs/bridge-hub-kusama/src/lib.rs b/system-parachains/bridge-hubs/bridge-hub-kusama/src/lib.rs index 92dbee597e..405eaa4891 100644 --- a/system-parachains/bridge-hubs/bridge-hub-kusama/src/lib.rs +++ b/system-parachains/bridge-hubs/bridge-hub-kusama/src/lib.rs @@ -186,7 +186,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("bridge-hub-kusama"), impl_name: create_runtime_str!("bridge-hub-kusama"), authoring_version: 1, - spec_version: 1_002_008, + spec_version: 1_003_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 5, diff --git a/system-parachains/bridge-hubs/bridge-hub-polkadot/src/lib.rs b/system-parachains/bridge-hubs/bridge-hub-polkadot/src/lib.rs index 3c2c0be48a..8c2aa532f3 100644 --- a/system-parachains/bridge-hubs/bridge-hub-polkadot/src/lib.rs +++ b/system-parachains/bridge-hubs/bridge-hub-polkadot/src/lib.rs @@ -169,7 +169,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("bridge-hub-polkadot"), impl_name: create_runtime_str!("bridge-hub-polkadot"), authoring_version: 1, - spec_version: 1_002_008, + spec_version: 1_003_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 4, diff --git a/system-parachains/collectives/collectives-polkadot/src/lib.rs b/system-parachains/collectives/collectives-polkadot/src/lib.rs index 66327c1ce6..8dcd46e3ea 100644 --- a/system-parachains/collectives/collectives-polkadot/src/lib.rs +++ b/system-parachains/collectives/collectives-polkadot/src/lib.rs @@ -121,7 +121,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("collectives"), impl_name: create_runtime_str!("collectives"), authoring_version: 1, - spec_version: 1_002_008, + spec_version: 1_003_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 7, diff --git a/system-parachains/coretime/coretime-kusama/src/lib.rs b/system-parachains/coretime/coretime-kusama/src/lib.rs index 4b6a296024..4efe55b25f 100644 --- a/system-parachains/coretime/coretime-kusama/src/lib.rs +++ b/system-parachains/coretime/coretime-kusama/src/lib.rs @@ -145,7 +145,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("coretime-kusama"), impl_name: create_runtime_str!("coretime-kusama"), authoring_version: 1, - spec_version: 1_002_006, + spec_version: 1_003_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, diff --git a/system-parachains/coretime/coretime-polkadot/src/lib.rs b/system-parachains/coretime/coretime-polkadot/src/lib.rs index 8404f7a2ea..6aac18b627 100644 --- a/system-parachains/coretime/coretime-polkadot/src/lib.rs +++ b/system-parachains/coretime/coretime-polkadot/src/lib.rs @@ -180,17 +180,22 @@ parameter_types! { /// Filter out credit purchase calls until the credit system is implemented. Otherwise, users /// may have chance of locking their funds forever on purchased credits they cannot use. -pub struct IsBrokerCreditPurchaseCall; -impl Contains for IsBrokerCreditPurchaseCall { +/// Also filter the interlace call until the relay can support this fully. +pub struct IsFilteredBrokerCall; +impl Contains for IsFilteredBrokerCall { fn contains(c: &RuntimeCall) -> bool { - matches!(c, RuntimeCall::Broker(pallet_broker::Call::purchase_credit { .. })) + matches!( + c, + RuntimeCall::Broker(pallet_broker::Call::purchase_credit { .. }) | + RuntimeCall::Broker(pallet_broker::Call::interlace { .. }) + ) } } // Configure FRAME pallets to include in runtime. #[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Runtime { - type BaseCallFilter = EverythingBut; + type BaseCallFilter = EverythingBut; /// The identifier used to distinguish between accounts. type AccountId = AccountId; /// The nonce type for storing how many extrinsics an account has signed. diff --git a/system-parachains/encointer/src/lib.rs b/system-parachains/encointer/src/lib.rs index e4827dddae..c071af71b2 100644 --- a/system-parachains/encointer/src/lib.rs +++ b/system-parachains/encointer/src/lib.rs @@ -133,7 +133,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("encointer-parachain"), impl_name: create_runtime_str!("encointer-parachain"), authoring_version: 1, - spec_version: 1_002_006, + spec_version: 1_003_000, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 4, diff --git a/system-parachains/gluttons/glutton-kusama/src/lib.rs b/system-parachains/gluttons/glutton-kusama/src/lib.rs index 6b61f2053f..6392e0a9d8 100644 --- a/system-parachains/gluttons/glutton-kusama/src/lib.rs +++ b/system-parachains/gluttons/glutton-kusama/src/lib.rs @@ -91,7 +91,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("glutton"), impl_name: create_runtime_str!("glutton"), authoring_version: 1, - spec_version: 1_002_006, + spec_version: 1_003_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, diff --git a/system-parachains/people/people-kusama/src/lib.rs b/system-parachains/people/people-kusama/src/lib.rs index 68305b9620..651473abcb 100644 --- a/system-parachains/people/people-kusama/src/lib.rs +++ b/system-parachains/people/people-kusama/src/lib.rs @@ -177,7 +177,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("people-kusama"), impl_name: create_runtime_str!("people-kusama"), authoring_version: 1, - spec_version: 1_002_006, + spec_version: 1_003_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, diff --git a/system-parachains/people/people-polkadot/src/lib.rs b/system-parachains/people/people-polkadot/src/lib.rs index 5aaac6a0ed..3333957713 100644 --- a/system-parachains/people/people-polkadot/src/lib.rs +++ b/system-parachains/people/people-polkadot/src/lib.rs @@ -147,7 +147,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("people-polkadot"), impl_name: create_runtime_str!("people-polkadot"), authoring_version: 1, - spec_version: 1_002_007, + spec_version: 1_003_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 0,