From 84b1d322a66379bd227fad24877b3688f62b1cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Sun, 18 Aug 2024 22:15:05 +0200 Subject: [PATCH 01/27] create pallet xcm-weight-trader --- Cargo.lock | 20 + Cargo.toml | 3 + pallets/xcm-weight-trader/Cargo.toml | 52 +++ pallets/xcm-weight-trader/src/benchmarking.rs | 139 +++++++ pallets/xcm-weight-trader/src/lib.rs | 387 ++++++++++++++++++ pallets/xcm-weight-trader/src/mock.rs | 191 +++++++++ pallets/xcm-weight-trader/src/tests.rs | 340 +++++++++++++++ pallets/xcm-weight-trader/src/weights.rs | 50 +++ primitives/xcm/src/fee_handlers.rs | 2 +- 9 files changed, 1183 insertions(+), 1 deletion(-) create mode 100644 pallets/xcm-weight-trader/Cargo.toml create mode 100644 pallets/xcm-weight-trader/src/benchmarking.rs create mode 100644 pallets/xcm-weight-trader/src/lib.rs create mode 100644 pallets/xcm-weight-trader/src/mock.rs create mode 100644 pallets/xcm-weight-trader/src/tests.rs create mode 100644 pallets/xcm-weight-trader/src/weights.rs diff --git a/Cargo.lock b/Cargo.lock index 10263419eb..fc2b325f36 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10535,6 +10535,26 @@ dependencies = [ "xcm-primitives 0.1.1", ] +[[package]] +name = "pallet-xcm-weight-trader" +version = "0.1.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-tracing", + "staging-xcm", + "staging-xcm-executor", +] + [[package]] name = "parachains-common" version = "7.0.0" diff --git a/Cargo.toml b/Cargo.toml index 0578bfc1bf..9fb87e34ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ members = [ "pallets/precompile-benchmarks", "pallets/proxy-genesis-companion", "pallets/xcm-transactor", + "pallets/xcm-weight-trader", "precompiles/balances-erc20", "precompiles/batch", "precompiles/call-permit", @@ -107,6 +108,7 @@ pallet-parachain-staking = { path = "pallets/parachain-staking", default-feature pallet-precompile-benchmarks = { path = "pallets/precompile-benchmarks", default-features = false } pallet-proxy-genesis-companion = { path = "pallets/proxy-genesis-companion", default-features = false } pallet-xcm-transactor = { path = "pallets/xcm-transactor", default-features = false } +pallet-xcm-weight-trader = { path = "pallets/xcm-weight-trader", default-features = false } precompile-foreign-asset-migrator = { path = "precompiles/foreign-asset-migrator", default-features = false } xcm-primitives = { path = "primitives/xcm", default-features = false } @@ -184,6 +186,7 @@ sp-runtime-interface = { git = "https://github.com/moonbeam-foundation/polkadot- sp-session = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.11.0", default-features = false } sp-std = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.11.0", default-features = false } sp-state-machine = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.11.0", default-features = false } +sp-tracing = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.11.0", default-features = false } sp-transaction-pool = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.11.0", default-features = false } sp-trie = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.11.0", default-features = false } sp-version = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.11.0", default-features = false } diff --git a/pallets/xcm-weight-trader/Cargo.toml b/pallets/xcm-weight-trader/Cargo.toml new file mode 100644 index 0000000000..c322f3b62a --- /dev/null +++ b/pallets/xcm-weight-trader/Cargo.toml @@ -0,0 +1,52 @@ +[package] +authors = {workspace = true} +description = "A pallet to trade weight for XCM execution" +edition = "2021" +name = "pallet-xcm-weight-trader" +version = "0.1.0" + +[dependencies] +log = {workspace = true} + +# Substrate +frame-support = {workspace = true} +frame-system = {workspace = true} +pallet-balances = {workspace = true} +parity-scale-codec = {workspace = true} +scale-info = {workspace = true, features = ["derive"]} +sp-core = {workspace = true} +sp-io = {workspace = true} +sp-runtime = {workspace = true} +sp-std = {workspace = true} + +# Polkadot +xcm = { workspace = true } +xcm-executor = { workspace = true } + +# Benchmarks +frame-benchmarking = {workspace = true, optional = true} + +[dev-dependencies] +frame-benchmarking = {workspace = true, features = ["std"]} +pallet-balances = {workspace = true, features = ["std", "insecure_zero_ed"]} +sp-tracing = {workspace = true, features = ["std"] } + +[features] +default = ["std"] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-system/runtime-benchmarks" +] +std = [ + "frame-support/std", + "frame-system/std", + "pallet-balances/std", + "scale-info/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", + "xcm/std", + "xcm-executor/std" +] +try-runtime = ["frame-support/try-runtime"] \ No newline at end of file diff --git a/pallets/xcm-weight-trader/src/benchmarking.rs b/pallets/xcm-weight-trader/src/benchmarking.rs new file mode 100644 index 0000000000..3f16c2d785 --- /dev/null +++ b/pallets/xcm-weight-trader/src/benchmarking.rs @@ -0,0 +1,139 @@ +// Copyright 2024 Moonbeam foundation +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +#![cfg(feature = "runtime-benchmarks")] + +use super::*; + +use frame_benchmarking::{v2::*, BenchmarkError}; +use frame_support::traits::EnsureOrigin; +use frame_system::EventRecord; + +fn assert_last_event(generic_event: ::RuntimeEvent) { + let events = frame_system::Pallet::::events(); + let system_event: ::RuntimeEvent = generic_event.into(); + // compare to the last event record + let EventRecord { event, .. } = &events[events.len() - 1]; + assert_eq!(event, &system_event); +} + +fn setup_one_asset() -> Result { + let origin = T::AddSupportedAssetOrigin::try_successful_origin() + .map_err(|_| BenchmarkError::Weightless)?; + + let location = T::NotFilteredLocation::get(); + + Pallet::::add_asset(origin, location.clone(), 1_000).expect("fail to setup asset"); + + Ok(location) +} + +#[benchmarks] +mod benchmarks { + use super::*; + + #[benchmark] + fn add_asset() -> Result<(), BenchmarkError> { + let origin = T::AddSupportedAssetOrigin::try_successful_origin() + .map_err(|_| BenchmarkError::Weightless)?; + + let location = T::NotFilteredLocation::get(); + + #[extrinsic_call] + _(origin as T::RuntimeOrigin, location.clone(), 1_000); + + assert_last_event::( + Event::SupportedAssetAdded { + location, + units_for_one_billion_native: 1_000, + } + .into(), + ); + Ok(()) + } + + #[benchmark] + fn edit_asset() -> Result<(), BenchmarkError> { + // Setup one asset + let location = setup_one_asset::()?; + + let origin = T::EditSupportedAssetOrigin::try_successful_origin() + .map_err(|_| BenchmarkError::Weightless)?; + + #[extrinsic_call] + _(origin as T::RuntimeOrigin, location.clone(), 2_000); + + assert_last_event::( + Event::SupportedAssetEdited { + location, + units_for_one_billion_native: 2_000, + } + .into(), + ); + Ok(()) + } + + #[benchmark] + fn resume_asset_support() -> Result<(), BenchmarkError> { + // Setup one asset + let location = setup_one_asset::()?; + let pause_origin = T::PauseSupportedAssetOrigin::try_successful_origin() + .map_err(|_| BenchmarkError::Weightless)?; + Pallet::::pause_asset_support(pause_origin, location.clone()) + .expect("fail to pause asset"); + + let origin = T::ResumeSupportedAssetOrigin::try_successful_origin() + .map_err(|_| BenchmarkError::Weightless)?; + + #[extrinsic_call] + _(origin as T::RuntimeOrigin, location.clone()); + + assert_last_event::(Event::ResumeAssetSupport { location }.into()); + Ok(()) + } + + #[benchmark] + fn pause_asset_support() -> Result<(), BenchmarkError> { + // Setup one asset + let location = setup_one_asset::()?; + + let origin = T::PauseSupportedAssetOrigin::try_successful_origin() + .map_err(|_| BenchmarkError::Weightless)?; + + #[extrinsic_call] + _(origin as T::RuntimeOrigin, location.clone()); + + assert_last_event::(Event::PauseAssetSupport { location }.into()); + Ok(()) + } + + #[benchmark] + fn remove_asset() -> Result<(), BenchmarkError> { + // Setup one asset + let location = setup_one_asset::()?; + + let origin = T::RemoveSupportedAssetOrigin::try_successful_origin() + .map_err(|_| BenchmarkError::Weightless)?; + + #[extrinsic_call] + _(origin as T::RuntimeOrigin, location.clone()); + + assert_last_event::(Event::SupportedAssetRemoved { location }.into()); + Ok(()) + } + + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test,); +} diff --git a/pallets/xcm-weight-trader/src/lib.rs b/pallets/xcm-weight-trader/src/lib.rs new file mode 100644 index 0000000000..913512407e --- /dev/null +++ b/pallets/xcm-weight-trader/src/lib.rs @@ -0,0 +1,387 @@ +// Copyright 2024 Moonbeam foundation +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! # A pallet to trade weight for XCM execution + +#![allow(non_camel_case_types)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; + +pub mod weights; + +pub use pallet::*; +pub use weights::WeightInfo; + +use frame_support::pallet; +use frame_support::pallet_prelude::*; +use frame_support::traits::Contains; +use frame_support::weights::WeightToFee; +use frame_system::pallet_prelude::*; +use sp_runtime::traits::{Convert, Zero}; +use xcm::latest::{ + Asset, AssetId as XcmAssetId, Error as XcmError, Fungibility, Location, XcmContext, +}; +use xcm_executor::traits::{TransactAsset, WeightTrader}; + +#[pallet] +pub mod pallet { + use super::*; + + /// Pallet for multi block migrations + #[pallet::pallet] + pub struct Pallet(PhantomData); + + /// Configuration trait of this pallet. + #[pallet::config] + pub trait Config: frame_system::Config { + /// Convert `T::AccountId` to `Location`. + type AccountIdToLocation: Convert; + + /// Origin that is allowed to register a supported asset + type AddSupportedAssetOrigin: EnsureOrigin; + + /// A filter to forbid some XCM Location to be supported for fees. + /// if you don't use it, put "Everything". + type AssetLocationFilter: Contains; + + /// How to withdraw and deposit an asset. + type AssetTransactor: TransactAsset; + + /// The native balance type. + type Balance: TryInto; + + /// Origin that is allowed to edit a supported asset units per seconds + type EditSupportedAssetOrigin: EnsureOrigin; + + /// XCM Location for native curreny + type NativeLocation: Get; + + /// Origin that is allowed to pause a supported asset + type PauseSupportedAssetOrigin: EnsureOrigin; + + /// Origin that is allowed to remove a supported asset + type RemoveSupportedAssetOrigin: EnsureOrigin; + + /// The overarching event type. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// Origin that is allowed to unpause a supported asset + type ResumeSupportedAssetOrigin: EnsureOrigin; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; + + /// Convert a weight value into deductible native balance. + type WeightToFee: WeightToFee; + + /// Account that will receive xcm fees + type XcmFeesAccount: Get; + + /// The benchmarks need a location that pass the filter AssetLocationFilter + #[cfg(feature = "runtime-benchmarks")] + type NotFilteredLocation: Get; + } + + /// Stores all supported assets per XCM Location. + /// The u128 is the number of units equal to one billion units of native currency. + /// The boolean specify if the support for this asset is active + #[pallet::storage] + #[pallet::getter(fn supported_assets)] + pub type SupportedAssets = StorageMap<_, Blake2_128Concat, Location, (bool, u128)>; + + #[pallet::error] + pub enum Error { + /// The given asset was already added + AssetAlreadyAdded, + /// The given asset was already paused + AssetAlreadyPaused, + /// The given asset was not found + AssetNotFound, + /// The given asset is not paused + AssetNotPaused, + /// XCM location filtered + XcmLocationFiltered, + /// The units price cannot be zero + UnitsCannotBeZero, + } + + #[pallet::event] + #[pallet::generate_deposit(pub(crate) fn deposit_event)] + pub enum Event { + /// New supported asset is registered + SupportedAssetAdded { + location: Location, + units_for_one_billion_native: u128, + }, + /// Changed the amount of units we are charging per execution second for a given asset + SupportedAssetEdited { + location: Location, + units_for_one_billion_native: u128, + }, + /// Pause support for a given asset + PauseAssetSupport { location: Location }, + /// Resume support for a given asset + ResumeAssetSupport { location: Location }, + /// Supported asset type for fee payment removed + SupportedAssetRemoved { location: Location }, + } + + #[pallet::call] + impl Pallet { + #[pallet::call_index(0)] + #[pallet::weight(T::WeightInfo::add_asset())] + pub fn add_asset( + origin: OriginFor, + location: Location, + units_for_one_billion_native: u128, + ) -> DispatchResult { + T::AddSupportedAssetOrigin::ensure_origin(origin)?; + + ensure!( + units_for_one_billion_native != 0, + Error::::UnitsCannotBeZero + ); + ensure!( + !SupportedAssets::::contains_key(&location), + Error::::AssetAlreadyAdded + ); + ensure!( + T::AssetLocationFilter::contains(&location), + Error::::XcmLocationFiltered + ); + + SupportedAssets::::insert(&location, (true, units_for_one_billion_native)); + + Self::deposit_event(Event::SupportedAssetAdded { + location, + units_for_one_billion_native, + }); + + Ok(()) + } + + #[pallet::call_index(1)] + #[pallet::weight(T::WeightInfo::edit_asset())] + pub fn edit_asset( + origin: OriginFor, + location: Location, + units_for_one_billion_native: u128, + ) -> DispatchResult { + T::EditSupportedAssetOrigin::ensure_origin(origin)?; + + ensure!( + units_for_one_billion_native != 0, + Error::::UnitsCannotBeZero + ); + ensure!( + SupportedAssets::::contains_key(&location), + Error::::AssetNotFound + ); + + SupportedAssets::::insert(&location, (true, units_for_one_billion_native)); + + Self::deposit_event(Event::SupportedAssetEdited { + location, + units_for_one_billion_native, + }); + + Ok(()) + } + + #[pallet::call_index(2)] + #[pallet::weight(T::WeightInfo::pause_asset_support())] + pub fn pause_asset_support(origin: OriginFor, location: Location) -> DispatchResult { + T::PauseSupportedAssetOrigin::ensure_origin(origin)?; + + match SupportedAssets::::get(&location) { + Some((true, units_for_one_billion_native)) => { + SupportedAssets::::insert(&location, (false, units_for_one_billion_native)); + Self::deposit_event(Event::PauseAssetSupport { location }); + Ok(()) + } + Some((false, _)) => Err(Error::::AssetAlreadyPaused.into()), + None => Err(Error::::AssetNotFound.into()), + } + } + + #[pallet::call_index(3)] + #[pallet::weight(T::WeightInfo::resume_asset_support())] + pub fn resume_asset_support(origin: OriginFor, location: Location) -> DispatchResult { + T::ResumeSupportedAssetOrigin::ensure_origin(origin)?; + + match SupportedAssets::::get(&location) { + Some((false, units_for_one_billion_native)) => { + SupportedAssets::::insert(&location, (true, units_for_one_billion_native)); + Self::deposit_event(Event::ResumeAssetSupport { location }); + Ok(()) + } + Some((true, _)) => Err(Error::::AssetNotPaused.into()), + None => Err(Error::::AssetNotFound.into()), + } + } + + #[pallet::call_index(4)] + #[pallet::weight(T::WeightInfo::remove_asset())] + pub fn remove_asset(origin: OriginFor, location: Location) -> DispatchResult { + T::RemoveSupportedAssetOrigin::ensure_origin(origin)?; + + ensure!( + SupportedAssets::::contains_key(&location), + Error::::AssetNotFound + ); + + SupportedAssets::::remove(&location); + + Self::deposit_event(Event::SupportedAssetRemoved { location }); + + Ok(()) + } + } + + impl Pallet { + pub fn get_asset_units_for_one_billion_native(location: &Location) -> Option { + if let Some((true, ratio)) = SupportedAssets::::get(location) { + Some(ratio) + } else { + None + } + } + } +} + +struct Trader(Weight, Option, core::marker::PhantomData); + +impl WeightTrader for Trader { + fn new() -> Self { + Self(Weight::zero(), None, PhantomData) + } + fn buy_weight( + &mut self, + weight: Weight, + payment: xcm_executor::AssetsInHolding, + context: &XcmContext, + ) -> Result { + log::trace!(target: "xcm::weight", "UsingComponents::buy_weight weight: {:?}, payment: {:?}, context: {:?}", weight, payment, context); + + // Can only call one time + if self.1.is_some() { + return Err(XcmError::NotWithdrawable); + } + + // Consistency check for tests only, we should never panic in release mode + debug_assert_eq!(self.0, Weight::zero()); + + // We support only one fee asset per buy, so we take the first one. + let first_asset = payment + .clone() + .fungible_assets_iter() + .next() + .ok_or(XcmError::AssetNotFound)?; + + match (first_asset.id, first_asset.fun) { + (XcmAssetId(location), Fungibility::Fungible(_)) => { + let amount: u128 = if location == ::NativeLocation::get() { + ::WeightToFee::weight_to_fee(&weight) + .try_into() + .map_err(|_| XcmError::Overflow)? + } else if let Some(units_for_one_billion_native) = + Pallet::::get_asset_units_for_one_billion_native(&location) + { + let native_amount: u128 = + ::WeightToFee::weight_to_fee(&weight) + .try_into() + .map_err(|_| XcmError::Overflow)?; + units_for_one_billion_native * native_amount / 1_000_000_000u128 + } else { + return Err(XcmError::AssetNotFound); + }; + + // We dont need to proceed if the amount is 0 + // For cases (specially tests) where the asset is very cheap with respect + // to the weight needed + if amount.is_zero() { + return Ok(payment); + } + + let required = Asset { + fun: Fungibility::Fungible(amount), + id: XcmAssetId(location), + }; + let unused = payment + .checked_sub(required.clone()) + .map_err(|_| XcmError::TooExpensive)?; + + self.0 = weight; + self.1 = Some(required); + + return Ok(unused); + } + _ => return Err(XcmError::AssetNotFound), + } + } + + fn refund_weight(&mut self, weight: Weight, context: &XcmContext) -> Option { + log::trace!( + target: "xcm-weight-trader", + "refund_weight weight: {:?}, context: {:?}, available weight: {:?}, asset: {:?}", + weight, + context, + self.0, + self.1 + ); + let maybe_asset_to_refound = if let Some(Asset { + fun: Fungibility::Fungible(initial_amount), + id: XcmAssetId(location), + }) = &self.1 + { + let weight = weight.min(self.0); + let amount: u128 = ::WeightToFee::weight_to_fee(&weight) + .try_into() + .unwrap_or(u128::MAX); + let final_amount = amount.min(*initial_amount); + let amount_to_refound = initial_amount.saturating_sub(final_amount); + self.0 -= weight; + log::trace!(target: "xcm-weight-trader", "refund_weight amount to refund: {:?}", amount_to_refound); + Some(Asset { + fun: Fungibility::Fungible(amount_to_refound), + id: XcmAssetId(location.clone()), + }) + } else { + None + }; + self.1 = maybe_asset_to_refound.clone(); + maybe_asset_to_refound + } +} + +impl Drop for Trader { + fn drop(&mut self) { + if let Some(asset) = self.1.take() { + let res = T::AssetTransactor::deposit_asset( + &asset, + &T::AccountIdToLocation::convert(T::XcmFeesAccount::get()), + None, + ); + debug_assert!(res.is_ok()); + } + } +} diff --git a/pallets/xcm-weight-trader/src/mock.rs b/pallets/xcm-weight-trader/src/mock.rs new file mode 100644 index 0000000000..6a9e749459 --- /dev/null +++ b/pallets/xcm-weight-trader/src/mock.rs @@ -0,0 +1,191 @@ +// Copyright 2024 Moonbeam foundation +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! A minimal runtime including the multi block migrations pallet + +use super::*; +use crate as pallet_xcm_weight_trader; +use frame_support::{ + construct_runtime, ord_parameter_types, parameter_types, + traits::{Currency, Everything}, + weights::{constants::RocksDbWeight, IdentityFee}, +}; +use frame_system::EnsureSignedBy; +use sp_core::H256; +use sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup}, + BuildStorage, +}; +use xcm::latest::{Asset, Error as XcmError, Junction, Location, Result as XcmResult, XcmContext}; + +type AccountId = u64; +type Balance = u128; +type Block = frame_system::mocking::MockBlock; + +// Configure a mock runtime to test the pallet. +construct_runtime!( + pub enum Test + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + XcmWeightTrader: pallet_xcm_weight_trader::{Pallet, Call, Storage, Event}, + } +); + +parameter_types! { + pub const BlockHashCount: u32 = 250; + pub const SS58Prefix: u8 = 42; +} +impl frame_system::Config for Test { + type BaseCallFilter = Everything; + type DbWeight = RocksDbWeight; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeTask = RuntimeTask; + type Nonce = u64; + type Block = Block; + type RuntimeCall = RuntimeCall; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type BlockWeights = (); + type BlockLength = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; + type SingleBlockMigrations = (); + type MultiBlockMigrator = (); + type PreInherents = (); + type PostInherents = (); + type PostTransactions = (); +} + +parameter_types! { + pub const ExistentialDeposit: u128 = 0; +} +impl pallet_balances::Config for Test { + type MaxReserves = (); + type ReserveIdentifier = (); + type MaxLocks = (); + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + type RuntimeHoldReason = (); + type FreezeIdentifier = (); + type MaxFreezes = (); + type RuntimeFreezeReason = (); +} + +pub struct AccountIdToLocation; +impl Convert for AccountIdToLocation { + fn convert(account: AccountId) -> Location { + Location::new( + 0, + [Junction::AccountIndex64 { + network: None, + index: account, + }], + ) + } +} + +pub struct AssetLocationFilter; +impl Contains for AssetLocationFilter { + fn contains(location: &Location) -> bool { + *location == ::NativeLocation::get() || *location == Location::parent() + } +} + +pub struct MockAssetTransactor; +impl TransactAsset for MockAssetTransactor { + fn deposit_asset(asset: &Asset, who: &Location, _context: Option<&XcmContext>) -> XcmResult { + match (asset.id.clone(), asset.fun.clone()) { + (XcmAssetId(location), Fungibility::Fungible(amount)) => { + let who = match who.interior.iter().next() { + Some(Junction::AccountIndex64 { index, .. }) => index, + _ => panic!("invalid location"), + }; + if location == ::NativeLocation::get() { + let _ = Balances::deposit_creating(who, amount); + Ok(()) + } else if location == Location::parent() { + todo!() + } else { + Err(XcmError::AssetNotFound) + } + } + _ => Err(XcmError::AssetNotFound), + } + } +} + +ord_parameter_types! { + pub const AddAccount: u64 = 1; + pub const EditAccount: u64 = 2; + pub const PauseAccount: u64 = 3; + pub const ResumeAccount: u64 = 4; + pub const RemoveAccount: u64 = 5; +} + +parameter_types! { + pub NativeLocation: Location = Location::here(); + pub XcmFeesAccount: AccountId = 101; + pub NotFilteredLocation: Location = Location::parent(); +} + +impl Config for Test { + type AccountIdToLocation = AccountIdToLocation; + type AddSupportedAssetOrigin = EnsureSignedBy; + type AssetLocationFilter = AssetLocationFilter; + type AssetTransactor = MockAssetTransactor; + type Balance = Balance; + type EditSupportedAssetOrigin = EnsureSignedBy; + type NativeLocation = NativeLocation; + type PauseSupportedAssetOrigin = EnsureSignedBy; + type RemoveSupportedAssetOrigin = EnsureSignedBy; + type RuntimeEvent = RuntimeEvent; + type ResumeSupportedAssetOrigin = EnsureSignedBy; + type WeightInfo = (); + type WeightToFee = IdentityFee; + type XcmFeesAccount = XcmFeesAccount; + #[cfg(feature = "runtime-benchmarks")] + type NotFilteredLocation = NotFilteredLocation; +} + +pub fn new_test_ext() -> sp_io::TestExternalities { + sp_tracing::try_init_simple(); + let mut t = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap(); + + let balances = vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100)]; + pallet_balances::GenesisConfig:: { balances } + .assimilate_storage(&mut t) + .unwrap(); + + t.into() +} diff --git a/pallets/xcm-weight-trader/src/tests.rs b/pallets/xcm-weight-trader/src/tests.rs new file mode 100644 index 0000000000..de867aad77 --- /dev/null +++ b/pallets/xcm-weight-trader/src/tests.rs @@ -0,0 +1,340 @@ +// Copyright 2024 Moonbeam foundation +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Unit testing +use { + crate::mock::*, + crate::Error, + frame_support::{assert_noop, assert_ok}, + sp_runtime::DispatchError, + xcm::latest::{Asset, Error as XcmError, Junction, Location, Result as XcmResult}, +}; + +#[test] +fn test_add_supported_asset() { + new_test_ext().execute_with(|| { + // Call with bad origin + assert_noop!( + XcmWeightTrader::add_asset( + RuntimeOrigin::signed(EditAccount::get()), + Location::parent(), + 1_000, + ), + DispatchError::BadOrigin + ); + + // Call with invalid location + assert_noop!( + XcmWeightTrader::add_asset( + RuntimeOrigin::signed(AddAccount::get()), + Location::new(2, []), + 1_000, + ), + Error::::XcmLocationFiltered + ); + + // Call with invalid price + assert_noop!( + XcmWeightTrader::add_asset( + RuntimeOrigin::signed(AddAccount::get()), + Location::parent(), + 0, + ), + Error::::UnitsCannotBeZero + ); + + // Call with the right origin + assert_ok!(XcmWeightTrader::add_asset( + RuntimeOrigin::signed(AddAccount::get()), + Location::parent(), + 1_000, + )); + + // The account should be supported + assert_eq!( + XcmWeightTrader::get_asset_units_for_one_billion_native(&Location::parent()), + Some(1_000), + ); + + // Check storage + assert_eq!( + crate::pallet::SupportedAssets::::get(&Location::parent()), + Some((true, 1_000)) + ); + + // Try to add the same asset twice (should fail) + assert_noop!( + XcmWeightTrader::add_asset( + RuntimeOrigin::signed(AddAccount::get()), + Location::parent(), + 1_000, + ), + Error::::AssetAlreadyAdded + ); + }) +} + +#[test] +fn test_edit_supported_asset() { + new_test_ext().execute_with(|| { + // Should not be able to edit an asset not added yet + assert_noop!( + XcmWeightTrader::edit_asset( + RuntimeOrigin::signed(EditAccount::get()), + Location::parent(), + 2_000, + ), + Error::::AssetNotFound + ); + + // Setup (add a supported asset) + assert_ok!(XcmWeightTrader::add_asset( + RuntimeOrigin::signed(AddAccount::get()), + Location::parent(), + 1_000, + )); + assert_eq!( + XcmWeightTrader::get_asset_units_for_one_billion_native(&Location::parent()), + Some(1_000), + ); + + // Call with bad origin + assert_noop!( + XcmWeightTrader::edit_asset( + RuntimeOrigin::signed(AddAccount::get()), + Location::parent(), + 2_000, + ), + DispatchError::BadOrigin + ); + + // Call with invalid price + assert_noop!( + XcmWeightTrader::edit_asset( + RuntimeOrigin::signed(EditAccount::get()), + Location::parent(), + 0, + ), + Error::::UnitsCannotBeZero + ); + + // Call with right origin and valid params + assert_ok!(XcmWeightTrader::edit_asset( + RuntimeOrigin::signed(EditAccount::get()), + Location::parent(), + 2_000, + ),); + + // The account should be supported + assert_eq!( + XcmWeightTrader::get_asset_units_for_one_billion_native(&Location::parent()), + Some(2_000), + ); + + // Check storage + assert_eq!( + crate::pallet::SupportedAssets::::get(&Location::parent()), + Some((true, 2_000)) + ); + }) +} + +#[test] +fn test_pause_asset_support() { + new_test_ext().execute_with(|| { + // Should not be able to pause an asset not added yet + assert_noop!( + XcmWeightTrader::pause_asset_support( + RuntimeOrigin::signed(PauseAccount::get()), + Location::parent(), + ), + Error::::AssetNotFound + ); + + // Setup (add a supported asset) + assert_ok!(XcmWeightTrader::add_asset( + RuntimeOrigin::signed(AddAccount::get()), + Location::parent(), + 1_000, + )); + assert_eq!( + XcmWeightTrader::get_asset_units_for_one_billion_native(&Location::parent()), + Some(1_000), + ); + + // Call with bad origin + assert_noop!( + XcmWeightTrader::pause_asset_support( + RuntimeOrigin::signed(AddAccount::get()), + Location::parent(), + ), + DispatchError::BadOrigin + ); + + // Call with right origin and valid params + assert_ok!(XcmWeightTrader::pause_asset_support( + RuntimeOrigin::signed(PauseAccount::get()), + Location::parent(), + )); + + // The account should be paused + assert_eq!( + XcmWeightTrader::get_asset_units_for_one_billion_native(&Location::parent()), + None, + ); + + // Check storage + assert_eq!( + crate::pallet::SupportedAssets::::get(&Location::parent()), + Some((false, 1_000)) + ); + + // Should not be able to pause an asset already paused + assert_noop!( + XcmWeightTrader::pause_asset_support( + RuntimeOrigin::signed(PauseAccount::get()), + Location::parent(), + ), + Error::::AssetAlreadyPaused + ); + }) +} + +#[test] +fn test_resume_asset_support() { + new_test_ext().execute_with(|| { + // Setup (add a supported asset and pause it) + assert_ok!(XcmWeightTrader::add_asset( + RuntimeOrigin::signed(AddAccount::get()), + Location::parent(), + 1_000, + )); + assert_ok!(XcmWeightTrader::pause_asset_support( + RuntimeOrigin::signed(PauseAccount::get()), + Location::parent(), + )); + assert_eq!( + crate::pallet::SupportedAssets::::get(&Location::parent()), + Some((false, 1_000)) + ); + + // Call with bad origin + assert_noop!( + XcmWeightTrader::resume_asset_support( + RuntimeOrigin::signed(AddAccount::get()), + Location::parent(), + ), + DispatchError::BadOrigin + ); + + // Call with invalid location + assert_noop!( + XcmWeightTrader::resume_asset_support( + RuntimeOrigin::signed(ResumeAccount::get()), + Location::new(2, []), + ), + Error::::AssetNotFound + ); + + // Call with right origin and valid params + assert_ok!(XcmWeightTrader::resume_asset_support( + RuntimeOrigin::signed(ResumeAccount::get()), + Location::parent(), + )); + + // The asset should be supported again + assert_eq!( + XcmWeightTrader::get_asset_units_for_one_billion_native(&Location::parent()), + Some(1_000), + ); + + // Check storage + assert_eq!( + crate::pallet::SupportedAssets::::get(&Location::parent()), + Some((true, 1_000)) + ); + + // Should not be able to resume an asset already active + assert_noop!( + XcmWeightTrader::resume_asset_support( + RuntimeOrigin::signed(ResumeAccount::get()), + Location::parent(), + ), + Error::::AssetNotPaused + ); + }) +} + +#[test] +fn test_remove_asset_support() { + new_test_ext().execute_with(|| { + // Should not be able to remove an asset not added yet + assert_noop!( + XcmWeightTrader::remove_asset( + RuntimeOrigin::signed(RemoveAccount::get()), + Location::parent(), + ), + Error::::AssetNotFound + ); + + // Setup (add a supported asset) + assert_ok!(XcmWeightTrader::add_asset( + RuntimeOrigin::signed(AddAccount::get()), + Location::parent(), + 1_000, + )); + assert_eq!( + XcmWeightTrader::get_asset_units_for_one_billion_native(&Location::parent()), + Some(1_000), + ); + + // Call with bad origin + assert_noop!( + XcmWeightTrader::remove_asset( + RuntimeOrigin::signed(AddAccount::get()), + Location::parent(), + ), + DispatchError::BadOrigin + ); + + // Call with right origin and valid params + assert_ok!(XcmWeightTrader::remove_asset( + RuntimeOrigin::signed(RemoveAccount::get()), + Location::parent(), + )); + + // The account should be removed + assert_eq!( + XcmWeightTrader::get_asset_units_for_one_billion_native(&Location::parent()), + None, + ); + + // Check storage + assert_eq!( + crate::pallet::SupportedAssets::::get(&Location::parent()), + None + ); + + // Should not be able to pause an asset already removed + assert_noop!( + XcmWeightTrader::remove_asset( + RuntimeOrigin::signed(RemoveAccount::get()), + Location::parent(), + ), + Error::::AssetNotFound + ); + }) +} diff --git a/pallets/xcm-weight-trader/src/weights.rs b/pallets/xcm-weight-trader/src/weights.rs new file mode 100644 index 0000000000..972a946eba --- /dev/null +++ b/pallets/xcm-weight-trader/src/weights.rs @@ -0,0 +1,50 @@ +// Copyright 2024 Moonbeam foundation +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_xcm_weight_trader +pub trait WeightInfo { + fn add_asset() -> Weight; + fn edit_asset() -> Weight; + fn pause_asset_support() -> Weight; + fn resume_asset_support() -> Weight; + fn remove_asset() -> Weight; +} + +// For tests only +impl WeightInfo for () { + fn add_asset() -> Weight { + Weight::default() + } + fn edit_asset() -> Weight { + Weight::default() + } + fn pause_asset_support() -> Weight { + Weight::default() + } + fn resume_asset_support() -> Weight { + Weight::default() + } + fn remove_asset() -> Weight { + Weight::default() + } +} \ No newline at end of file diff --git a/primitives/xcm/src/fee_handlers.rs b/primitives/xcm/src/fee_handlers.rs index c496bc37c9..b052d95826 100644 --- a/primitives/xcm/src/fee_handlers.rs +++ b/primitives/xcm/src/fee_handlers.rs @@ -82,7 +82,7 @@ impl< // This involves the same db read per block, mitigating any attack based on // non-supported assets if !AssetIdInfoGetter::payment_is_supported(asset_type.clone()) { - return Err(XcmError::TooExpensive); + return Err(XcmError::AssetNotFound); } if let Some(units_per_second) = AssetIdInfoGetter::get_units_per_second(asset_type) { From 7c7212dded8b5ce2bb0d8235e43217b72b07ab61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Wed, 21 Aug 2024 16:38:56 +0200 Subject: [PATCH 02/27] add rust unit tests for trader fix trader impl --- pallets/xcm-weight-trader/src/benchmarking.rs | 4 +- pallets/xcm-weight-trader/src/lib.rs | 127 +++++----- pallets/xcm-weight-trader/src/mock.rs | 11 +- pallets/xcm-weight-trader/src/tests.rs | 223 +++++++++++++++++- 4 files changed, 296 insertions(+), 69 deletions(-) diff --git a/pallets/xcm-weight-trader/src/benchmarking.rs b/pallets/xcm-weight-trader/src/benchmarking.rs index 3f16c2d785..1d711289eb 100644 --- a/pallets/xcm-weight-trader/src/benchmarking.rs +++ b/pallets/xcm-weight-trader/src/benchmarking.rs @@ -58,7 +58,7 @@ mod benchmarks { assert_last_event::( Event::SupportedAssetAdded { location, - units_for_one_billion_native: 1_000, + relative_price: 1_000, } .into(), ); @@ -79,7 +79,7 @@ mod benchmarks { assert_last_event::( Event::SupportedAssetEdited { location, - units_for_one_billion_native: 2_000, + relative_price: 2_000, } .into(), ); diff --git a/pallets/xcm-weight-trader/src/lib.rs b/pallets/xcm-weight-trader/src/lib.rs index 913512407e..854bc5e5b3 100644 --- a/pallets/xcm-weight-trader/src/lib.rs +++ b/pallets/xcm-weight-trader/src/lib.rs @@ -42,6 +42,8 @@ use xcm::latest::{ }; use xcm_executor::traits::{TransactAsset, WeightTrader}; +const RELATIVE_PRICE_DECIMALS: u32 = 9; + #[pallet] pub mod pallet { use super::*; @@ -102,7 +104,7 @@ pub mod pallet { } /// Stores all supported assets per XCM Location. - /// The u128 is the number of units equal to one billion units of native currency. + /// The u128 is the asset price relative to native asset with 9 decimals /// The boolean specify if the support for this asset is active #[pallet::storage] #[pallet::getter(fn supported_assets)] @@ -130,12 +132,12 @@ pub mod pallet { /// New supported asset is registered SupportedAssetAdded { location: Location, - units_for_one_billion_native: u128, + relative_price: u128, }, /// Changed the amount of units we are charging per execution second for a given asset SupportedAssetEdited { location: Location, - units_for_one_billion_native: u128, + relative_price: u128, }, /// Pause support for a given asset PauseAssetSupport { location: Location }, @@ -152,14 +154,11 @@ pub mod pallet { pub fn add_asset( origin: OriginFor, location: Location, - units_for_one_billion_native: u128, + relative_price: u128, ) -> DispatchResult { T::AddSupportedAssetOrigin::ensure_origin(origin)?; - ensure!( - units_for_one_billion_native != 0, - Error::::UnitsCannotBeZero - ); + ensure!(relative_price != 0, Error::::UnitsCannotBeZero); ensure!( !SupportedAssets::::contains_key(&location), Error::::AssetAlreadyAdded @@ -169,11 +168,11 @@ pub mod pallet { Error::::XcmLocationFiltered ); - SupportedAssets::::insert(&location, (true, units_for_one_billion_native)); + SupportedAssets::::insert(&location, (true, relative_price)); Self::deposit_event(Event::SupportedAssetAdded { location, - units_for_one_billion_native, + relative_price, }); Ok(()) @@ -184,24 +183,21 @@ pub mod pallet { pub fn edit_asset( origin: OriginFor, location: Location, - units_for_one_billion_native: u128, + relative_price: u128, ) -> DispatchResult { T::EditSupportedAssetOrigin::ensure_origin(origin)?; - ensure!( - units_for_one_billion_native != 0, - Error::::UnitsCannotBeZero - ); + ensure!(relative_price != 0, Error::::UnitsCannotBeZero); ensure!( SupportedAssets::::contains_key(&location), Error::::AssetNotFound ); - SupportedAssets::::insert(&location, (true, units_for_one_billion_native)); + SupportedAssets::::insert(&location, (true, relative_price)); Self::deposit_event(Event::SupportedAssetEdited { location, - units_for_one_billion_native, + relative_price, }); Ok(()) @@ -213,8 +209,8 @@ pub mod pallet { T::PauseSupportedAssetOrigin::ensure_origin(origin)?; match SupportedAssets::::get(&location) { - Some((true, units_for_one_billion_native)) => { - SupportedAssets::::insert(&location, (false, units_for_one_billion_native)); + Some((true, relative_price)) => { + SupportedAssets::::insert(&location, (false, relative_price)); Self::deposit_event(Event::PauseAssetSupport { location }); Ok(()) } @@ -229,8 +225,8 @@ pub mod pallet { T::ResumeSupportedAssetOrigin::ensure_origin(origin)?; match SupportedAssets::::get(&location) { - Some((false, units_for_one_billion_native)) => { - SupportedAssets::::insert(&location, (true, units_for_one_billion_native)); + Some((false, relative_price)) => { + SupportedAssets::::insert(&location, (true, relative_price)); Self::deposit_event(Event::ResumeAssetSupport { location }); Ok(()) } @@ -258,7 +254,7 @@ pub mod pallet { } impl Pallet { - pub fn get_asset_units_for_one_billion_native(location: &Location) -> Option { + pub fn get_asset_relative_price(location: &Location) -> Option { if let Some((true, ratio)) = SupportedAssets::::get(location) { Some(ratio) } else { @@ -270,6 +266,30 @@ pub mod pallet { struct Trader(Weight, Option, core::marker::PhantomData); +impl Trader { + fn compute_amount_to_charge( + weight: &Weight, + asset_location: &Location, + ) -> Result { + if *asset_location == ::NativeLocation::get() { + ::WeightToFee::weight_to_fee(&weight) + .try_into() + .map_err(|_| XcmError::Overflow) + } else if let Some(relative_price) = Pallet::::get_asset_relative_price(asset_location) { + let native_amount: u128 = ::WeightToFee::weight_to_fee(&weight) + .try_into() + .map_err(|_| XcmError::Overflow)?; + Ok(native_amount + .checked_mul(10u128.pow(RELATIVE_PRICE_DECIMALS)) + .ok_or(XcmError::Overflow)? + .checked_div(relative_price) + .ok_or(XcmError::Overflow)?) + } else { + Err(XcmError::AssetNotFound) + } + } +} + impl WeightTrader for Trader { fn new() -> Self { Self(Weight::zero(), None, PhantomData) @@ -299,21 +319,7 @@ impl WeightTrader for Trader { match (first_asset.id, first_asset.fun) { (XcmAssetId(location), Fungibility::Fungible(_)) => { - let amount: u128 = if location == ::NativeLocation::get() { - ::WeightToFee::weight_to_fee(&weight) - .try_into() - .map_err(|_| XcmError::Overflow)? - } else if let Some(units_for_one_billion_native) = - Pallet::::get_asset_units_for_one_billion_native(&location) - { - let native_amount: u128 = - ::WeightToFee::weight_to_fee(&weight) - .try_into() - .map_err(|_| XcmError::Overflow)?; - units_for_one_billion_native * native_amount / 1_000_000_000u128 - } else { - return Err(XcmError::AssetNotFound); - }; + let amount: u128 = Self::compute_amount_to_charge(&weight, &location)?; // We dont need to proceed if the amount is 0 // For cases (specially tests) where the asset is very cheap with respect @@ -339,37 +345,46 @@ impl WeightTrader for Trader { } } - fn refund_weight(&mut self, weight: Weight, context: &XcmContext) -> Option { + fn refund_weight(&mut self, actual_weight: Weight, context: &XcmContext) -> Option { log::trace!( target: "xcm-weight-trader", "refund_weight weight: {:?}, context: {:?}, available weight: {:?}, asset: {:?}", - weight, + actual_weight, context, self.0, self.1 ); - let maybe_asset_to_refound = if let Some(Asset { + if let Some(Asset { fun: Fungibility::Fungible(initial_amount), id: XcmAssetId(location), - }) = &self.1 + }) = self.1.take() { - let weight = weight.min(self.0); - let amount: u128 = ::WeightToFee::weight_to_fee(&weight) - .try_into() - .unwrap_or(u128::MAX); - let final_amount = amount.min(*initial_amount); - let amount_to_refound = initial_amount.saturating_sub(final_amount); - self.0 -= weight; - log::trace!(target: "xcm-weight-trader", "refund_weight amount to refund: {:?}", amount_to_refound); - Some(Asset { - fun: Fungibility::Fungible(amount_to_refound), - id: XcmAssetId(location.clone()), - }) + if actual_weight == self.0 { + self.1 = Some(Asset { + fun: Fungibility::Fungible(initial_amount), + id: XcmAssetId(location), + }); + None + } else { + let weight = actual_weight.min(self.0); + let amount: u128 = + Self::compute_amount_to_charge(&weight, &location).unwrap_or(u128::MAX); + let final_amount = amount.min(initial_amount); + let amount_to_refound = initial_amount.saturating_sub(final_amount); + self.0 -= weight; + self.1 = Some(Asset { + fun: Fungibility::Fungible(final_amount), + id: XcmAssetId(location.clone()), + }); + log::trace!(target: "xcm-weight-trader", "refund_weight amount to refund: {:?}", amount_to_refound); + Some(Asset { + fun: Fungibility::Fungible(amount_to_refound), + id: XcmAssetId(location), + }) + } } else { None - }; - self.1 = maybe_asset_to_refound.clone(); - maybe_asset_to_refound + } } } diff --git a/pallets/xcm-weight-trader/src/mock.rs b/pallets/xcm-weight-trader/src/mock.rs index 6a9e749459..0345fd0fb8 100644 --- a/pallets/xcm-weight-trader/src/mock.rs +++ b/pallets/xcm-weight-trader/src/mock.rs @@ -120,6 +120,11 @@ impl Contains for AssetLocationFilter { } } +pub fn get_parent_asset_deposited() -> Option<(AccountId, Balance)> { + storage::unhashed::get_raw(b"____parent_asset_deposited") + .map(|output| Decode::decode(&mut output.as_slice()).expect("Decoding should work")) +} + pub struct MockAssetTransactor; impl TransactAsset for MockAssetTransactor { fn deposit_asset(asset: &Asset, who: &Location, _context: Option<&XcmContext>) -> XcmResult { @@ -133,7 +138,11 @@ impl TransactAsset for MockAssetTransactor { let _ = Balances::deposit_creating(who, amount); Ok(()) } else if location == Location::parent() { - todo!() + storage::unhashed::put_raw( + b"____parent_asset_deposited", + (who, amount).encode().as_slice(), + ); + Ok(()) } else { Err(XcmError::AssetNotFound) } diff --git a/pallets/xcm-weight-trader/src/tests.rs b/pallets/xcm-weight-trader/src/tests.rs index de867aad77..441ebaf3b9 100644 --- a/pallets/xcm-weight-trader/src/tests.rs +++ b/pallets/xcm-weight-trader/src/tests.rs @@ -17,12 +17,20 @@ //! Unit testing use { crate::mock::*, - crate::Error, + crate::{Error, Trader}, + frame_support::pallet_prelude::Weight, frame_support::{assert_noop, assert_ok}, sp_runtime::DispatchError, - xcm::latest::{Asset, Error as XcmError, Junction, Location, Result as XcmResult}, + xcm::latest::{ + Asset, AssetId as XcmAssetId, Error as XcmError, Fungibility, Location, XcmContext, XcmHash, + }, + xcm_executor::traits::WeightTrader, }; +fn xcm_fees_account() -> ::AccountId { + ::XcmFeesAccount::get() +} + #[test] fn test_add_supported_asset() { new_test_ext().execute_with(|| { @@ -65,7 +73,7 @@ fn test_add_supported_asset() { // The account should be supported assert_eq!( - XcmWeightTrader::get_asset_units_for_one_billion_native(&Location::parent()), + XcmWeightTrader::get_asset_relative_price(&Location::parent()), Some(1_000), ); @@ -107,7 +115,7 @@ fn test_edit_supported_asset() { 1_000, )); assert_eq!( - XcmWeightTrader::get_asset_units_for_one_billion_native(&Location::parent()), + XcmWeightTrader::get_asset_relative_price(&Location::parent()), Some(1_000), ); @@ -140,7 +148,7 @@ fn test_edit_supported_asset() { // The account should be supported assert_eq!( - XcmWeightTrader::get_asset_units_for_one_billion_native(&Location::parent()), + XcmWeightTrader::get_asset_relative_price(&Location::parent()), Some(2_000), ); @@ -171,7 +179,7 @@ fn test_pause_asset_support() { 1_000, )); assert_eq!( - XcmWeightTrader::get_asset_units_for_one_billion_native(&Location::parent()), + XcmWeightTrader::get_asset_relative_price(&Location::parent()), Some(1_000), ); @@ -192,7 +200,7 @@ fn test_pause_asset_support() { // The account should be paused assert_eq!( - XcmWeightTrader::get_asset_units_for_one_billion_native(&Location::parent()), + XcmWeightTrader::get_asset_relative_price(&Location::parent()), None, ); @@ -257,7 +265,7 @@ fn test_resume_asset_support() { // The asset should be supported again assert_eq!( - XcmWeightTrader::get_asset_units_for_one_billion_native(&Location::parent()), + XcmWeightTrader::get_asset_relative_price(&Location::parent()), Some(1_000), ); @@ -297,7 +305,7 @@ fn test_remove_asset_support() { 1_000, )); assert_eq!( - XcmWeightTrader::get_asset_units_for_one_billion_native(&Location::parent()), + XcmWeightTrader::get_asset_relative_price(&Location::parent()), Some(1_000), ); @@ -318,7 +326,7 @@ fn test_remove_asset_support() { // The account should be removed assert_eq!( - XcmWeightTrader::get_asset_units_for_one_billion_native(&Location::parent()), + XcmWeightTrader::get_asset_relative_price(&Location::parent()), None, ); @@ -338,3 +346,198 @@ fn test_remove_asset_support() { ); }) } + +#[test] +fn test_trader_native_asset() { + new_test_ext().execute_with(|| { + let weight_to_buy = Weight::from_parts(10_000, 0); + let dummy_xcm_context = XcmContext::with_message_id(XcmHash::default()); + + // Should not be able to buy weight with too low asset balance + assert_eq!( + Trader::::new().buy_weight( + weight_to_buy, + Asset { + fun: Fungibility::Fungible(9_999), + id: XcmAssetId(Location::here()), + } + .into(), + &dummy_xcm_context + ), + Err(XcmError::TooExpensive) + ); + + // Should not be able to buy weight with unsupported asset + assert_eq!( + Trader::::new().buy_weight( + weight_to_buy, + Asset { + fun: Fungibility::Fungible(10_000), + id: XcmAssetId(Location::parent()), + } + .into(), + &dummy_xcm_context + ), + Err(XcmError::AssetNotFound) + ); + + // Should not be able to buy weight without asset + assert_eq!( + Trader::::new().buy_weight(weight_to_buy, Default::default(), &dummy_xcm_context), + Err(XcmError::AssetNotFound) + ); + + // Should be able to buy weight with just enough native asset + let mut trader = Trader::::new(); + assert_eq!( + trader.buy_weight( + weight_to_buy, + Asset { + fun: Fungibility::Fungible(10_000), + id: XcmAssetId(Location::here()), + } + .into(), + &dummy_xcm_context + ), + Ok(Default::default()) + ); + + // Should not refund any funds + let actual_weight = weight_to_buy; + assert_eq!( + trader.refund_weight(actual_weight, &dummy_xcm_context), + None + ); + + // Should not be able to buy weight again with the same trader + assert_eq!( + trader.buy_weight( + weight_to_buy, + Asset { + fun: Fungibility::Fungible(10_000), + id: XcmAssetId(Location::here()), + } + .into(), + &dummy_xcm_context + ), + Err(XcmError::NotWithdrawable) + ); + + // Fees asset should be deposited into XcmFeesAccount + drop(trader); + assert_eq!(Balances::free_balance(&xcm_fees_account()), 10_000); + + // Should be able to buy weight with more native asset (and get back unused amount) + let mut trader = Trader::::new(); + assert_eq!( + trader.buy_weight( + weight_to_buy, + Asset { + fun: Fungibility::Fungible(11_000), + id: XcmAssetId(Location::here()), + } + .into(), + &dummy_xcm_context + ), + Ok(Asset { + fun: Fungibility::Fungible(1_000), + id: XcmAssetId(Location::here()), + } + .into()) + ); + + // Should be able to refund unused weights + let actual_weight = weight_to_buy.saturating_sub(Weight::from_parts(2_000, 0)); + assert_eq!( + trader.refund_weight(actual_weight, &dummy_xcm_context), + Some(Asset { + fun: Fungibility::Fungible(2_000), + id: XcmAssetId(Location::here()), + }) + ); + + // Fees asset should be deposited again into XcmFeesAccount (2 times cost minus one refund) + drop(trader); + assert_eq!( + Balances::free_balance(&xcm_fees_account()), + (2 * 10_000) - 2_000 + ); + }) +} + +#[test] +fn test_trader_parent_asset() { + new_test_ext().execute_with(|| { + let weight_to_buy = Weight::from_parts(10_000, 0); + let dummy_xcm_context = XcmContext::with_message_id(XcmHash::default()); + + // Setup (add a supported asset) + assert_ok!(XcmWeightTrader::add_asset( + RuntimeOrigin::signed(AddAccount::get()), + Location::parent(), + 500_000_000, + )); + assert_eq!( + XcmWeightTrader::get_asset_relative_price(&Location::parent()), + Some(500_000_000), + ); + + // Should be able to pay fees with registered asset + let mut trader = Trader::::new(); + assert_eq!( + trader.buy_weight( + weight_to_buy, + Asset { + fun: Fungibility::Fungible(22_000), + id: XcmAssetId(Location::parent()), + } + .into(), + &dummy_xcm_context + ), + Ok(Asset { + fun: Fungibility::Fungible(2_000), + id: XcmAssetId(Location::parent()), + } + .into()) + ); + + // Should be able to refund unused weights + let actual_weight = weight_to_buy.saturating_sub(Weight::from_parts(2_000, 0)); + assert_eq!( + trader.refund_weight(actual_weight, &dummy_xcm_context), + Some(Asset { + fun: Fungibility::Fungible(4_000), + id: XcmAssetId(Location::parent()), + }) + ); + + // Fees asset should be deposited into XcmFeesAccount + drop(trader); + assert_eq!( + get_parent_asset_deposited(), + Some((xcm_fees_account(), 20_000 - 4_000)) + ); + + // Should not be able to buy weight if the asset is not a first position + assert_eq!( + Trader::::new().buy_weight( + weight_to_buy, + vec![ + Asset { + fun: Fungibility::Fungible(10), + id: XcmAssetId(Location::here()), + }, + Asset { + fun: Fungibility::Fungible(30_000), + id: XcmAssetId(Location::parent()), + } + ] + .into(), + &dummy_xcm_context + ), + Err(XcmError::TooExpensive) + ); + + // TODO + }) +} From 27b51cf434fdedb7b49bec081520d2369cc60a69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Thu, 22 Aug 2024 13:02:20 +0200 Subject: [PATCH 03/27] add functions for runtime api xcm-fee-payment --- Cargo.lock | 1 + pallets/xcm-weight-trader/Cargo.toml | 4 +- pallets/xcm-weight-trader/src/lib.rs | 51 +++++++++- pallets/xcm-weight-trader/src/mock.rs | 2 +- pallets/xcm-weight-trader/src/tests.rs | 127 ++++++++++++++++++++++++- 5 files changed, 177 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fc2b325f36..96fe9a98fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10553,6 +10553,7 @@ dependencies = [ "sp-tracing", "staging-xcm", "staging-xcm-executor", + "xcm-fee-payment-runtime-api", ] [[package]] diff --git a/pallets/xcm-weight-trader/Cargo.toml b/pallets/xcm-weight-trader/Cargo.toml index c322f3b62a..680c3c234f 100644 --- a/pallets/xcm-weight-trader/Cargo.toml +++ b/pallets/xcm-weight-trader/Cargo.toml @@ -22,6 +22,7 @@ sp-std = {workspace = true} # Polkadot xcm = { workspace = true } xcm-executor = { workspace = true } +xcm-fee-payment-runtime-api = { workspace = true } # Benchmarks frame-benchmarking = {workspace = true, optional = true} @@ -47,6 +48,7 @@ std = [ "sp-runtime/std", "sp-std/std", "xcm/std", - "xcm-executor/std" + "xcm-executor/std", + "xcm-fee-payment-runtime-api/std", ] try-runtime = ["frame-support/try-runtime"] \ No newline at end of file diff --git a/pallets/xcm-weight-trader/src/lib.rs b/pallets/xcm-weight-trader/src/lib.rs index 854bc5e5b3..2485bac3b6 100644 --- a/pallets/xcm-weight-trader/src/lib.rs +++ b/pallets/xcm-weight-trader/src/lib.rs @@ -37,10 +37,10 @@ use frame_support::traits::Contains; use frame_support::weights::WeightToFee; use frame_system::pallet_prelude::*; use sp_runtime::traits::{Convert, Zero}; -use xcm::latest::{ - Asset, AssetId as XcmAssetId, Error as XcmError, Fungibility, Location, XcmContext, -}; +use xcm::v4::{Asset, AssetId as XcmAssetId, Error as XcmError, Fungibility, Location, XcmContext}; +use xcm::{IntoVersion, VersionedAssetId}; use xcm_executor::traits::{TransactAsset, WeightTrader}; +use xcm_fee_payment_runtime_api::Error as XcmPaymentApiError; const RELATIVE_PRICE_DECIMALS: u32 = 9; @@ -261,6 +261,51 @@ pub mod pallet { None } } + pub fn query_acceptable_payment_assets( + xcm_version: xcm::Version, + ) -> Result, XcmPaymentApiError> { + if !matches!(xcm_version, 3 | 4) { + return Err(XcmPaymentApiError::UnhandledXcmVersion); + } + + let v4_assets = [VersionedAssetId::V4(XcmAssetId::from( + T::NativeLocation::get(), + ))] + .into_iter() + .chain( + SupportedAssets::::iter().filter_map(|(asset_location, (enabled, _))| { + enabled.then(|| VersionedAssetId::V4(XcmAssetId(asset_location))) + }), + ) + .collect::>(); + + if xcm_version == 3 { + v4_assets + .into_iter() + .map(|v4_asset| v4_asset.into_version(3)) + .collect::>() + .map_err(|_| XcmPaymentApiError::VersionedConversionFailed) + } else { + Ok(v4_assets) + } + } + pub fn query_weight_to_asset_fee( + weight: Weight, + asset: VersionedAssetId, + ) -> Result { + if let VersionedAssetId::V4(XcmAssetId(asset_location)) = asset + .into_version(4) + .map_err(|_| XcmPaymentApiError::VersionedConversionFailed)? + { + Trader::::compute_amount_to_charge(&weight, &asset_location).map_err(|e| match e + { + XcmError::AssetNotFound => XcmPaymentApiError::AssetNotFound, + _ => XcmPaymentApiError::WeightNotComputable, + }) + } else { + Err(XcmPaymentApiError::UnhandledXcmVersion) + } + } } } diff --git a/pallets/xcm-weight-trader/src/mock.rs b/pallets/xcm-weight-trader/src/mock.rs index 0345fd0fb8..b1ce8166eb 100644 --- a/pallets/xcm-weight-trader/src/mock.rs +++ b/pallets/xcm-weight-trader/src/mock.rs @@ -29,7 +29,7 @@ use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, BuildStorage, }; -use xcm::latest::{Asset, Error as XcmError, Junction, Location, Result as XcmResult, XcmContext}; +use xcm::v4::{Asset, Error as XcmError, Junction, Location, Result as XcmResult, XcmContext}; type AccountId = u64; type Balance = u128; diff --git a/pallets/xcm-weight-trader/src/tests.rs b/pallets/xcm-weight-trader/src/tests.rs index 441ebaf3b9..382d15397c 100644 --- a/pallets/xcm-weight-trader/src/tests.rs +++ b/pallets/xcm-weight-trader/src/tests.rs @@ -17,13 +17,14 @@ //! Unit testing use { crate::mock::*, - crate::{Error, Trader}, + crate::{Error, Trader, XcmPaymentApiError}, frame_support::pallet_prelude::Weight, frame_support::{assert_noop, assert_ok}, sp_runtime::DispatchError, - xcm::latest::{ + xcm::v4::{ Asset, AssetId as XcmAssetId, Error as XcmError, Fungibility, Location, XcmContext, XcmHash, }, + xcm::{IntoVersion, VersionedAssetId}, xcm_executor::traits::WeightTrader, }; @@ -537,7 +538,127 @@ fn test_trader_parent_asset() { ), Err(XcmError::TooExpensive) ); + }) +} + +#[test] +fn test_query_acceptable_payment_assets() { + new_test_ext().execute_with(|| { + // By default, only native asset should be supported + assert_eq!( + XcmWeightTrader::query_acceptable_payment_assets(4), + Ok(vec![VersionedAssetId::V4(XcmAssetId( + ::NativeLocation::get() + ))]) + ); + + // We should support XCMv3 + assert_eq!( + XcmWeightTrader::query_acceptable_payment_assets(3), + Ok(vec![VersionedAssetId::V4(XcmAssetId( + ::NativeLocation::get() + )) + .into_version(3) + .expect("native location should be convertible to v3")]) + ); + + // We should not support XCMv2 + assert_eq!( + XcmWeightTrader::query_acceptable_payment_assets(2), + Err(XcmPaymentApiError::UnhandledXcmVersion) + ); + + // Setup (add a supported asset) + assert_ok!(XcmWeightTrader::add_asset( + RuntimeOrigin::signed(AddAccount::get()), + Location::parent(), + 500_000_000, + )); + assert_eq!( + XcmWeightTrader::get_asset_relative_price(&Location::parent()), + Some(500_000_000), + ); + + // We should support parent asset now + assert_eq!( + XcmWeightTrader::query_acceptable_payment_assets(4), + Ok(vec![ + VersionedAssetId::V4(XcmAssetId(::NativeLocation::get())), + VersionedAssetId::V4(XcmAssetId(Location::parent())) + ]) + ); + + // Setup: pause parent asset + assert_ok!(XcmWeightTrader::pause_asset_support( + RuntimeOrigin::signed(PauseAccount::get()), + Location::parent(), + )); + assert_eq!( + XcmWeightTrader::get_asset_relative_price(&Location::parent()), + None + ); + + // We should not support paused assets + assert_eq!( + XcmWeightTrader::query_acceptable_payment_assets(4), + Ok(vec![VersionedAssetId::V4(XcmAssetId( + ::NativeLocation::get() + )),]) + ); + }) +} + +#[test] +fn test_query_weight_to_asset_fee() { + new_test_ext().execute_with(|| { + let native_asset = + VersionedAssetId::V4(XcmAssetId(::NativeLocation::get())); + let parent_asset = VersionedAssetId::V4(XcmAssetId(Location::parent())); + let weight_to_buy = Weight::from_parts(10_000, 0); + + // Native asset price should be 1:1 + assert_eq!( + XcmWeightTrader::query_weight_to_asset_fee(weight_to_buy, native_asset.clone()), + Ok(10_000) + ); + + // Should not be able to query fees for an unsupported asset + assert_eq!( + XcmWeightTrader::query_weight_to_asset_fee(weight_to_buy, parent_asset.clone()), + Err(XcmPaymentApiError::AssetNotFound) + ); + + // Setup (add a supported asset) + assert_ok!(XcmWeightTrader::add_asset( + RuntimeOrigin::signed(AddAccount::get()), + Location::parent(), + 500_000_000, + )); + assert_eq!( + XcmWeightTrader::get_asset_relative_price(&Location::parent()), + Some(500_000_000), + ); - // TODO + // Parent asset price should be 0.5 + assert_eq!( + XcmWeightTrader::query_weight_to_asset_fee(weight_to_buy, parent_asset.clone()), + Ok(2 * 10_000) + ); + + // Setup: pause parent asset + assert_ok!(XcmWeightTrader::pause_asset_support( + RuntimeOrigin::signed(PauseAccount::get()), + Location::parent(), + )); + assert_eq!( + XcmWeightTrader::get_asset_relative_price(&Location::parent()), + None + ); + + // We should not support paused assets + assert_eq!( + XcmWeightTrader::query_weight_to_asset_fee(weight_to_buy, parent_asset), + Err(XcmPaymentApiError::AssetNotFound) + ); }) } From 3d9c721282bc5806ef6b6bb62c58df23147e1614 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Thu, 22 Aug 2024 14:15:54 +0200 Subject: [PATCH 04/27] add rust test scenario: unpause and edit asset price --- pallets/xcm-weight-trader/src/tests.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/pallets/xcm-weight-trader/src/tests.rs b/pallets/xcm-weight-trader/src/tests.rs index 382d15397c..5a32ea3730 100644 --- a/pallets/xcm-weight-trader/src/tests.rs +++ b/pallets/xcm-weight-trader/src/tests.rs @@ -657,8 +657,29 @@ fn test_query_weight_to_asset_fee() { // We should not support paused assets assert_eq!( - XcmWeightTrader::query_weight_to_asset_fee(weight_to_buy, parent_asset), + XcmWeightTrader::query_weight_to_asset_fee(weight_to_buy, parent_asset.clone()), Err(XcmPaymentApiError::AssetNotFound) ); + + // Setup: unpause parent asset and edit price + assert_ok!(XcmWeightTrader::resume_asset_support( + RuntimeOrigin::signed(ResumeAccount::get()), + Location::parent(), + )); + assert_ok!(XcmWeightTrader::edit_asset( + RuntimeOrigin::signed(EditAccount::get()), + Location::parent(), + 2_000_000_000, + )); + assert_eq!( + XcmWeightTrader::get_asset_relative_price(&Location::parent()), + Some(2_000_000_000), + ); + + // We should support unpaused asset with new price + assert_eq!( + XcmWeightTrader::query_weight_to_asset_fee(weight_to_buy, parent_asset), + Ok(10_000 / 2) + ); }) } From 83157cd0a784da729d155e94c910882b6434fa98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Thu, 22 Aug 2024 20:17:35 +0200 Subject: [PATCH 05/27] add pallet-xcm-weight-trader to all runtimes & migrate assets fees data --- Cargo.lock | 5 + pallets/asset-manager/src/benchmarks.rs | 79 +-- pallets/asset-manager/src/lib.rs | 187 +------ pallets/asset-manager/src/tests.rs | 144 +----- pallets/asset-manager/src/weights.rs | 102 +--- pallets/xcm-weight-trader/src/lib.rs | 3 +- primitives/xcm/src/fee_handlers.rs | 466 ------------------ primitives/xcm/src/lib.rs | 3 - runtime/common/Cargo.toml | 4 + runtime/common/src/apis.rs | 60 +-- runtime/common/src/migrations.rs | 101 +++- .../src/weights/pallet_asset_manager.rs | 48 +- runtime/moonbase/Cargo.toml | 2 + runtime/moonbase/src/lib.rs | 8 +- runtime/moonbase/src/xcm_config.rs | 70 +-- runtime/moonbase/tests/xcm_tests.rs | 7 +- runtime/moonbeam/Cargo.toml | 2 + runtime/moonbeam/src/lib.rs | 12 +- runtime/moonbeam/src/xcm_config.rs | 64 +-- runtime/moonriver/Cargo.toml | 2 + runtime/moonriver/src/lib.rs | 12 +- runtime/moonriver/src/xcm_config.rs | 64 +-- 22 files changed, 272 insertions(+), 1173 deletions(-) delete mode 100644 primitives/xcm/src/fee_handlers.rs diff --git a/Cargo.lock b/Cargo.lock index 96fe9a98fc..306b53ab8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6410,6 +6410,7 @@ dependencies = [ "pallet-xcm", "pallet-xcm-benchmarks", "pallet-xcm-transactor", + "pallet-xcm-weight-trader", "parachains-common", "parity-scale-codec", "polkadot-core-primitives", @@ -6904,6 +6905,7 @@ dependencies = [ "pallet-xcm", "pallet-xcm-benchmarks", "pallet-xcm-transactor", + "pallet-xcm-weight-trader", "parachains-common", "parity-scale-codec", "polkadot-core-primitives", @@ -6993,11 +6995,13 @@ dependencies = [ "pallet-scheduler", "pallet-sudo", "pallet-timestamp", + "pallet-transaction-payment", "pallet-treasury", "pallet-utility", "pallet-whitelist", "pallet-xcm", "pallet-xcm-transactor", + "pallet-xcm-weight-trader", "parity-scale-codec", "precompile-utils", "sp-api", @@ -7312,6 +7316,7 @@ dependencies = [ "pallet-xcm", "pallet-xcm-benchmarks", "pallet-xcm-transactor", + "pallet-xcm-weight-trader", "parachains-common", "parity-scale-codec", "polkadot-core-primitives", diff --git a/pallets/asset-manager/src/benchmarks.rs b/pallets/asset-manager/src/benchmarks.rs index a444a0ae1b..fafb37e9bf 100644 --- a/pallets/asset-manager/src/benchmarks.rs +++ b/pallets/asset-manager/src/benchmarks.rs @@ -36,49 +36,8 @@ benchmarks! { assert_eq!(Pallet::::asset_id_type(asset_id), Some(asset_type)); } - set_asset_units_per_second { - // We make it dependent on the number of existing assets already - let x in 5..100; - for i in 0..x { - let asset_type: T::ForeignAssetType = Location::new( - 0, - X1(GeneralIndex(i as u128)) - ).into(); - let metadata = T::AssetRegistrarMetadata::default(); - let amount = 1u32.into(); - Pallet::::register_foreign_asset( - RawOrigin::Root.into(), - asset_type.clone(), - metadata, - amount, - true - )?; - Pallet::::set_asset_units_per_second(RawOrigin::Root.into(), asset_type.clone(), 1, i)?; - } - - // does not really matter what we register, as long as it is different than the previous - let asset_type = T::ForeignAssetType::default(); - let metadata = T::AssetRegistrarMetadata::default(); - let amount = 1u32.into(); - let asset_id: T::AssetId = asset_type.clone().into(); - Pallet::::register_foreign_asset( - RawOrigin::Root.into(), - asset_type.clone(), - metadata, - amount, - true - )?; - - }: _(RawOrigin::Root, asset_type.clone(), 1, x) - verify { - assert!(Pallet::::supported_fee_payment_assets().contains(&asset_type)); - assert_eq!(Pallet::::asset_type_units_per_second(asset_type), Some(1)); - } - change_existing_asset_type { - // We make it dependent on the number of existing assets already - let x in 5..100; - for i in 0..x { + for i in 0..1 { let asset_type: T::ForeignAssetType = Location::new(0, X1(GeneralIndex(i as u128))).into(); let metadata = T::AssetRegistrarMetadata::default(); let amount = 1u32.into(); @@ -89,7 +48,6 @@ benchmarks! { amount, true )?; - Pallet::::set_asset_units_per_second(RawOrigin::Root.into(), asset_type.clone(), 1, i)?; } let new_asset_type = T::ForeignAssetType::default(); @@ -101,42 +59,10 @@ benchmarks! { }: _(RawOrigin::Root, asset_id_to_be_changed, new_asset_type.clone(), x) verify { assert_eq!(Pallet::::asset_id_type(asset_id_to_be_changed), Some(new_asset_type.clone())); - assert_eq!(Pallet::::asset_type_units_per_second(&new_asset_type), Some(1)); - assert!(Pallet::::supported_fee_payment_assets().contains(&new_asset_type)); - } - - remove_supported_asset { - // We make it dependent on the number of existing assets already - let x in 5..100; - for i in 0..x { - let asset_type: T::ForeignAssetType = Location::new(0, X1(GeneralIndex(i as u128))).into(); - let metadata = T::AssetRegistrarMetadata::default(); - let amount = 1u32.into(); - Pallet::::register_foreign_asset( - RawOrigin::Root.into(), - asset_type.clone(), - metadata, - amount, - true - )?; - Pallet::::set_asset_units_per_second(RawOrigin::Root.into(), asset_type.clone(), 1, i)?; - } - let asset_type_to_be_removed: T::ForeignAssetType = Location::new( - 0, - X1(GeneralIndex((x-1) as u128)) - ).into(); - // We try to remove the last asset type - }: _(RawOrigin::Root, asset_type_to_be_removed.clone(), x) - verify { - assert!(!Pallet::::supported_fee_payment_assets().contains(&asset_type_to_be_removed)); - assert_eq!(Pallet::::asset_type_units_per_second(asset_type_to_be_removed), None); } remove_existing_asset_type { - // We make it dependent on the number of existing assets already - // Worst case is we need to remove it from SupportedAAssetsFeePayment too - let x in 5..100; - for i in 0..x { + for i in 0..1 { let asset_type: T::ForeignAssetType = Location::new(0, X1(GeneralIndex(i as u128))).into(); let metadata = T::AssetRegistrarMetadata::default(); let amount = 1u32.into(); @@ -147,7 +73,6 @@ benchmarks! { amount, true )?; - Pallet::::set_asset_units_per_second(RawOrigin::Root.into(), asset_type.clone(), 1, i)?; } let asset_type_to_be_removed: T::ForeignAssetType = Location::new( diff --git a/pallets/asset-manager/src/lib.rs b/pallets/asset-manager/src/lib.rs index e7ee00c3e9..d825d5b3e2 100644 --- a/pallets/asset-manager/src/lib.rs +++ b/pallets/asset-manager/src/lib.rs @@ -27,8 +27,6 @@ //! //! This pallet has eight extrinsics: register_foreign_asset, which registers a foreign //! asset in this pallet and creates the asset as dictated by the AssetRegistrar trait. -//! set_asset_units_per_second: which sets the unit per second that should be charged for -//! a particular asset. //! change_existing_asset_type: which allows to update the correspondence between AssetId and //! AssetType //! remove_supported_asset: which removes an asset from the supported assets for fee payment @@ -57,7 +55,6 @@ pub mod pallet { use frame_system::pallet_prelude::*; use parity_scale_codec::HasCompact; use sp_runtime::traits::{AccountIdConversion, AtLeast32BitUnsigned}; - use sp_std::vec::Vec; #[pallet::pallet] #[pallet::without_storage_info] @@ -105,28 +102,6 @@ pub mod pallet { } } - impl xcm_primitives::UnitsToWeightRatio for Pallet { - fn payment_is_supported(asset_type: T::ForeignAssetType) -> bool { - SupportedFeePaymentAssets::::get() - .binary_search(&asset_type) - .is_ok() - } - fn get_units_per_second(asset_type: T::ForeignAssetType) -> Option { - AssetTypeUnitsPerSecond::::get(asset_type) - } - #[cfg(feature = "runtime-benchmarks")] - fn set_units_per_second(asset_type: T::ForeignAssetType, fee_per_second: u128) { - // Grab supported assets - let mut supported_assets = SupportedFeePaymentAssets::::get(); - // Only if the asset is not supported we need to push it - if let Err(index) = supported_assets.binary_search(&asset_type) { - supported_assets.insert(index, asset_type.clone()); - SupportedFeePaymentAssets::::put(supported_assets); - } - AssetTypeUnitsPerSecond::::insert(&asset_type, &fee_per_second); - } - } - #[pallet::config] pub trait Config: frame_system::Config { type RuntimeEvent: From> + IsType<::RuntimeEvent>; @@ -218,21 +193,6 @@ pub mod pallet { pub type AssetTypeId = StorageMap<_, Blake2_128Concat, T::ForeignAssetType, T::AssetId>; - /// Stores the units per second for local execution for a AssetType. - /// This is used to know how to charge for XCM execution in a particular - /// asset - /// Not all assets might contain units per second, hence the different storage - #[pallet::storage] - #[pallet::getter(fn asset_type_units_per_second)] - pub type AssetTypeUnitsPerSecond = - StorageMap<_, Blake2_128Concat, T::ForeignAssetType, u128>; - - // Supported fee asset payments - #[pallet::storage] - #[pallet::getter(fn supported_fee_payment_assets)] - pub type SupportedFeePaymentAssets = - StorageValue<_, Vec, ValueQuery>; - #[pallet::call] impl Pallet { /// Register new asset with the asset manager @@ -275,68 +235,19 @@ pub mod pallet { Ok(()) } - /// Change the amount of units we are charging per execution second - /// for a given ForeignAssetType - #[pallet::call_index(1)] - #[pallet::weight(T::WeightInfo::set_asset_units_per_second(*num_assets_weight_hint))] - pub fn set_asset_units_per_second( - origin: OriginFor, - asset_type: T::ForeignAssetType, - units_per_second: u128, - num_assets_weight_hint: u32, - ) -> DispatchResult { - T::ForeignAssetModifierOrigin::ensure_origin(origin)?; - - // Ensure such an assetId does not exist - ensure!( - AssetTypeId::::get(&asset_type).is_some(), - Error::::AssetDoesNotExist - ); - - // Grab supported assets - let mut supported_assets = SupportedFeePaymentAssets::::get(); - - ensure!( - num_assets_weight_hint >= (supported_assets.len() as u32), - Error::::TooLowNumAssetsWeightHint - ); - - // Only if the asset is not supported we need to push it - if let Err(index) = supported_assets.binary_search(&asset_type) { - supported_assets.insert(index, asset_type.clone()); - SupportedFeePaymentAssets::::put(supported_assets); - } - - AssetTypeUnitsPerSecond::::insert(&asset_type, &units_per_second); - - Self::deposit_event(Event::UnitsPerSecondChanged { - asset_type, - units_per_second, - }); - Ok(()) - } - /// Change the xcm type mapping for a given assetId /// We also change this if the previous units per second where pointing at the old /// assetType #[pallet::call_index(2)] - #[pallet::weight(T::WeightInfo::change_existing_asset_type(*num_assets_weight_hint))] + #[pallet::weight(T::WeightInfo::change_existing_asset_type())] pub fn change_existing_asset_type( origin: OriginFor, asset_id: T::AssetId, new_asset_type: T::ForeignAssetType, - num_assets_weight_hint: u32, + _num_assets_weight_hint: u32, ) -> DispatchResult { T::ForeignAssetModifierOrigin::ensure_origin(origin)?; - // Grab supported assets - let mut supported_assets = SupportedFeePaymentAssets::::get(); - - ensure!( - num_assets_weight_hint >= (supported_assets.len() as u32), - Error::::TooLowNumAssetsWeightHint - ); - let previous_asset_type = AssetIdType::::get(&asset_id).ok_or(Error::::AssetDoesNotExist)?; @@ -347,26 +258,6 @@ pub mod pallet { // Remove previous asset type info AssetTypeId::::remove(&previous_asset_type); - // Change AssetTypeUnitsPerSecond - if let Some(units) = AssetTypeUnitsPerSecond::::get(&previous_asset_type) { - // Only if the old asset is supported we need to remove it - if let Ok(index) = supported_assets.binary_search(&previous_asset_type) { - supported_assets.remove(index); - } - - // Only if the new asset is not supported we need to push it - if let Err(index) = supported_assets.binary_search(&new_asset_type) { - supported_assets.insert(index, new_asset_type.clone()); - } - - // Insert supported fee payment assets - SupportedFeePaymentAssets::::put(supported_assets); - - // Remove previous asset type info - AssetTypeUnitsPerSecond::::remove(&previous_asset_type); - AssetTypeUnitsPerSecond::::insert(&new_asset_type, units); - } - Self::deposit_event(Event::ForeignAssetXcmLocationChanged { asset_id, new_asset_type, @@ -374,56 +265,16 @@ pub mod pallet { Ok(()) } - #[pallet::call_index(3)] - #[pallet::weight(T::WeightInfo::remove_supported_asset(*num_assets_weight_hint))] - pub fn remove_supported_asset( - origin: OriginFor, - asset_type: T::ForeignAssetType, - num_assets_weight_hint: u32, - ) -> DispatchResult { - T::ForeignAssetModifierOrigin::ensure_origin(origin)?; - - // Grab supported assets - let mut supported_assets = SupportedFeePaymentAssets::::get(); - - ensure!( - num_assets_weight_hint >= (supported_assets.len() as u32), - Error::::TooLowNumAssetsWeightHint - ); - - // Only if the old asset is supported we need to remove it - if let Ok(index) = supported_assets.binary_search(&asset_type) { - supported_assets.remove(index); - } - - // Insert - SupportedFeePaymentAssets::::put(supported_assets); - - // Remove - AssetTypeUnitsPerSecond::::remove(&asset_type); - - Self::deposit_event(Event::SupportedAssetRemoved { asset_type }); - Ok(()) - } - /// Remove a given assetId -> assetType association #[pallet::call_index(4)] - #[pallet::weight(T::WeightInfo::remove_existing_asset_type(*num_assets_weight_hint))] + #[pallet::weight(T::WeightInfo::remove_existing_asset_type())] pub fn remove_existing_asset_type( origin: OriginFor, asset_id: T::AssetId, - num_assets_weight_hint: u32, + _num_assets_weight_hint: u32, ) -> DispatchResult { T::ForeignAssetModifierOrigin::ensure_origin(origin)?; - // Grab supported assets - let mut supported_assets = SupportedFeePaymentAssets::::get(); - - ensure!( - num_assets_weight_hint >= (supported_assets.len() as u32), - Error::::TooLowNumAssetsWeightHint - ); - let asset_type = AssetIdType::::get(&asset_id).ok_or(Error::::AssetDoesNotExist)?; @@ -431,15 +282,6 @@ pub mod pallet { AssetIdType::::remove(&asset_id); // Remove from AssetTypeId AssetTypeId::::remove(&asset_type); - // Remove previous asset type units per second - AssetTypeUnitsPerSecond::::remove(&asset_type); - - // Only if the old asset is supported we need to remove it - if let Ok(index) = supported_assets.binary_search(&asset_type) { - supported_assets.remove(index); - // Insert - SupportedFeePaymentAssets::::put(supported_assets); - } Self::deposit_event(Event::ForeignAssetRemoved { asset_id, @@ -457,27 +299,19 @@ pub mod pallet { let dispatch_info_weight = T::AssetRegistrar::destroy_asset_dispatch_info_weight( *asset_id ); - T::WeightInfo::remove_existing_asset_type(*num_assets_weight_hint) + T::WeightInfo::remove_existing_asset_type() .saturating_add(dispatch_info_weight) })] pub fn destroy_foreign_asset( origin: OriginFor, asset_id: T::AssetId, - num_assets_weight_hint: u32, + _num_assets_weight_hint: u32, ) -> DispatchResult { T::ForeignAssetModifierOrigin::ensure_origin(origin)?; T::AssetRegistrar::destroy_foreign_asset(asset_id) .map_err(|_| Error::::ErrorDestroyingAsset)?; - // Grab supported assets - let mut supported_assets = SupportedFeePaymentAssets::::get(); - - ensure!( - num_assets_weight_hint >= (supported_assets.len() as u32), - Error::::TooLowNumAssetsWeightHint - ); - let asset_type = AssetIdType::::get(&asset_id).ok_or(Error::::AssetDoesNotExist)?; @@ -485,15 +319,6 @@ pub mod pallet { AssetIdType::::remove(&asset_id); // Remove from AssetTypeId AssetTypeId::::remove(&asset_type); - // Remove previous asset type units per second - AssetTypeUnitsPerSecond::::remove(&asset_type); - - // Only if the old asset is supported we need to remove it - if let Ok(index) = supported_assets.binary_search(&asset_type) { - supported_assets.remove(index); - // Insert - SupportedFeePaymentAssets::::put(supported_assets); - } Self::deposit_event(Event::ForeignAssetDestroyed { asset_id, diff --git a/pallets/asset-manager/src/tests.rs b/pallets/asset-manager/src/tests.rs index dee27f5229..e25a66bda9 100644 --- a/pallets/asset-manager/src/tests.rs +++ b/pallets/asset-manager/src/tests.rs @@ -75,44 +75,6 @@ fn test_asset_exists_error() { }); } -#[test] -fn test_root_can_change_units_per_second() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(AssetManager::register_foreign_asset( - RuntimeOrigin::root(), - MockAssetType::MockAsset(1), - 0u32.into(), - 1u32.into(), - true - )); - - assert_ok!(AssetManager::set_asset_units_per_second( - RuntimeOrigin::root(), - MockAssetType::MockAsset(1), - 200u128.into(), - 0 - )); - - assert_eq!( - AssetManager::asset_type_units_per_second(MockAssetType::MockAsset(1)).unwrap(), - 200 - ); - assert!(AssetManager::supported_fee_payment_assets().contains(&MockAssetType::MockAsset(1))); - - expect_events(vec![ - crate::Event::ForeignAssetRegistered { - asset_id: 1, - asset: MockAssetType::MockAsset(1), - metadata: 0, - }, - crate::Event::UnitsPerSecondChanged { - asset_type: MockAssetType::MockAsset(1), - units_per_second: 200, - }, - ]) - }); -} - #[test] fn test_regular_user_cannot_call_extrinsics() { ExtBuilder::default().build().execute_with(|| { @@ -127,16 +89,6 @@ fn test_regular_user_cannot_call_extrinsics() { sp_runtime::DispatchError::BadOrigin ); - assert_noop!( - AssetManager::set_asset_units_per_second( - RuntimeOrigin::signed(1), - MockAssetType::MockAsset(1), - 200u128.into(), - 0 - ), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( AssetManager::change_existing_asset_type( RuntimeOrigin::signed(1), @@ -160,13 +112,6 @@ fn test_root_can_change_asset_id_type() { true )); - assert_ok!(AssetManager::set_asset_units_per_second( - RuntimeOrigin::root(), - MockAssetType::MockAsset(1), - 200u128.into(), - 0 - )); - assert_ok!(AssetManager::change_existing_asset_type( RuntimeOrigin::root(), 1, @@ -225,47 +170,23 @@ fn test_change_units_per_second_after_setting_it_once() { true, )); - assert_ok!(AssetManager::set_asset_units_per_second( - RuntimeOrigin::root(), - MockAssetType::MockAsset(1), - 200u128.into(), - 0 - )); - assert_eq!( AssetManager::asset_type_units_per_second(MockAssetType::MockAsset(1)).unwrap(), 200 ); assert!(AssetManager::supported_fee_payment_assets().contains(&MockAssetType::MockAsset(1))); - assert_ok!(AssetManager::set_asset_units_per_second( - RuntimeOrigin::root(), - MockAssetType::MockAsset(1), - 100u128.into(), - 1 - )); - assert_eq!( AssetManager::asset_type_units_per_second(MockAssetType::MockAsset(1)).unwrap(), 100 ); assert!(AssetManager::supported_fee_payment_assets().contains(&MockAssetType::MockAsset(1))); - expect_events(vec![ - crate::Event::ForeignAssetRegistered { - asset_id: 1, - asset: MockAssetType::MockAsset(1), - metadata: 0, - }, - crate::Event::UnitsPerSecondChanged { - asset_type: MockAssetType::MockAsset(1), - units_per_second: 200, - }, - crate::Event::UnitsPerSecondChanged { - asset_type: MockAssetType::MockAsset(1), - units_per_second: 100, - }, - ]); + expect_events(vec![crate::Event::ForeignAssetRegistered { + asset_id: 1, + asset: MockAssetType::MockAsset(1), + metadata: 0, + }]); }); } @@ -280,43 +201,21 @@ fn test_root_can_change_units_per_second_and_then_remove() { true, )); - assert_ok!(AssetManager::set_asset_units_per_second( - RuntimeOrigin::root(), - MockAssetType::MockAsset(1), - 200u128.into(), - 0 - )); - assert_eq!( AssetManager::asset_type_units_per_second(MockAssetType::MockAsset(1)).unwrap(), 200 ); assert!(AssetManager::supported_fee_payment_assets().contains(&MockAssetType::MockAsset(1))); - assert_ok!(AssetManager::remove_supported_asset( - RuntimeOrigin::root(), - MockAssetType::MockAsset(1), - 1, - )); - assert!( !AssetManager::supported_fee_payment_assets().contains(&MockAssetType::MockAsset(1)) ); - expect_events(vec![ - crate::Event::ForeignAssetRegistered { - asset_id: 1, - asset: MockAssetType::MockAsset(1), - metadata: 0, - }, - crate::Event::UnitsPerSecondChanged { - asset_type: MockAssetType::MockAsset(1), - units_per_second: 200, - }, - crate::Event::SupportedAssetRemoved { - asset_type: MockAssetType::MockAsset(1), - }, - ]); + expect_events(vec![crate::Event::ForeignAssetRegistered { + asset_id: 1, + asset: MockAssetType::MockAsset(1), + metadata: 0, + }]); }); } @@ -331,13 +230,6 @@ fn test_weight_hint_error() { true, )); - assert_ok!(AssetManager::set_asset_units_per_second( - RuntimeOrigin::root(), - MockAssetType::MockAsset(1), - 200u128.into(), - 0 - )); - assert_noop!( AssetManager::remove_supported_asset( RuntimeOrigin::root(), @@ -352,15 +244,6 @@ fn test_weight_hint_error() { #[test] fn test_asset_id_non_existent_error() { ExtBuilder::default().build().execute_with(|| { - assert_noop!( - AssetManager::set_asset_units_per_second( - RuntimeOrigin::root(), - MockAssetType::MockAsset(1), - 200u128.into(), - 0 - ), - Error::::AssetDoesNotExist - ); assert_noop!( AssetManager::change_existing_asset_type( RuntimeOrigin::root(), @@ -384,13 +267,6 @@ fn test_root_can_remove_asset_association() { true )); - assert_ok!(AssetManager::set_asset_units_per_second( - RuntimeOrigin::root(), - MockAssetType::MockAsset(1), - 200u128.into(), - 0 - )); - assert_ok!(AssetManager::remove_existing_asset_type( RuntimeOrigin::root(), 1, diff --git a/pallets/asset-manager/src/weights.rs b/pallets/asset-manager/src/weights.rs index 6d4fb9e6f8..5bab822ae8 100644 --- a/pallets/asset-manager/src/weights.rs +++ b/pallets/asset-manager/src/weights.rs @@ -53,10 +53,8 @@ use sp_std::marker::PhantomData; /// Weight functions needed for pallet_asset_manager. pub trait WeightInfo { fn register_foreign_asset() -> Weight; - fn set_asset_units_per_second(x: u32, ) -> Weight; - fn change_existing_asset_type(x: u32, ) -> Weight; - fn remove_supported_asset(x: u32, ) -> Weight; - fn remove_existing_asset_type(x: u32, ) -> Weight; + fn change_existing_asset_type() -> Weight; + fn remove_existing_asset_type() -> Weight; } /// Weights for pallet_asset_manager using the Substrate node and recommended hardware. @@ -79,25 +77,6 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: AssetManager AssetTypeId (r:1 w:0) - /// Proof Skipped: AssetManager AssetTypeId (max_values: None, max_size: None, mode: Measured) - /// Storage: AssetManager SupportedFeePaymentAssets (r:1 w:1) - /// Proof Skipped: AssetManager SupportedFeePaymentAssets (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AssetManager AssetTypeUnitsPerSecond (r:0 w:1) - /// Proof Skipped: AssetManager AssetTypeUnitsPerSecond (max_values: None, max_size: None, mode: Measured) - /// The range of component `x` is `[5, 100]`. - fn set_asset_units_per_second(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `611 + x * (9 ±0)` - // Estimated: `6555 + x * (30 ±0)` - // Minimum execution time: 30_927_000 picoseconds. - Weight::from_parts(30_990_835, 6555) - // Standard Error: 2_254 - .saturating_add(Weight::from_parts(494_375, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - .saturating_add(Weight::from_parts(0, 30).saturating_mul(x.into())) - } /// Storage: AssetManager SupportedFeePaymentAssets (r:1 w:1) /// Proof Skipped: AssetManager SupportedFeePaymentAssets (max_values: Some(1), max_size: None, mode: Measured) /// Storage: AssetManager AssetIdType (r:1 w:1) @@ -107,34 +86,17 @@ impl WeightInfo for SubstrateWeight { /// Storage: AssetManager AssetTypeId (r:0 w:2) /// Proof Skipped: AssetManager AssetTypeId (max_values: None, max_size: None, mode: Measured) /// The range of component `x` is `[5, 100]`. - fn change_existing_asset_type(x: u32, ) -> Weight { + fn change_existing_asset_type() -> Weight { // Proof Size summary in bytes: // Measured: `926 + x * (13 ±0)` // Estimated: `11791 + x * (60 ±0)` // Minimum execution time: 42_959_000 picoseconds. Weight::from_parts(43_255_055, 11791) // Standard Error: 3_394 - .saturating_add(Weight::from_parts(543_897, 0).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(543_897, 0)) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) - .saturating_add(Weight::from_parts(0, 60).saturating_mul(x.into())) - } - /// Storage: AssetManager SupportedFeePaymentAssets (r:1 w:1) - /// Proof Skipped: AssetManager SupportedFeePaymentAssets (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AssetManager AssetTypeUnitsPerSecond (r:0 w:1) - /// Proof Skipped: AssetManager AssetTypeUnitsPerSecond (max_values: None, max_size: None, mode: Measured) - /// The range of component `x` is `[5, 100]`. - fn remove_supported_asset(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `196 + x * (5 ±0)` - // Estimated: `1871 + x * (10 ±0)` - // Minimum execution time: 25_453_000 picoseconds. - Weight::from_parts(24_977_319, 1871) - // Standard Error: 2_109 - .saturating_add(Weight::from_parts(407_717, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - .saturating_add(Weight::from_parts(0, 10).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 60)) } /// Storage: AssetManager SupportedFeePaymentAssets (r:1 w:1) /// Proof Skipped: AssetManager SupportedFeePaymentAssets (max_values: Some(1), max_size: None, mode: Measured) @@ -145,17 +107,17 @@ impl WeightInfo for SubstrateWeight { /// Storage: AssetManager AssetTypeId (r:0 w:1) /// Proof Skipped: AssetManager AssetTypeId (max_values: None, max_size: None, mode: Measured) /// The range of component `x` is `[5, 100]`. - fn remove_existing_asset_type(x: u32, ) -> Weight { + fn remove_existing_asset_type() -> Weight { // Proof Size summary in bytes: // Measured: `482 + x * (10 ±0)` // Estimated: `6910 + x * (40 ±0)` // Minimum execution time: 32_960_000 picoseconds. Weight::from_parts(33_257_599, 6910) // Standard Error: 2_430 - .saturating_add(Weight::from_parts(421_651, 0).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(421_651, 0)) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) - .saturating_add(Weight::from_parts(0, 40).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 40)) } } @@ -178,25 +140,6 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: AssetManager AssetTypeId (r:1 w:0) - /// Proof Skipped: AssetManager AssetTypeId (max_values: None, max_size: None, mode: Measured) - /// Storage: AssetManager SupportedFeePaymentAssets (r:1 w:1) - /// Proof Skipped: AssetManager SupportedFeePaymentAssets (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AssetManager AssetTypeUnitsPerSecond (r:0 w:1) - /// Proof Skipped: AssetManager AssetTypeUnitsPerSecond (max_values: None, max_size: None, mode: Measured) - /// The range of component `x` is `[5, 100]`. - fn set_asset_units_per_second(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `611 + x * (9 ±0)` - // Estimated: `6555 + x * (30 ±0)` - // Minimum execution time: 30_927_000 picoseconds. - Weight::from_parts(30_990_835, 6555) - // Standard Error: 2_254 - .saturating_add(Weight::from_parts(494_375, 0).saturating_mul(x.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - .saturating_add(Weight::from_parts(0, 30).saturating_mul(x.into())) - } /// Storage: AssetManager SupportedFeePaymentAssets (r:1 w:1) /// Proof Skipped: AssetManager SupportedFeePaymentAssets (max_values: Some(1), max_size: None, mode: Measured) /// Storage: AssetManager AssetIdType (r:1 w:1) @@ -206,34 +149,17 @@ impl WeightInfo for () { /// Storage: AssetManager AssetTypeId (r:0 w:2) /// Proof Skipped: AssetManager AssetTypeId (max_values: None, max_size: None, mode: Measured) /// The range of component `x` is `[5, 100]`. - fn change_existing_asset_type(x: u32, ) -> Weight { + fn change_existing_asset_type() -> Weight { // Proof Size summary in bytes: // Measured: `926 + x * (13 ±0)` // Estimated: `11791 + x * (60 ±0)` // Minimum execution time: 42_959_000 picoseconds. Weight::from_parts(43_255_055, 11791) // Standard Error: 3_394 - .saturating_add(Weight::from_parts(543_897, 0).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(543_897, 0)) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) - .saturating_add(Weight::from_parts(0, 60).saturating_mul(x.into())) - } - /// Storage: AssetManager SupportedFeePaymentAssets (r:1 w:1) - /// Proof Skipped: AssetManager SupportedFeePaymentAssets (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AssetManager AssetTypeUnitsPerSecond (r:0 w:1) - /// Proof Skipped: AssetManager AssetTypeUnitsPerSecond (max_values: None, max_size: None, mode: Measured) - /// The range of component `x` is `[5, 100]`. - fn remove_supported_asset(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `196 + x * (5 ±0)` - // Estimated: `1871 + x * (10 ±0)` - // Minimum execution time: 25_453_000 picoseconds. - Weight::from_parts(24_977_319, 1871) - // Standard Error: 2_109 - .saturating_add(Weight::from_parts(407_717, 0).saturating_mul(x.into())) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - .saturating_add(Weight::from_parts(0, 10).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 60)) } /// Storage: AssetManager SupportedFeePaymentAssets (r:1 w:1) /// Proof Skipped: AssetManager SupportedFeePaymentAssets (max_values: Some(1), max_size: None, mode: Measured) @@ -244,16 +170,16 @@ impl WeightInfo for () { /// Storage: AssetManager AssetTypeId (r:0 w:1) /// Proof Skipped: AssetManager AssetTypeId (max_values: None, max_size: None, mode: Measured) /// The range of component `x` is `[5, 100]`. - fn remove_existing_asset_type(x: u32, ) -> Weight { + fn remove_existing_asset_type() -> Weight { // Proof Size summary in bytes: // Measured: `482 + x * (10 ±0)` // Estimated: `6910 + x * (40 ±0)` // Minimum execution time: 32_960_000 picoseconds. Weight::from_parts(33_257_599, 6910) // Standard Error: 2_430 - .saturating_add(Weight::from_parts(421_651, 0).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(421_651, 0)) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) - .saturating_add(Weight::from_parts(0, 40).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 40)) } } \ No newline at end of file diff --git a/pallets/xcm-weight-trader/src/lib.rs b/pallets/xcm-weight-trader/src/lib.rs index 2485bac3b6..17b5504786 100644 --- a/pallets/xcm-weight-trader/src/lib.rs +++ b/pallets/xcm-weight-trader/src/lib.rs @@ -37,6 +37,7 @@ use frame_support::traits::Contains; use frame_support::weights::WeightToFee; use frame_system::pallet_prelude::*; use sp_runtime::traits::{Convert, Zero}; +use sp_std::vec::Vec; use xcm::v4::{Asset, AssetId as XcmAssetId, Error as XcmError, Fungibility, Location, XcmContext}; use xcm::{IntoVersion, VersionedAssetId}; use xcm_executor::traits::{TransactAsset, WeightTrader}; @@ -309,7 +310,7 @@ pub mod pallet { } } -struct Trader(Weight, Option, core::marker::PhantomData); +pub struct Trader(Weight, Option, core::marker::PhantomData); impl Trader { fn compute_amount_to_charge( diff --git a/primitives/xcm/src/fee_handlers.rs b/primitives/xcm/src/fee_handlers.rs deleted file mode 100644 index b052d95826..0000000000 --- a/primitives/xcm/src/fee_handlers.rs +++ /dev/null @@ -1,466 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam 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. - -// Moonbeam 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 Moonbeam. If not, see . - -// We need to know how to charge for incoming assets -// We assume AssetIdInfoGetter is implemented and is capable of getting how much units we should -// charge for a given asset -// This takes the first fungible asset, and takes whatever UnitPerSecondGetter establishes -// UnitsToWeightRatio trait, which needs to be implemented by AssetIdInfoGetter - -use cumulus_primitives_core::XcmContext; -use frame_support::{ - pallet_prelude::Weight, - traits::{tokens::fungibles::Mutate, Get}, - weights::constants::WEIGHT_REF_TIME_PER_SECOND, -}; -use sp_runtime::traits::Zero; -use sp_std::marker::PhantomData; -use xcm::latest::{Asset, AssetId as xcmAssetId, Error as XcmError, Fungibility, Location}; - -use xcm_builder::TakeRevenue; -use xcm_executor::traits::{MatchesFungibles, WeightTrader}; - -pub struct FirstAssetTrader< - AssetType: TryFrom + Clone, - AssetIdInfoGetter: UnitsToWeightRatio, - R: TakeRevenue, ->( - Weight, - Option<(Location, u128, u128)>, // id, amount, units_per_second - PhantomData<(AssetType, AssetIdInfoGetter, R)>, -); -impl< - AssetType: TryFrom + Clone, - AssetIdInfoGetter: UnitsToWeightRatio, - R: TakeRevenue, - > WeightTrader for FirstAssetTrader -{ - fn new() -> Self { - FirstAssetTrader(Weight::zero(), None, PhantomData) - } - fn buy_weight( - &mut self, - weight: Weight, - payment: xcm_executor::AssetsInHolding, - _context: &XcmContext, - ) -> Result { - // can only call one time - if self.1.is_some() { - // TODO: better error - return Err(XcmError::NotWithdrawable); - } - - assert_eq!(self.0, Weight::zero()); - let first_asset = payment - .clone() - .fungible_assets_iter() - .next() - .ok_or(XcmError::TooExpensive)?; - - // We are only going to check first asset for now. This should be sufficient for simple token - // transfers. We will see later if we change this. - match (first_asset.id, first_asset.fun) { - (xcmAssetId(location), Fungibility::Fungible(_)) => { - let asset_type: AssetType = location - .clone() - .try_into() - .map_err(|_| XcmError::InvalidLocation)?; - // Shortcut if we know the asset is not supported - // This involves the same db read per block, mitigating any attack based on - // non-supported assets - if !AssetIdInfoGetter::payment_is_supported(asset_type.clone()) { - return Err(XcmError::AssetNotFound); - } - if let Some(units_per_second) = AssetIdInfoGetter::get_units_per_second(asset_type) - { - // TODO handle proof size payment - let amount = units_per_second.saturating_mul(weight.ref_time() as u128) - / (WEIGHT_REF_TIME_PER_SECOND as u128); - - // We dont need to proceed if the amount is 0 - // For cases (specially tests) where the asset is very cheap with respect - // to the weight needed - if amount.is_zero() { - return Ok(payment); - } - - let required = Asset { - fun: Fungibility::Fungible(amount), - id: xcmAssetId(location.clone()), - }; - let unused = payment - .checked_sub(required) - .map_err(|_| XcmError::TooExpensive)?; - - self.0 = weight; - self.1 = Some((location, amount, units_per_second)); - - return Ok(unused); - } else { - return Err(XcmError::TooExpensive); - }; - } - _ => return Err(XcmError::TooExpensive), - } - } - - // Refund weight. We will refund in whatever asset is stored in self. - fn refund_weight(&mut self, weight: Weight, _context: &XcmContext) -> Option { - if let Some((location, prev_amount, units_per_second)) = self.1.clone() { - let weight = weight.min(self.0); - self.0 -= weight; - let amount = units_per_second * (weight.ref_time() as u128) - / (WEIGHT_REF_TIME_PER_SECOND as u128); - let amount = amount.min(prev_amount); - self.1 = Some(( - location.clone(), - prev_amount.saturating_sub(amount), - units_per_second, - )); - Some(Asset { - fun: Fungibility::Fungible(amount), - id: xcmAssetId(location.clone()), - }) - } else { - None - } - } -} - -/// Deal with spent fees, deposit them as dictated by R -impl< - AssetType: TryFrom + Clone, - AssetIdInfoGetter: UnitsToWeightRatio, - R: TakeRevenue, - > Drop for FirstAssetTrader -{ - fn drop(&mut self) { - if let Some((id, amount, _)) = self.1.clone() { - if amount > 0 { - R::take_revenue((id, amount).into()); - } - } - } -} - -/// XCM fee depositor to which we implement the TakeRevenue trait -/// It receives a fungibles::Mutate implemented argument, a matcher to convert Asset into -/// AssetId and amount, and the fee receiver account -pub struct XcmFeesToAccount( - PhantomData<(Assets, Matcher, AccountId, ReceiverAccount)>, -); -impl< - Assets: Mutate, - Matcher: MatchesFungibles, - AccountId: Clone + Eq, - ReceiverAccount: Get, - > TakeRevenue for XcmFeesToAccount -{ - fn take_revenue(revenue: Asset) { - match Matcher::matches_fungibles(&revenue) { - Ok((asset_id, amount)) => { - let ok = Assets::mint_into(asset_id, &ReceiverAccount::get(), amount).is_ok(); - debug_assert!(ok, "`mint_into` cannot generally fail; qed"); - } - Err(_) => log::debug!( - target: "xcm", - "take revenue failed matching fungible" - ), - } - } -} - -// Defines the trait to obtain the units per second of a give asset_type for local execution -// This parameter will be used to charge for fees upon asset_type deposit -pub trait UnitsToWeightRatio { - // Whether payment in a particular asset_type is suppotrted - fn payment_is_supported(asset_type: AssetType) -> bool; - // Get units per second from asset type - fn get_units_per_second(asset_type: AssetType) -> Option; - #[cfg(feature = "runtime-benchmarks")] - fn set_units_per_second(_asset_type: AssetType, _fee_per_second: u128) {} -} - -#[cfg(test)] -mod test { - use super::*; - use cumulus_primitives_core::XcmHash; - use xcm::latest::{AssetId, Fungibility, Junction, Junctions}; - use xcm_executor::AssetsInHolding; - - const ARBITRARY_ML: Location = Location { - parents: 0u8, - interior: Junctions::Here, - }; - const ARBITRARY_ID: AssetId = AssetId(ARBITRARY_ML); - - impl UnitsToWeightRatio for () { - fn payment_is_supported(_asset_type: Location) -> bool { - true - } - fn get_units_per_second(_asset_type: Location) -> Option { - // return WEIGHT_REF_TIME_PER_SECOND to cancel the division out in buy_weight() - // this should make weight and payment amounts directly comparable - Some(WEIGHT_REF_TIME_PER_SECOND as u128) - } - } - - #[test] - fn test_buy_weight_accounts_weight_properly() { - let amount = 1000u128; - - let mut payment = AssetsInHolding::new(); - let location = Location { - parents: 0u8, - interior: Junctions::Here, - }; - payment.subsume(Asset { - id: AssetId(location.clone()), - fun: Fungibility::Fungible(amount), - }); - - let mut trader: FirstAssetTrader = FirstAssetTrader::new(); - let ctx = XcmContext { - origin: Some(location), - message_id: XcmHash::default(), - topic: None, - }; - let unused = trader - .buy_weight((amount as u64).into(), payment.clone(), &ctx) - .expect("can buy weight once"); - assert!(unused.is_empty()); - assert_eq!(trader.0, 1000u64.into()); - } - - #[test] - fn cant_call_buy_weight_twice() { - let mut trader: FirstAssetTrader = FirstAssetTrader::new(); - - // should be able to buy once - let mut asset_one_payment = AssetsInHolding::new(); - let location = Location { - parents: 0u8, - interior: [Junction::Parachain(1000)].into(), - }; - asset_one_payment.subsume(Asset { - id: AssetId(location.clone()), - fun: Fungibility::Fungible(100u128), - }); - let ctx = XcmContext { - origin: Some(location), - message_id: XcmHash::default(), - topic: None, - }; - let buy_one_results = trader - .buy_weight(100u64.into(), asset_one_payment.clone(), &ctx) - .expect("can buy weight once"); - assert_eq!(buy_one_results.fungible.len(), 0); // no unused amount - assert_eq!(trader.0, 100u64.into()); - assert_eq!( - trader.1, - Some(( - Location { - parents: 0u8, - interior: [Junction::Parachain(1000)].into() - }, - 100, - WEIGHT_REF_TIME_PER_SECOND as u128 - )) - ); - - // but not twice - let mut asset_two_payment = xcm_executor::AssetsInHolding::new(); - let location = Location { - parents: 0u8, - interior: [Junction::Parachain(1001)].into(), - }; - asset_two_payment.subsume(Asset { - id: AssetId(location.clone()), - fun: Fungibility::Fungible(10_000u128), - }); - let ctx = XcmContext { - origin: Some(location), - message_id: XcmHash::default(), - topic: None, - }; - assert_eq!( - trader.buy_weight(10_000u64.into(), asset_two_payment.clone(), &ctx), - Err(XcmError::NotWithdrawable), - ); - - // state should be unchanged - assert_eq!(trader.0, 100u64.into()); - assert_eq!( - trader.1, - Some(( - Location { - parents: 0u8, - interior: [Junction::Parachain(1000)].into() - }, - 100, - WEIGHT_REF_TIME_PER_SECOND as u128 - )) - ); - } - - #[test] - fn can_call_refund_weight_with_all_weight() { - let amount = 1000u128; - - let mut payment = AssetsInHolding::new(); - payment.subsume(Asset { - id: ARBITRARY_ID, - fun: Fungibility::Fungible(amount), - }); - - let mut trader: FirstAssetTrader = FirstAssetTrader::new(); - let ctx = XcmContext { - origin: Some(ARBITRARY_ML), - message_id: XcmHash::default(), - topic: None, - }; - let unused = trader - .buy_weight((amount as u64).into(), payment.clone(), &ctx) - .expect("can buy weight once"); - assert!(unused.is_empty()); - assert_eq!(trader.0, 1000u64.into()); - - assert_eq!( - trader.refund_weight(1000u64.into(), &ctx), - Some(Asset { - fun: Fungibility::Fungible(1000), - id: ARBITRARY_ID, - }) - ); - } - - #[test] - fn can_call_refund_multiple_times() { - let amount = 1000u128; - - let mut payment = AssetsInHolding::new(); - payment.subsume(Asset { - id: ARBITRARY_ID, - fun: Fungibility::Fungible(amount), - }); - - let mut trader: FirstAssetTrader = FirstAssetTrader::new(); - let ctx = XcmContext { - origin: Some(ARBITRARY_ML), - message_id: XcmHash::default(), - topic: None, - }; - let unused = trader - .buy_weight((amount as u64).into(), payment.clone(), &ctx) - .expect("can buy weight once"); - assert!(unused.is_empty()); - assert_eq!(trader.0, 1000u64.into()); - - assert_eq!( - trader.refund_weight(100u64.into(), &ctx), - Some(Asset { - fun: Fungibility::Fungible(100), - id: ARBITRARY_ID, - }) - ); - - // should reflect 100 weight and 100 currency deducted - assert_eq!(trader.0, 900u64.into()); - assert_eq!(trader.1.clone().unwrap().1, 900); - - // can call again - assert_eq!( - trader.refund_weight(200u64.into(), &ctx), - Some(Asset { - fun: Fungibility::Fungible(200), - id: ARBITRARY_ID, - }) - ); - - // should reflect another 200 weight and 200 currency deducted - assert_eq!(trader.0, 700u64.into()); - assert_eq!(trader.1.clone().unwrap().1, 700); - } - - #[test] - fn refund_weight_caps_weight() { - let amount = 1000u128; - - let mut payment = AssetsInHolding::new(); - payment.subsume(Asset { - id: ARBITRARY_ID, - fun: Fungibility::Fungible(amount), - }); - let ctx = XcmContext { - origin: Some(ARBITRARY_ML), - message_id: XcmHash::default(), - topic: None, - }; - let mut trader: FirstAssetTrader = FirstAssetTrader::new(); - let unused = trader - .buy_weight((amount as u64).into(), payment.clone(), &ctx) - .expect("can buy weight once"); - assert!(unused.is_empty()); - assert_eq!(trader.0, 1000u64.into()); - - // can't call with more weight - assert_eq!( - trader.refund_weight(9999u64.into(), &ctx), - Some(Asset { - fun: Fungibility::Fungible(1000), - id: ARBITRARY_ID, - }) - ); - assert_eq!(trader.0, Weight::zero()); - } - - #[test] - fn refund_weight_caps_currency() { - let amount = 1000u128; - - let mut payment = AssetsInHolding::new(); - payment.subsume(Asset { - id: ARBITRARY_ID, - fun: Fungibility::Fungible(amount), - }); - - let ctx = XcmContext { - origin: Some(ARBITRARY_ML), - message_id: XcmHash::default(), - topic: None, - }; - let mut trader: FirstAssetTrader = FirstAssetTrader::new(); - let unused = trader - .buy_weight((amount as u64).into(), payment.clone(), &ctx) - .expect("can buy weight once"); - assert!(unused.is_empty()); - assert_eq!(trader.0, 1000u64.into()); - - // adjust weight so that it will allow a higher amount -- we want to see that the currency - // (self.1.1) is capped even when weight is not - trader.0 = trader.0.saturating_add(1000u64.into()); - - // can't call with more weight - assert_eq!( - trader.refund_weight(1500u64.into(), &ctx), - Some(Asset { - fun: Fungibility::Fungible(1000), - id: ARBITRARY_ID, - }) - ); - assert_eq!(trader.0, 500u64.into()); // still thinks we have unreturned weight - } -} diff --git a/primitives/xcm/src/lib.rs b/primitives/xcm/src/lib.rs index d61f62d7e3..d63f13327d 100644 --- a/primitives/xcm/src/lib.rs +++ b/primitives/xcm/src/lib.rs @@ -24,9 +24,6 @@ pub use asset_id_conversions::*; mod constants; pub use constants::*; -mod fee_handlers; -pub use fee_handlers::*; - mod origin_conversion; pub use origin_conversion::*; diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index 292ba44bbc..f811e0dc39 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -27,6 +27,7 @@ pallet-precompile-benchmarks = { workspace = true } pallet-randomness = { workspace = true } pallet-relay-storage-roots = { workspace = true } pallet-xcm-transactor = { workspace = true } +pallet-xcm-weight-trader = { workspace = true } xcm-primitives = { workspace = true } # Substrate @@ -48,6 +49,7 @@ pallet-referenda = { workspace = true } pallet-scheduler = { workspace = true } pallet-sudo = { workspace = true } pallet-timestamp = { workspace = true } +pallet-transaction-payment = { workspace = true } pallet-treasury = { workspace = true } pallet-utility = { workspace = true } pallet-whitelist = { workspace = true } @@ -105,6 +107,8 @@ std = [ "pallet-xcm-transactor/std", "pallet-moonbeam-lazy-migrations/std", "pallet-identity/std", + "pallet-transaction-payment/std", + "pallet-xcm-weight-trader/std", "parity-scale-codec/std", "precompile-utils/std", "sp-consensus-slots/std", diff --git a/runtime/common/src/apis.rs b/runtime/common/src/apis.rs index 38912cb7d4..7db0247b36 100644 --- a/runtime/common/src/apis.rs +++ b/runtime/common/src/apis.rs @@ -745,69 +745,13 @@ macro_rules! impl_runtime_apis_plus_common { fn query_acceptable_payment_assets( xcm_version: xcm::Version ) -> Result, XcmPaymentApiError> { - if !matches!(xcm_version, 3) { - return Err(XcmPaymentApiError::UnhandledXcmVersion); - } - - let self_reserve_location: Location = Location::try_from(xcm_config::SelfReserve::get()) - .map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?; - - Ok([VersionedAssetId::V3(XcmAssetId::from(self_reserve_location))] - .into_iter() - .chain( - pallet_asset_manager::AssetTypeId::::iter_keys().filter_map(|asset_location| { - if !AssetManager::payment_is_supported(asset_location.clone()) { - return None; - } - - let location: Option = asset_location.into(); - if let Some(loc) = location { - return Some(VersionedAssetId::V3(loc.into())) - } - None - }) - ) - .filter_map(|asset| asset.into_version(xcm_version).ok()) - .collect()) + XcmWeightTrader::query_acceptable_payment_assets(xcm_version) } fn query_weight_to_asset_fee( weight: Weight, asset: VersionedAssetId ) -> Result { - let self_reserve_location: Location = Location::try_from(xcm_config::SelfReserve::get()) - .map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?; - - let local_asset = VersionedAssetId::V3(XcmAssetId::from(self_reserve_location)); - let asset = asset - .into_version(3) - .map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?; - - if asset == local_asset { - Ok(TransactionPayment::weight_to_fee(weight)) - }else { - let asset_v3: XcmAssetId = asset.try_into() - .map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?; - - if let XcmAssetId::Concrete(asset_location) = asset_v3 { - let asset_type: AssetType = AssetType::from(asset_location); - if !AssetManager::payment_is_supported(asset_type.clone()) { - return Err(XcmPaymentApiError::AssetNotFound); - } - - let units_per_sec = AssetManager::get_units_per_second(asset_type); - if let None = units_per_sec { - return Err(XcmPaymentApiError::WeightNotComputable); - } - - let final_asset_fee = units_per_sec - .unwrap_or_default() - .saturating_mul(weight.ref_time() as u128) - / (WEIGHT_REF_TIME_PER_SECOND as u128); - - return Ok(final_asset_fee) - } - Err(XcmPaymentApiError::AssetNotFound) - } + XcmWeightTrader::query_weight_to_asset_fee(weight, asset) } fn query_xcm_weight(message: VersionedXcm<()>) -> Result { diff --git a/runtime/common/src/migrations.rs b/runtime/common/src/migrations.rs index ea0620921b..1b2e277076 100644 --- a/runtime/common/src/migrations.rs +++ b/runtime/common/src/migrations.rs @@ -48,11 +48,108 @@ where } } +pub struct MigrateXcmFeesAssetsMeatdata(PhantomData); +impl Migration for MigrateXcmFeesAssetsMeatdata +where + Runtime: pallet_transaction_payment::Config, + Runtime: pallet_xcm_weight_trader::Config, +{ + fn friendly_name(&self) -> &str { + "MM_MigrateXcmFeesAssetsMeatdata" + } + + fn migrate(&self, _available_weight: Weight) -> Weight { + #[derive(parity_scale_codec::Decode, Eq, Ord, PartialEq, PartialOrd)] + enum OldAssetType { + Xcm(xcm::v3::Location), + } + + let supported_assets = + if let Some(supported_assets) = frame_support::storage::migration::get_storage_value::< + Vec, + >(b"AssetManager", b"SupportedFeePaymentAssets", &[]) + { + sp_std::collections::btree_set::BTreeSet::from_iter( + supported_assets + .into_iter() + .map(|OldAssetType::Xcm(location_v3)| location_v3), + ) + } else { + return Weight::MAX; + }; + + let mut assets: Vec<(xcm::v4::Location, (bool, u128))> = Vec::new(); + + for (OldAssetType::Xcm(location_v3), units_per_seconds) in + frame_support::storage::migration::storage_key_iter::< + OldAssetType, + u128, + frame_support::Blake2_128Concat, + >(b"AssetManager", b"AssetTypeUnitsPerSecond") + { + let enabled = supported_assets.get(&location_v3).is_some(); + + if let Ok(location_v4) = location_v3.try_into() { + assets.push((location_v4, (enabled, units_per_seconds))); + } + } + + //***** Start mutate storage *****// + + // Write asset metadat in new pallet_xcm_weight_trader + use frame_support::weights::WeightToFee as _; + for (asset_location, (enabled, units_per_second)) in assets { + let native_amount_per_second: u128 = + ::WeightToFee::weight_to_fee( + &Weight::from_parts( + frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND, + 0, + ), + ) + .try_into() + .unwrap_or(u128::MAX); + let relative_price: u128 = native_amount_per_second / units_per_second; + pallet_xcm_weight_trader::SupportedAssets::::insert( + asset_location, + (enabled, relative_price), + ); + } + + // Remove storage value AssetManager::SupportedFeePaymentAssets + frame_support::storage::unhashed::kill(&frame_support::storage::storage_prefix( + b"AssetManager", + b"SupportedFeePaymentAssets", + )); + + // Remove storage map AssetManager::AssetTypeUnitsPerSecond + let _ = frame_support::storage::migration::clear_storage_prefix( + b"AssetManager", + b"AssetTypeUnitsPerSecond", + &[], + None, + None, + ); + + Weight::MAX + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade(&self) -> Result, sp_runtime::DispatchError> { + todo!() + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(&self, state: Vec) -> Result<(), sp_runtime::DispatchError> { + todo!() + } +} + pub struct CommonMigrations(PhantomData); impl GetMigrations for CommonMigrations where - Runtime: pallet_xcm::Config, + Runtime: + pallet_xcm::Config + pallet_transaction_payment::Config + pallet_xcm_weight_trader::Config, Runtime::AccountId: Default, BlockNumberFor: Into, { @@ -192,6 +289,8 @@ where // completed in runtime 2900 // Box::new(remove_pallet_democracy), // Box::new(remove_collectives_addresses), + // completed in runtime 3200 + Box::new(MigrateXcmFeesAssetsMeatdata::(Default::default())), // permanent migrations Box::new(MigrateToLatestXcmVersion::(Default::default())), ] diff --git a/runtime/common/src/weights/pallet_asset_manager.rs b/runtime/common/src/weights/pallet_asset_manager.rs index 9d0ed109f6..0ea1ccf7f6 100644 --- a/runtime/common/src/weights/pallet_asset_manager.rs +++ b/runtime/common/src/weights/pallet_asset_manager.rs @@ -63,25 +63,6 @@ impl pallet_asset_manager::WeightInfo for WeightInfo .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `AssetManager::AssetTypeId` (r:1 w:0) - /// Proof: `AssetManager::AssetTypeId` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `AssetManager::SupportedFeePaymentAssets` (r:1 w:1) - /// Proof: `AssetManager::SupportedFeePaymentAssets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AssetManager::AssetTypeUnitsPerSecond` (r:0 w:1) - /// Proof: `AssetManager::AssetTypeUnitsPerSecond` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `x` is `[5, 100]`. - fn set_asset_units_per_second(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `611 + x * (9 ±0)` - // Estimated: `4000 + x * (10 ±0)` - // Minimum execution time: 19_578_000 picoseconds. - Weight::from_parts(18_705_391, 4000) - // Standard Error: 3_442 - .saturating_add(Weight::from_parts(792_309, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - .saturating_add(Weight::from_parts(0, 10).saturating_mul(x.into())) - } /// Storage: `AssetManager::SupportedFeePaymentAssets` (r:1 w:1) /// Proof: `AssetManager::SupportedFeePaymentAssets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `AssetManager::AssetIdType` (r:1 w:1) @@ -91,34 +72,17 @@ impl pallet_asset_manager::WeightInfo for WeightInfo /// Storage: `AssetManager::AssetTypeId` (r:0 w:2) /// Proof: `AssetManager::AssetTypeId` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `x` is `[5, 100]`. - fn change_existing_asset_type(x: u32, ) -> Weight { + fn change_existing_asset_type() -> Weight { // Proof Size summary in bytes: // Measured: `926 + x * (13 ±0)` // Estimated: `4309 + x * (15 ±0)` // Minimum execution time: 29_180_000 picoseconds. Weight::from_parts(29_891_006, 4309) // Standard Error: 4_391 - .saturating_add(Weight::from_parts(874_012, 0).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(874_012, 0)) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) - .saturating_add(Weight::from_parts(0, 15).saturating_mul(x.into())) - } - /// Storage: `AssetManager::SupportedFeePaymentAssets` (r:1 w:1) - /// Proof: `AssetManager::SupportedFeePaymentAssets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AssetManager::AssetTypeUnitsPerSecond` (r:0 w:1) - /// Proof: `AssetManager::AssetTypeUnitsPerSecond` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `x` is `[5, 100]`. - fn remove_supported_asset(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `196 + x * (5 ±0)` - // Estimated: `1678 + x * (5 ±0)` - // Minimum execution time: 15_115_000 picoseconds. - Weight::from_parts(13_493_610, 1678) - // Standard Error: 2_952 - .saturating_add(Weight::from_parts(694_325, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - .saturating_add(Weight::from_parts(0, 5).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 15)) } /// Storage: `AssetManager::SupportedFeePaymentAssets` (r:1 w:1) /// Proof: `AssetManager::SupportedFeePaymentAssets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -129,16 +93,16 @@ impl pallet_asset_manager::WeightInfo for WeightInfo /// Storage: `AssetManager::AssetTypeId` (r:0 w:1) /// Proof: `AssetManager::AssetTypeId` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `x` is `[5, 100]`. - fn remove_existing_asset_type(x: u32, ) -> Weight { + fn remove_existing_asset_type() -> Weight { // Proof Size summary in bytes: // Measured: `482 + x * (10 ±0)` // Estimated: `3955 + x * (10 ±0)` // Minimum execution time: 21_219_000 picoseconds. Weight::from_parts(20_476_212, 3955) // Standard Error: 3_389 - .saturating_add(Weight::from_parts(716_188, 0).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(716_188, 0)) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) - .saturating_add(Weight::from_parts(0, 10).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 10)) } } diff --git a/runtime/moonbase/Cargo.toml b/runtime/moonbase/Cargo.toml index f059b33244..98b96bd9fc 100644 --- a/runtime/moonbase/Cargo.toml +++ b/runtime/moonbase/Cargo.toml @@ -45,6 +45,7 @@ pallet-precompile-benchmarks = { workspace = true } pallet-proxy-genesis-companion = { workspace = true } pallet-randomness = { workspace = true } pallet-xcm-transactor = { workspace = true } +pallet-xcm-weight-trader = { workspace = true } # Moonbeam precompiles pallet-evm-precompile-author-mapping = { workspace = true } @@ -291,6 +292,7 @@ std = [ "pallet-whitelist/std", "pallet-xcm-transactor/std", "pallet-xcm/std", + "pallet-xcm-weight-trader/std", "parachain-info/std", "parachains-common/std", "parity-scale-codec/std", diff --git a/runtime/moonbase/src/lib.rs b/runtime/moonbase/src/lib.rs index 395af492f3..3dbeb72e03 100644 --- a/runtime/moonbase/src/lib.rs +++ b/runtime/moonbase/src/lib.rs @@ -117,13 +117,8 @@ use sp_std::{ #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; -use xcm::{ - v3::{AssetId as XcmAssetId, Location}, - IntoVersion, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm, -}; -use xcm_config::AssetType; +use xcm::{VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm}; use xcm_fee_payment_runtime_api::Error as XcmPaymentApiError; -use xcm_primitives::UnitsToWeightRatio; use smallvec::smallvec; use sp_runtime::serde::{Deserialize, Serialize}; @@ -1441,6 +1436,7 @@ construct_runtime! { MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event} = 54, EmergencyParaXcm: pallet_emergency_para_xcm::{Pallet, Call, Storage, Event} = 55, EvmForeignAssets: pallet_moonbeam_foreign_assets::{Pallet, Call, Storage, Event} = 56, + XcmWeightTrader: pallet_xcm_weight_trader::{Pallet, Call, Storage, Event} = 57, } } diff --git a/runtime/moonbase/src/xcm_config.rs b/runtime/moonbase/src/xcm_config.rs index 4e44f607a4..415417f74a 100644 --- a/runtime/moonbase/src/xcm_config.rs +++ b/runtime/moonbase/src/xcm_config.rs @@ -18,10 +18,10 @@ //! use super::{ - governance, AccountId, AssetId, AssetManager, Balance, Balances, DealWithFees, - EmergencyParaXcm, Erc20XcmBridge, EvmForeignAssets, MaintenanceMode, MessageQueue, - ParachainInfo, ParachainSystem, Perbill, PolkadotXcm, Runtime, RuntimeBlockWeights, - RuntimeCall, RuntimeEvent, RuntimeOrigin, Treasury, XcmpQueue, + governance, AccountId, AssetId, AssetManager, Balance, Balances, EmergencyParaXcm, + Erc20XcmBridge, EvmForeignAssets, MaintenanceMode, MessageQueue, ParachainInfo, + ParachainSystem, Perbill, PolkadotXcm, Runtime, RuntimeBlockWeights, RuntimeCall, RuntimeEvent, + RuntimeOrigin, Treasury, XcmpQueue, }; use crate::OpenTechCommitteeInstance; use moonbeam_runtime_common::weights as moonbase_weights; @@ -45,7 +45,7 @@ use xcm_builder::{ EnsureXcmOrigin, FungibleAdapter as XcmCurrencyAdapter, FungiblesAdapter, HashedDescription, NoChecking, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountKey20AsNative, SovereignSignedViaLocation, - TakeWeightCredit, UsingComponents, WeightInfoBounds, WithComputedOrigin, + TakeWeightCredit, WeightInfoBounds, WithComputedOrigin, }; use parachains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling}; @@ -61,8 +61,8 @@ use cumulus_primitives_core::{AggregateMessageOrigin, ParaId}; use orml_xcm_support::MultiNativeAsset; use xcm_primitives::{ AbsoluteAndRelativeReserve, AccountIdToCurrencyId, AccountIdToLocation, AsAssetType, - FirstAssetTrader, IsBridgedConcreteAssetFrom, SignedToAccountId20, UtilityAvailableCalls, - UtilityEncodeCall, XcmTransact, + IsBridgedConcreteAssetFrom, SignedToAccountId20, UtilityAvailableCalls, UtilityEncodeCall, + XcmTransact, }; use parity_scale_codec::{Decode, Encode}; @@ -232,23 +232,6 @@ parameter_types! { pub XcmFeesAccount: AccountId = Treasury::account_id(); } -/// This is the struct that will handle the revenue from xcm fees -/// We do not burn anything because we want to mimic exactly what -/// the sovereign account has -pub type XcmFeesToAccount = xcm_primitives::XcmFeesToAccount< - super::Assets, - ( - ConvertedConcreteId< - AssetId, - Balance, - AsAssetType, - JustTry, - >, - ), - AccountId, - XcmFeesAccount, ->; - // Our implementation of the Moonbeam Call // Attachs the right origin in case the call is made to pallet-ethereum-xcm #[cfg(not(feature = "evm-tracing"))] @@ -311,16 +294,7 @@ impl xcm_executor::Config for XcmExecutorConfig { // we use UsingComponents and the local way of handling fees // When we receive a non-reserve asset, we use AssetManager to fetch how many // units per second we should charge - type Trader = ( - UsingComponents< - ::WeightToFee, - SelfReserve, - AccountId, - Balances, - DealWithFees, - >, - FirstAssetTrader, - ); + type Trader = pallet_xcm_weight_trader::Trader; type ResponseHandler = PolkadotXcm; type SubscriptionService = PolkadotXcm; type AssetTrap = pallet_erc20_xcm_bridge::AssetTrapWrapper; @@ -778,6 +752,34 @@ impl pallet_moonbeam_foreign_assets::Config for Runtime { type XcmLocationToH160 = LocationToH160; } +pub struct AssetFeesFilter; +impl frame_support::traits::Contains for AssetFeesFilter { + fn contains(location: &Location) -> bool { + location.parent_count() > 0 + && location.first_interior() != Erc20XcmBridgePalletLocation::get().first_interior() + } +} + +impl pallet_xcm_weight_trader::Config for Runtime { + type AccountIdToLocation = AccountIdToLocation; + type AddSupportedAssetOrigin = EnsureRoot; + type AssetLocationFilter = AssetFeesFilter; + type AssetTransactor = AssetTransactors; + type Balance = Balance; + type EditSupportedAssetOrigin = EnsureRoot; + type NativeLocation = SelfReserve; + type PauseSupportedAssetOrigin = EnsureRoot; + type RemoveSupportedAssetOrigin = EnsureRoot; + type RuntimeEvent = RuntimeEvent; + type ResumeSupportedAssetOrigin = EnsureRoot; + // TODO generate weights + type WeightInfo = (); + type WeightToFee = ::WeightToFee; + type XcmFeesAccount = XcmFeesAccount; + #[cfg(feature = "runtime-benchmarks")] + type NotFilteredLocation = Location::parent(); +} + #[cfg(feature = "runtime-benchmarks")] mod testing { use super::*; diff --git a/runtime/moonbase/tests/xcm_tests.rs b/runtime/moonbase/tests/xcm_tests.rs index 24ad722407..b2044c585c 100644 --- a/runtime/moonbase/tests/xcm_tests.rs +++ b/runtime/moonbase/tests/xcm_tests.rs @@ -62,11 +62,10 @@ fn receive_relay_asset_from_relay() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( + assert_ok!(XcmWeightTrader::add_asset( parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 + Location::parent(), + 1u128, )); }); diff --git a/runtime/moonbeam/Cargo.toml b/runtime/moonbeam/Cargo.toml index 66c4d19981..fc046edbf2 100644 --- a/runtime/moonbeam/Cargo.toml +++ b/runtime/moonbeam/Cargo.toml @@ -45,6 +45,7 @@ pallet-precompile-benchmarks = { workspace = true } pallet-proxy-genesis-companion = { workspace = true } pallet-randomness = { workspace = true } pallet-xcm-transactor = { workspace = true } +pallet-xcm-weight-trader = { workspace = true } # Moonbeam precompiles pallet-evm-precompile-author-mapping = { workspace = true } @@ -281,6 +282,7 @@ std = [ "pallet-whitelist/std", "pallet-xcm-transactor/std", "pallet-xcm/std", + "pallet-xcm-weight-trader/std", "parachain-info/std", "parachains-common/std", "parity-scale-codec/std", diff --git a/runtime/moonbeam/src/lib.rs b/runtime/moonbeam/src/lib.rs index e2b6b86108..1c8742735e 100644 --- a/runtime/moonbeam/src/lib.rs +++ b/runtime/moonbeam/src/lib.rs @@ -21,8 +21,8 @@ //! * Moonbeam tokenomics #![cfg_attr(not(feature = "std"), no_std)] -// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. -#![recursion_limit = "256"] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 512. +#![recursion_limit = "512"] // Make the WASM binary available. #[cfg(feature = "std")] @@ -98,13 +98,8 @@ use sp_runtime::{ Perquintill, SaturatedConversion, }; use sp_std::{convert::TryFrom, prelude::*}; -use xcm::{ - v3::{AssetId as XcmAssetId, Location}, - IntoVersion, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm, -}; -use xcm_config::AssetType; +use xcm::{VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm}; use xcm_fee_payment_runtime_api::Error as XcmPaymentApiError; -use xcm_primitives::UnitsToWeightRatio; #[cfg(feature = "std")] use sp_version::NativeVersion; @@ -1454,6 +1449,7 @@ construct_runtime! { Erc20XcmBridge: pallet_erc20_xcm_bridge::{Pallet} = 110, MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event} = 111, EvmForeignAssets: pallet_moonbeam_foreign_assets::{Pallet, Call, Storage, Event} = 114, + XcmWeightTrader: pallet_xcm_weight_trader::{Pallet, Call, Storage, Event} = 115, // Utils RelayStorageRoots: pallet_relay_storage_roots::{Pallet, Storage} = 112, diff --git a/runtime/moonbeam/src/xcm_config.rs b/runtime/moonbeam/src/xcm_config.rs index 6fa1210f8e..492b60187c 100644 --- a/runtime/moonbeam/src/xcm_config.rs +++ b/runtime/moonbeam/src/xcm_config.rs @@ -18,7 +18,7 @@ //! use super::{ - governance, AccountId, AssetId, AssetManager, Balance, Balances, DealWithFees, Erc20XcmBridge, + governance, AccountId, AssetId, AssetManager, Balance, Balances, Erc20XcmBridge, MaintenanceMode, MessageQueue, ParachainInfo, ParachainSystem, Perbill, PolkadotXcm, Runtime, RuntimeBlockWeights, RuntimeCall, RuntimeEvent, RuntimeOrigin, Treasury, XcmpQueue, }; @@ -44,7 +44,7 @@ use xcm_builder::{ EnsureXcmOrigin, FungibleAdapter as XcmCurrencyAdapter, FungiblesAdapter, HashedDescription, NoChecking, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountKey20AsNative, SovereignSignedViaLocation, - TakeWeightCredit, UsingComponents, WeightInfoBounds, WithComputedOrigin, + TakeWeightCredit, WeightInfoBounds, WithComputedOrigin, }; use parachains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling}; @@ -59,8 +59,8 @@ use cumulus_primitives_core::{AggregateMessageOrigin, ParaId}; use orml_xcm_support::MultiNativeAsset; use xcm_primitives::{ AbsoluteAndRelativeReserve, AccountIdToCurrencyId, AccountIdToLocation, AsAssetType, - FirstAssetTrader, IsBridgedConcreteAssetFrom, SignedToAccountId20, UtilityAvailableCalls, - UtilityEncodeCall, XcmTransact, + IsBridgedConcreteAssetFrom, SignedToAccountId20, UtilityAvailableCalls, UtilityEncodeCall, + XcmTransact, }; use parity_scale_codec::{Decode, Encode}; @@ -220,23 +220,6 @@ parameter_types! { pub XcmFeesAccount: AccountId = Treasury::account_id(); } -/// This is the struct that will handle the revenue from xcm fees -/// We do not burn anything because we want to mimic exactly what -/// the sovereign account has -pub type XcmFeesToAccount = xcm_primitives::XcmFeesToAccount< - super::Assets, - ( - ConvertedConcreteId< - AssetId, - Balance, - AsAssetType, - JustTry, - >, - ), - AccountId, - XcmFeesAccount, ->; - pub struct SafeCallFilter; impl frame_support::traits::Contains for SafeCallFilter { fn contains(_call: &RuntimeCall) -> bool { @@ -299,16 +282,7 @@ impl xcm_executor::Config for XcmExecutorConfig { // we use UsingComponents and the local way of handling fees // When we receive a non-reserve asset, we use AssetManager to fetch how many // units per second we should charge - type Trader = ( - UsingComponents< - ::WeightToFee, - SelfReserve, - AccountId, - Balances, - DealWithFees, - >, - FirstAssetTrader, - ); + type Trader = pallet_xcm_weight_trader::Trader; type ResponseHandler = PolkadotXcm; type SubscriptionService = PolkadotXcm; type AssetTrap = pallet_erc20_xcm_bridge::AssetTrapWrapper; @@ -729,6 +703,34 @@ impl pallet_moonbeam_foreign_assets::Config for Runtime { type XcmLocationToH160 = LocationToH160; } +pub struct AssetFeesFilter; +impl frame_support::traits::Contains for AssetFeesFilter { + fn contains(location: &Location) -> bool { + location.parent_count() > 0 + && location.first_interior() != Erc20XcmBridgePalletLocation::get().first_interior() + } +} + +impl pallet_xcm_weight_trader::Config for Runtime { + type AccountIdToLocation = AccountIdToLocation; + type AddSupportedAssetOrigin = EnsureRoot; + type AssetLocationFilter = AssetFeesFilter; + type AssetTransactor = AssetTransactors; + type Balance = Balance; + type EditSupportedAssetOrigin = EnsureRoot; + type NativeLocation = SelfReserve; + type PauseSupportedAssetOrigin = EnsureRoot; + type RemoveSupportedAssetOrigin = EnsureRoot; + type RuntimeEvent = RuntimeEvent; + type ResumeSupportedAssetOrigin = EnsureRoot; + // TODO generate weights + type WeightInfo = (); + type WeightToFee = ::WeightToFee; + type XcmFeesAccount = XcmFeesAccount; + #[cfg(feature = "runtime-benchmarks")] + type NotFilteredLocation = Location::parent(); +} + #[cfg(feature = "runtime-benchmarks")] mod testing { use super::*; diff --git a/runtime/moonriver/Cargo.toml b/runtime/moonriver/Cargo.toml index 1bf5e5c6a4..6075c2a7e0 100644 --- a/runtime/moonriver/Cargo.toml +++ b/runtime/moonriver/Cargo.toml @@ -45,6 +45,7 @@ pallet-precompile-benchmarks = { workspace = true } pallet-proxy-genesis-companion = { workspace = true } pallet-randomness = { workspace = true } pallet-xcm-transactor = { workspace = true } +pallet-xcm-weight-trader = { workspace = true } # Moonbeam precompiles pallet-evm-precompile-author-mapping = { workspace = true } @@ -281,6 +282,7 @@ std = [ "pallet-whitelist/std", "pallet-xcm-transactor/std", "pallet-xcm/std", + "pallet-xcm-weight-trader/std", "parachain-info/std", "parachains-common/std", "parity-scale-codec/std", diff --git a/runtime/moonriver/src/lib.rs b/runtime/moonriver/src/lib.rs index ba2b196098..c416e55ca7 100644 --- a/runtime/moonriver/src/lib.rs +++ b/runtime/moonriver/src/lib.rs @@ -21,8 +21,8 @@ //! * Moonriver tokenomics #![cfg_attr(not(feature = "std"), no_std)] -// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. -#![recursion_limit = "256"] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 512. +#![recursion_limit = "512"] // Make the WASM binary available. #[cfg(feature = "std")] @@ -98,13 +98,8 @@ use sp_runtime::{ Perquintill, SaturatedConversion, }; use sp_std::{convert::TryFrom, prelude::*}; -use xcm::{ - v3::{AssetId as XcmAssetId, Location}, - IntoVersion, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm, -}; -use xcm_config::AssetType; +use xcm::{VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm}; use xcm_fee_payment_runtime_api::Error as XcmPaymentApiError; -use xcm_primitives::UnitsToWeightRatio; use smallvec::smallvec; #[cfg(feature = "std")] @@ -1457,6 +1452,7 @@ construct_runtime! { Erc20XcmBridge: pallet_erc20_xcm_bridge::{Pallet} = 110, MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event} = 111, EvmForeignAssets: pallet_moonbeam_foreign_assets::{Pallet, Call, Storage, Event} = 114, + XcmWeightTrader: pallet_xcm_weight_trader::{Pallet, Call, Storage, Event} = 115, // Utils RelayStorageRoots: pallet_relay_storage_roots::{Pallet, Storage} = 112, diff --git a/runtime/moonriver/src/xcm_config.rs b/runtime/moonriver/src/xcm_config.rs index 38645915da..157bca2e6e 100644 --- a/runtime/moonriver/src/xcm_config.rs +++ b/runtime/moonriver/src/xcm_config.rs @@ -18,7 +18,7 @@ //! use super::{ - governance, AccountId, AssetId, AssetManager, Balance, Balances, DealWithFees, Erc20XcmBridge, + governance, AccountId, AssetId, AssetManager, Balance, Balances, Erc20XcmBridge, MaintenanceMode, MessageQueue, ParachainInfo, ParachainSystem, Perbill, PolkadotXcm, Runtime, RuntimeBlockWeights, RuntimeCall, RuntimeEvent, RuntimeOrigin, Treasury, XcmpQueue, }; @@ -44,7 +44,7 @@ use xcm_builder::{ EnsureXcmOrigin, FungibleAdapter as XcmCurrencyAdapter, FungiblesAdapter, HashedDescription, NoChecking, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountKey20AsNative, SovereignSignedViaLocation, - TakeWeightCredit, UsingComponents, WeightInfoBounds, WithComputedOrigin, + TakeWeightCredit, WeightInfoBounds, WithComputedOrigin, }; use parachains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling}; @@ -59,8 +59,8 @@ use cumulus_primitives_core::{AggregateMessageOrigin, ParaId}; use orml_xcm_support::MultiNativeAsset; use xcm_primitives::{ AbsoluteAndRelativeReserve, AccountIdToCurrencyId, AccountIdToLocation, AsAssetType, - FirstAssetTrader, IsBridgedConcreteAssetFrom, SignedToAccountId20, UtilityAvailableCalls, - UtilityEncodeCall, XcmTransact, + IsBridgedConcreteAssetFrom, SignedToAccountId20, UtilityAvailableCalls, UtilityEncodeCall, + XcmTransact, }; use parity_scale_codec::{Decode, Encode}; @@ -228,23 +228,6 @@ parameter_types! { pub XcmFeesAccount: AccountId = Treasury::account_id(); } -/// This is the struct that will handle the revenue from xcm fees -/// We do not burn anything because we want to mimic exactly what -/// the sovereign account has -pub type XcmFeesToAccount = xcm_primitives::XcmFeesToAccount< - super::Assets, - ( - ConvertedConcreteId< - AssetId, - Balance, - AsAssetType, - JustTry, - >, - ), - AccountId, - XcmFeesAccount, ->; - pub struct SafeCallFilter; impl frame_support::traits::Contains for SafeCallFilter { fn contains(_call: &RuntimeCall) -> bool { @@ -307,16 +290,7 @@ impl xcm_executor::Config for XcmExecutorConfig { // we use UsingComponents and the local way of handling fees // When we receive a non-reserve asset, we use AssetManager to fetch how many // units per second we should charge - type Trader = ( - UsingComponents< - ::WeightToFee, - SelfReserve, - AccountId, - Balances, - DealWithFees, - >, - FirstAssetTrader, - ); + type Trader = pallet_xcm_weight_trader::Trader; type ResponseHandler = PolkadotXcm; type SubscriptionService = PolkadotXcm; type AssetTrap = pallet_erc20_xcm_bridge::AssetTrapWrapper; @@ -742,6 +716,34 @@ impl pallet_moonbeam_foreign_assets::Config for Runtime { type XcmLocationToH160 = LocationToH160; } +pub struct AssetFeesFilter; +impl frame_support::traits::Contains for AssetFeesFilter { + fn contains(location: &Location) -> bool { + location.parent_count() > 0 + && location.first_interior() != Erc20XcmBridgePalletLocation::get().first_interior() + } +} + +impl pallet_xcm_weight_trader::Config for Runtime { + type AccountIdToLocation = AccountIdToLocation; + type AddSupportedAssetOrigin = EnsureRoot; + type AssetLocationFilter = AssetFeesFilter; + type AssetTransactor = AssetTransactors; + type Balance = Balance; + type EditSupportedAssetOrigin = EnsureRoot; + type NativeLocation = SelfReserve; + type PauseSupportedAssetOrigin = EnsureRoot; + type RemoveSupportedAssetOrigin = EnsureRoot; + type RuntimeEvent = RuntimeEvent; + type ResumeSupportedAssetOrigin = EnsureRoot; + // TODO generate weights + type WeightInfo = (); + type WeightToFee = ::WeightToFee; + type XcmFeesAccount = XcmFeesAccount; + #[cfg(feature = "runtime-benchmarks")] + type NotFilteredLocation = Location::parent(); +} + #[cfg(feature = "runtime-benchmarks")] mod testing { use super::*; From 24998877bbe1e0145cab87272e3f327998108f52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Fri, 23 Aug 2024 13:33:23 +0200 Subject: [PATCH 06/27] avoid div by zero --- pallets/xcm-weight-trader/src/lib.rs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/pallets/xcm-weight-trader/src/lib.rs b/pallets/xcm-weight-trader/src/lib.rs index 17b5504786..e35733b0c0 100644 --- a/pallets/xcm-weight-trader/src/lib.rs +++ b/pallets/xcm-weight-trader/src/lib.rs @@ -123,8 +123,8 @@ pub mod pallet { AssetNotPaused, /// XCM location filtered XcmLocationFiltered, - /// The units price cannot be zero - UnitsCannotBeZero, + /// The relative price cannot be zero + PriceCannotBeZero, } #[pallet::event] @@ -159,7 +159,7 @@ pub mod pallet { ) -> DispatchResult { T::AddSupportedAssetOrigin::ensure_origin(origin)?; - ensure!(relative_price != 0, Error::::UnitsCannotBeZero); + ensure!(relative_price != 0, Error::::PriceCannotBeZero); ensure!( !SupportedAssets::::contains_key(&location), Error::::AssetAlreadyAdded @@ -188,7 +188,7 @@ pub mod pallet { ) -> DispatchResult { T::EditSupportedAssetOrigin::ensure_origin(origin)?; - ensure!(relative_price != 0, Error::::UnitsCannotBeZero); + ensure!(relative_price != 0, Error::::PriceCannotBeZero); ensure!( SupportedAssets::::contains_key(&location), Error::::AssetNotFound @@ -322,14 +322,18 @@ impl Trader { .try_into() .map_err(|_| XcmError::Overflow) } else if let Some(relative_price) = Pallet::::get_asset_relative_price(asset_location) { - let native_amount: u128 = ::WeightToFee::weight_to_fee(&weight) - .try_into() - .map_err(|_| XcmError::Overflow)?; - Ok(native_amount - .checked_mul(10u128.pow(RELATIVE_PRICE_DECIMALS)) - .ok_or(XcmError::Overflow)? - .checked_div(relative_price) - .ok_or(XcmError::Overflow)?) + if relative_price == 0u128 { + Ok(0u128) + } else { + let native_amount: u128 = ::WeightToFee::weight_to_fee(&weight) + .try_into() + .map_err(|_| XcmError::Overflow)?; + Ok(native_amount + .checked_mul(10u128.pow(RELATIVE_PRICE_DECIMALS)) + .ok_or(XcmError::Overflow)? + .checked_div(relative_price) + .ok_or(XcmError::Overflow)?) + } } else { Err(XcmError::AssetNotFound) } From 2492d890904f129e7cea2261bb9a7453f2fdf7e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Fri, 23 Aug 2024 13:56:58 +0200 Subject: [PATCH 07/27] refactor moonbase rust tests to use new pallet xcm-weight-trader --- runtime/moonbase/tests/xcm_mock/parachain.rs | 71 +++--- runtime/moonbase/tests/xcm_tests.rs | 238 +++++-------------- 2 files changed, 101 insertions(+), 208 deletions(-) diff --git a/runtime/moonbase/tests/xcm_mock/parachain.rs b/runtime/moonbase/tests/xcm_mock/parachain.rs index 4f39468545..da216325dd 100644 --- a/runtime/moonbase/tests/xcm_mock/parachain.rs +++ b/runtime/moonbase/tests/xcm_mock/parachain.rs @@ -44,15 +44,15 @@ use pallet_ethereum::PostLogContent; use polkadot_core_primitives::BlockNumber as RelayBlockNumber; use polkadot_parachain::primitives::{Id as ParaId, Sibling}; use xcm::latest::{ - AssetId as XcmAssetId, Error as XcmError, ExecuteXcm, + Error as XcmError, ExecuteXcm, Junction::{PalletInstance, Parachain}, Location, NetworkId, Outcome, Xcm, }; use xcm_builder::{ AccountKey20Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, ConvertedConcreteId, EnsureXcmOrigin, FixedRateOfFungible, - FixedWeightBounds, FungibleAdapter as XcmCurrencyAdapter, FungiblesAdapter, IsConcrete, - NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + AllowTopLevelPaidExecutionFrom, ConvertedConcreteId, EnsureXcmOrigin, FixedWeightBounds, + FungibleAdapter as XcmCurrencyAdapter, FungiblesAdapter, IsConcrete, NoChecking, + ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountKey20AsNative, SovereignSignedViaLocation, TakeWeightCredit, WithComputedOrigin, }; @@ -286,32 +286,20 @@ pub type XcmBarrier = ( parameter_types! { /// Xcm fees will go to the treasury account pub XcmFeesAccount: AccountId = Treasury::account_id(); + /// Parachain token units per second of execution + pub ParaTokensPerSecond: u128 = 1000000000000; } -/// This is the struct that will handle the revenue from xcm fees -pub type XcmFeesToAccount_ = xcm_primitives::XcmFeesToAccount< - Assets, - ( - ConvertedConcreteId< - AssetId, - Balance, - xcm_primitives::AsAssetType, - JustTry, - >, - ), - AccountId, - XcmFeesAccount, ->; +pub struct WeightToFee; +impl sp_weights::WeightToFee for WeightToFee { + type Balance = Balance; -parameter_types! { - // We cannot skip the native trader for some specific tests, so we will have to work with - // a native trader that charges same number of units as weight - // We use both the old and new anchoring logics - pub ParaTokensPerSecond: (XcmAssetId, u128, u128) = ( - AssetId(SelfReserve::get()), - 1000000000000, - 0, - ); + fn weight_to_fee(weight: &Weight) -> Self::Balance { + use sp_runtime::SaturatedConversion as _; + Self::Balance::saturated_from(weight.ref_time()) + .saturating_mul(ParaTokensPerSecond::get()) + .saturating_div(frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND as u128) + } } parameter_types! { @@ -351,14 +339,7 @@ impl Config for XcmConfig { type UniversalLocation = UniversalLocation; type Barrier = XcmBarrier; type Weigher = FixedWeightBounds; - // We use three traders - // When we receive either representation of the self-reserve asset, - // When we receive a non-reserve asset, we use AssetManager to fetch how many - // units per second we should charge - type Trader = ( - FixedRateOfFungible, - xcm_primitives::FirstAssetTrader, - ); + type Trader = pallet_xcm_weight_trader::Trader; type ResponseHandler = PolkadotXcm; type SubscriptionService = PolkadotXcm; @@ -828,6 +809,25 @@ impl pallet_xcm_transactor::Config for Runtime { type MaxHrmpFee = xcm_builder::Case; } +impl pallet_xcm_weight_trader::Config for Runtime { + type AccountIdToLocation = xcm_primitives::AccountIdToLocation; + type AddSupportedAssetOrigin = EnsureRoot; + type AssetLocationFilter = Everything; + type AssetTransactor = AssetTransactors; + type Balance = Balance; + type EditSupportedAssetOrigin = EnsureRoot; + type NativeLocation = SelfReserve; + type PauseSupportedAssetOrigin = EnsureRoot; + type RemoveSupportedAssetOrigin = EnsureRoot; + type RuntimeEvent = RuntimeEvent; + type ResumeSupportedAssetOrigin = EnsureRoot; + type WeightInfo = (); + type WeightToFee = WeightToFee; + type XcmFeesAccount = XcmFeesAccount; + #[cfg(feature = "runtime-benchmarks")] + type NotFilteredLocation = Location::parent(); +} + parameter_types! { pub const MinimumPeriod: u64 = 1000; } @@ -1077,6 +1077,7 @@ construct_runtime!( XTokens: orml_xtokens, AssetManager: pallet_asset_manager, XcmTransactor: pallet_xcm_transactor, + XcmWeightTrader: pallet_xcm_weight_trader, Treasury: pallet_treasury, Proxy: pallet_proxy, diff --git a/runtime/moonbase/tests/xcm_tests.rs b/runtime/moonbase/tests/xcm_tests.rs index b2044c585c..dced70b2fd 100644 --- a/runtime/moonbase/tests/xcm_tests.rs +++ b/runtime/moonbase/tests/xcm_tests.rs @@ -34,13 +34,44 @@ use xcm::latest::prelude::{ Junction, Junctions, Limited, Location, OriginKind, PalletInstance, Parachain, QueryResponse, Reanchorable, Response, WeightLimit, WithdrawAsset, Xcm, }; -use xcm::{VersionedLocation, WrapVersion}; +use xcm::{IntoVersion, VersionedLocation, WrapVersion}; use xcm_executor::traits::ConvertLocation; use xcm_mock::*; use xcm_primitives::{UtilityEncodeCall, DEFAULT_PROOF_SIZE}; use xcm_simulator::TestExt; mod common; use cumulus_primitives_core::relay_chain::HrmpChannelId; + +fn add_supported_asset(asset_type: parachain::AssetType, units_per_second: u128) -> Result<(), ()> { + let parachain::AssetType::Xcm(location_v3) = asset_type; + let VersionedLocation::V4(location_v4) = VersionedLocation::V3(location_v3) + .into_version(4) + .map_err(|_| ())? + else { + return Err(()); + }; + use frame_support::weights::WeightToFee as _; + let native_amount_per_second: u128 = + ::WeightToFee::weight_to_fee( + &Weight::from_parts( + frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND, + 0, + ), + ) + .try_into() + .map_err(|_| ())?; + let relative_price: u128 = if units_per_second > 0u128 { + native_amount_per_second / units_per_second + } else { + 0u128 + }; + pallet_xcm_weight_trader::SupportedAssets::::insert( + location_v4, + (true, relative_price), + ); + Ok(()) +} + // Send a relay asset (like DOT) to a parachain A #[test] fn receive_relay_asset_from_relay() { @@ -62,11 +93,7 @@ fn receive_relay_asset_from_relay() { 1u128, true )); - assert_ok!(XcmWeightTrader::add_asset( - parachain::RuntimeOrigin::root(), - Location::parent(), - 1u128, - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128,)); }); // Actually send relay asset to parachain @@ -117,12 +144,7 @@ fn send_relay_asset_to_relay() { true )); // Free execution - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 0u128,)); }); let dest: Location = Junction::AccountKey20 { @@ -209,12 +231,7 @@ fn send_relay_asset_to_para_b() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location.clone(), - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128,)); }); // Register asset in paraB. Free execution @@ -226,12 +243,7 @@ fn send_relay_asset_to_para_b() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 0u128,)); }); // First send relay chain asset to Parachain A like in previous test @@ -316,12 +328,7 @@ fn send_para_a_asset_to_para_b() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 0u128,)); }); // Send para A asset from para A to para B @@ -388,12 +395,7 @@ fn send_para_a_asset_from_para_b_to_para_c() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location.clone(), - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128,)); }); // Register para A asset in parachain C. Free execution @@ -405,12 +407,7 @@ fn send_para_a_asset_from_para_b_to_para_c() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 0u128,)); }); // Send para A asset to para B @@ -504,12 +501,7 @@ fn send_para_a_asset_to_para_b_and_back_to_para_a() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 0u128,)); }); // Send para A asset to para B @@ -602,12 +594,7 @@ fn send_para_a_asset_to_para_b_and_back_to_para_a_with_new_reanchoring() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 0u128,)); }); let dest = Location { @@ -715,12 +702,7 @@ fn receive_relay_asset_with_trader() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 2500000000000u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 2500000000000u128,)); }); let dest: Location = Junction::AccountKey20 { @@ -777,12 +759,7 @@ fn send_para_a_asset_to_para_b_with_trader() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 2500000000000u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 2500000000000u128,)); }); let dest = Location { @@ -855,12 +832,7 @@ fn send_para_a_asset_to_para_b_with_trader_and_fee() { true )); // With these units per second, 80K weight convrets to 1 asset unit - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 12500000u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 12500000u128,)); }); let dest = Location { @@ -930,12 +902,7 @@ fn error_when_not_paying_enough() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 2500000000000u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 2500000000000u128,)); }); // We are sending 100 tokens from relay. @@ -979,12 +946,7 @@ fn transact_through_derivative_multilocation() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 1u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 1u128,)); // Root can set transact info assert_ok!(XcmTransactor::set_transact_info( @@ -1149,12 +1111,7 @@ fn transact_through_derivative_with_custom_fee_weight() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 1u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 1u128,)); }); // Let's construct the call to know how much weight it is going to require @@ -1305,12 +1262,7 @@ fn transact_through_derivative_with_custom_fee_weight_refund() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 1u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 1u128,)); }); // Let's construct the call to know how much weight it is going to require @@ -1460,12 +1412,7 @@ fn transact_through_sovereign() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 1u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 1u128,)); // Root can set transact info assert_ok!(XcmTransactor::set_transact_info( @@ -1733,12 +1680,7 @@ fn transact_through_sovereign_with_custom_fee_weight() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 1u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 1u128,)); }); let dest: Location = AccountKey20 { @@ -1887,12 +1829,7 @@ fn transact_through_sovereign_with_custom_fee_weight_refund() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 1u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 1u128,)); }); let dest: Location = AccountKey20 { @@ -2041,12 +1978,7 @@ fn test_automatic_versioning_on_runtime_upgrade_with_relay() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 0u128,)); }); let response = Response::Version(2); @@ -2195,12 +2127,7 @@ fn test_automatic_versioning_on_runtime_upgrade_with_para_b() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 0u128,)); }); ParaA::execute_with(|| { @@ -2328,12 +2255,7 @@ fn receive_asset_with_no_sufficients_not_possible_if_non_existent_account() { 1u128, false )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 0u128,)); }); // Actually send relay asset to parachain @@ -2408,12 +2330,7 @@ fn receive_assets_with_sufficients_true_allows_non_funded_account_to_receive_ass 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 0u128,)); }); // Actually send relay asset to parachain @@ -2469,12 +2386,7 @@ fn evm_account_receiving_assets_should_handle_sufficients_ref_count() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 0u128,)); }); // Actually send relay asset to parachain @@ -2539,12 +2451,7 @@ fn empty_account_should_not_be_reset() { 1u128, false )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 0u128,)); }); // Send native token to evm_account @@ -2650,12 +2557,7 @@ fn test_statemint_like() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 0u128,)); }); Statemint::execute_with(|| { @@ -2764,12 +2666,7 @@ fn send_statemint_asset_from_para_a_to_statemint_with_relay_fee() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - relay_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(relay_location, 0u128,)); assert_ok!(AssetManager::register_foreign_asset( parachain::RuntimeOrigin::root(), @@ -2778,12 +2675,7 @@ fn send_statemint_asset_from_para_a_to_statemint_with_relay_fee() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - statemint_location_asset, - 0u128, - 1 - )); + assert_ok!(add_supported_asset(statemint_location_asset, 0u128,)); }); let parachain_beneficiary_from_relay: Location = Junction::AccountKey20 { @@ -3249,7 +3141,7 @@ fn transact_through_signed_multilocation_para_to_para() { assert_ok!(XcmTransactor::set_fee_per_second( parachain::RuntimeOrigin::root(), Box::new(xcm::VersionedLocation::V4(para_b_balances.clone())), - parachain::ParaTokensPerSecond::get().1 as u128, + parachain::ParaTokensPerSecond::get(), )); ancestry = parachain::UniversalLocation::get().into(); }); @@ -3349,7 +3241,7 @@ fn transact_through_signed_multilocation_para_to_para_refund() { assert_ok!(XcmTransactor::set_fee_per_second( parachain::RuntimeOrigin::root(), Box::new(xcm::VersionedLocation::V4(para_b_balances.clone())), - parachain::ParaTokensPerSecond::get().1 as u128, + parachain::ParaTokensPerSecond::get(), )); ancestry = parachain::UniversalLocation::get().into(); }); @@ -3463,7 +3355,7 @@ fn transact_through_signed_multilocation_para_to_para_ethereum() { assert_ok!(XcmTransactor::set_fee_per_second( parachain::RuntimeOrigin::root(), Box::new(xcm::VersionedLocation::V4(para_b_balances.clone())), - parachain::ParaTokensPerSecond::get().1 as u128, + parachain::ParaTokensPerSecond::get(), )); ancestry = parachain::UniversalLocation::get().into(); }); @@ -3592,7 +3484,7 @@ fn transact_through_signed_multilocation_para_to_para_ethereum_no_proxy_fails() assert_ok!(XcmTransactor::set_fee_per_second( parachain::RuntimeOrigin::root(), Box::new(xcm::VersionedLocation::V4(para_b_balances.clone())), - parachain::ParaTokensPerSecond::get().1 as u128, + parachain::ParaTokensPerSecond::get(), )); ancestry = parachain::UniversalLocation::get().into(); }); @@ -3717,7 +3609,7 @@ fn transact_through_signed_multilocation_para_to_para_ethereum_proxy_succeeds() assert_ok!(XcmTransactor::set_fee_per_second( parachain::RuntimeOrigin::root(), Box::new(xcm::VersionedLocation::V4(para_b_balances.clone())), - parachain::ParaTokensPerSecond::get().1 as u128, + parachain::ParaTokensPerSecond::get(), )); ancestry = parachain::UniversalLocation::get().into(); }); From d6ff588f43f384021198a7f7f5bc371104ba7c01 Mon Sep 17 00:00:00 2001 From: Rodrigo Quelhas Date: Fri, 23 Aug 2024 23:07:36 +0100 Subject: [PATCH 08/27] refactor moonbeam/moonriver rust tests to use new pallet xcm-weight-trader --- runtime/moonbeam/tests/xcm_mock/parachain.rs | 70 ++--- runtime/moonbeam/tests/xcm_tests.rs | 227 +++++------------ runtime/moonriver/tests/xcm_mock/parachain.rs | 70 ++--- runtime/moonriver/tests/xcm_tests.rs | 241 +++++------------- 4 files changed, 210 insertions(+), 398 deletions(-) diff --git a/runtime/moonbeam/tests/xcm_mock/parachain.rs b/runtime/moonbeam/tests/xcm_mock/parachain.rs index 4bdd9f2f5c..5b394c26bb 100644 --- a/runtime/moonbeam/tests/xcm_mock/parachain.rs +++ b/runtime/moonbeam/tests/xcm_mock/parachain.rs @@ -45,15 +45,15 @@ use pallet_ethereum::PostLogContent; use polkadot_core_primitives::BlockNumber as RelayBlockNumber; use polkadot_parachain::primitives::{Id as ParaId, Sibling}; use xcm::latest::{ - AssetId as XcmAssetId, Error as XcmError, ExecuteXcm, + Error as XcmError, ExecuteXcm, Junction::{PalletInstance, Parachain}, Location, NetworkId, Outcome, Xcm, }; use xcm_builder::{ AccountKey20Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, ConvertedConcreteId, EnsureXcmOrigin, FixedRateOfFungible, - FixedWeightBounds, FungibleAdapter as XcmCurrencyAdapter, FungiblesAdapter, IsConcrete, - NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + AllowTopLevelPaidExecutionFrom, ConvertedConcreteId, EnsureXcmOrigin, FixedWeightBounds, + FungibleAdapter as XcmCurrencyAdapter, FungiblesAdapter, IsConcrete, NoChecking, + ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountKey20AsNative, SovereignSignedViaLocation, TakeWeightCredit, WithComputedOrigin, }; @@ -282,31 +282,20 @@ pub type XcmBarrier = ( parameter_types! { /// Xcm fees will go to the treasury account pub XcmFeesAccount: AccountId = Treasury::account_id(); + /// Parachain token units per second of execution + pub ParaTokensPerSecond: u128 = 1000000000000; } -/// This is the struct that will handle the revenue from xcm fees -pub type XcmFeesToAccount_ = xcm_primitives::XcmFeesToAccount< - Assets, - ( - ConvertedConcreteId< - AssetId, - Balance, - xcm_primitives::AsAssetType, - JustTry, - >, - ), - AccountId, - XcmFeesAccount, ->; +pub struct WeightToFee; +impl sp_weights::WeightToFee for WeightToFee { + type Balance = Balance; -parameter_types! { - // We cannot skip the native trader for some specific tests, so we will have to work with - // a native trader that charges same number of units as weight - pub ParaTokensPerSecond: (XcmAssetId, u128, u128) = ( - AssetId(SelfReserve::get()), - 1000000000000, - 0, - ); + fn weight_to_fee(weight: &Weight) -> Self::Balance { + use sp_runtime::SaturatedConversion as _; + Self::Balance::saturated_from(weight.ref_time()) + .saturating_mul(ParaTokensPerSecond::get()) + .saturating_div(frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND as u128) + } } parameter_types! { @@ -342,14 +331,7 @@ impl Config for XcmConfig { type UniversalLocation = UniversalLocation; type Barrier = XcmBarrier; type Weigher = FixedWeightBounds; - // We use two traders - // When we receive the self-reserve asset, - // When we receive a non-reserve asset, we use AssetManager to fetch how many - // units per second we should charge - type Trader = ( - FixedRateOfFungible, - xcm_primitives::FirstAssetTrader, - ); + type Trader = pallet_xcm_weight_trader::Trader; type ResponseHandler = PolkadotXcm; type SubscriptionService = PolkadotXcm; type AssetTrap = PolkadotXcm; @@ -813,6 +795,25 @@ impl pallet_xcm_transactor::Config for Runtime { type MaxHrmpFee = xcm_builder::Case; } +impl pallet_xcm_weight_trader::Config for Runtime { + type AccountIdToLocation = xcm_primitives::AccountIdToLocation; + type AddSupportedAssetOrigin = EnsureRoot; + type AssetLocationFilter = Everything; + type AssetTransactor = AssetTransactors; + type Balance = Balance; + type EditSupportedAssetOrigin = EnsureRoot; + type NativeLocation = SelfReserve; + type PauseSupportedAssetOrigin = EnsureRoot; + type RemoveSupportedAssetOrigin = EnsureRoot; + type RuntimeEvent = RuntimeEvent; + type ResumeSupportedAssetOrigin = EnsureRoot; + type WeightInfo = (); + type WeightToFee = WeightToFee; + type XcmFeesAccount = XcmFeesAccount; + #[cfg(feature = "runtime-benchmarks")] + type NotFilteredLocation = Location::parent(); +} + parameter_types! { pub const MinimumPeriod: u64 = 1000; } @@ -1062,6 +1063,7 @@ construct_runtime!( XTokens: orml_xtokens, AssetManager: pallet_asset_manager, XcmTransactor: pallet_xcm_transactor, + XcmWeightTrader: pallet_xcm_weight_trader, Treasury: pallet_treasury, Proxy: pallet_proxy, diff --git a/runtime/moonbeam/tests/xcm_tests.rs b/runtime/moonbeam/tests/xcm_tests.rs index ff3409abc9..fb37466bb6 100644 --- a/runtime/moonbeam/tests/xcm_tests.rs +++ b/runtime/moonbeam/tests/xcm_tests.rs @@ -34,7 +34,7 @@ use xcm::latest::prelude::{ AccountId32, AccountKey20, GeneralIndex, Junction, Junctions, Limited, Location, OriginKind, PalletInstance, Parachain, QueryResponse, Reanchorable, Response, WeightLimit, Xcm, }; -use xcm::{VersionedLocation, WrapVersion}; +use xcm::{IntoVersion, VersionedLocation, WrapVersion}; use xcm_executor::traits::ConvertLocation; use xcm_mock::parachain; use xcm_mock::relay_chain; @@ -42,6 +42,36 @@ use xcm_mock::*; use xcm_primitives::{UtilityEncodeCall, DEFAULT_PROOF_SIZE}; use xcm_simulator::TestExt; +fn add_supported_asset(asset_type: parachain::AssetType, units_per_second: u128) -> Result<(), ()> { + let parachain::AssetType::Xcm(location_v3) = asset_type; + let VersionedLocation::V4(location_v4) = VersionedLocation::V3(location_v3) + .into_version(4) + .map_err(|_| ())? + else { + return Err(()); + }; + use frame_support::weights::WeightToFee as _; + let native_amount_per_second: u128 = + ::WeightToFee::weight_to_fee( + &Weight::from_parts( + frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND, + 0, + ), + ) + .try_into() + .map_err(|_| ())?; + let relative_price: u128 = if units_per_second > 0u128 { + native_amount_per_second / units_per_second + } else { + 0u128 + }; + pallet_xcm_weight_trader::SupportedAssets::::insert( + location_v4, + (true, relative_price), + ); + Ok(()) +} + // Send a relay asset (like DOT) to a parachain A #[test] fn receive_relay_asset_from_relay() { @@ -64,12 +94,7 @@ fn receive_relay_asset_from_relay() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Actually send relay asset to parachain @@ -122,12 +147,7 @@ fn send_relay_asset_to_relay() { true )); // Free execution - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location, 0u128)); }); let dest: Location = Junction::AccountKey20 { @@ -213,12 +233,7 @@ fn send_relay_asset_to_para_b() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location.clone(), - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Register asset in paraB. Free execution @@ -230,12 +245,7 @@ fn send_relay_asset_to_para_b() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); let dest: Location = Junction::AccountKey20 { @@ -319,12 +329,7 @@ fn send_para_a_asset_to_para_b() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Send para A asset from para A to para B @@ -392,12 +397,7 @@ fn send_para_a_asset_from_para_b_to_para_c() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location.clone(), - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Register para A asset in parachain C. Free execution @@ -409,12 +409,7 @@ fn send_para_a_asset_from_para_b_to_para_c() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); let dest = Location { @@ -506,12 +501,7 @@ fn send_para_a_asset_to_para_b_and_back_to_para_a() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Send para A asset to para B @@ -605,11 +595,9 @@ fn receive_relay_asset_with_trader() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 2500000000000u128, - 0 + assert_ok!(add_supported_asset( + source_location.clone(), + 2500000000000u128 )); }); @@ -667,11 +655,9 @@ fn send_para_a_asset_to_para_b_with_trader() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 2500000000000u128, - 0 + assert_ok!(add_supported_asset( + source_location.clone(), + 2500000000000u128 )); }); @@ -745,12 +731,7 @@ fn send_para_a_asset_to_para_b_with_trader_and_fee() { true )); // With these units per second, 80K weight convrets to 1 asset unit - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 12500000u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 12500000u128)); }); let dest = Location { @@ -820,11 +801,9 @@ fn error_when_not_paying_enough() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 2500000000000u128, - 0 + assert_ok!(add_supported_asset( + source_location.clone(), + 2500000000000u128 )); }); @@ -869,12 +848,7 @@ fn transact_through_derivative_multilocation() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 1u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 1u128)); // Root can set transact info assert_ok!(XcmTransactor::set_transact_info( @@ -1029,12 +1003,7 @@ fn transact_through_derivative_with_custom_fee_weight() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 1u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 1u128)); }); // Let's construct the call to know how much weight it is going to require @@ -1185,12 +1154,7 @@ fn transact_through_derivative_with_custom_fee_weight_refund() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 1u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 1u128)); }); // Let's construct the call to know how much weight it is going to require @@ -1340,12 +1304,7 @@ fn transact_through_sovereign() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 1u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 1u128)); // Root can set transact info assert_ok!(XcmTransactor::set_transact_info( @@ -1613,12 +1572,7 @@ fn transact_through_sovereign_with_custom_fee_weight() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 1u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 1u128)); }); let dest: Location = AccountKey20 { @@ -1767,12 +1721,7 @@ fn transact_through_sovereign_with_custom_fee_weight_refund() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 1u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 1u128)); }); let dest: Location = AccountKey20 { @@ -1921,12 +1870,7 @@ fn test_automatic_versioning_on_runtime_upgrade_with_relay() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); let response = Response::Version(2); @@ -2053,12 +1997,7 @@ fn receive_asset_with_no_sufficients_not_possible_if_non_existent_account() { 1u128, false )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Actually send relay asset to parachain @@ -2133,12 +2072,7 @@ fn receive_assets_with_sufficients_true_allows_non_funded_account_to_receive_ass 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Actually send relay asset to parachain @@ -2194,12 +2128,7 @@ fn evm_account_receiving_assets_should_handle_sufficients_ref_count() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Actually send relay asset to parachain @@ -2264,12 +2193,7 @@ fn empty_account_should_not_be_reset() { 1u128, false )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Send native token to evm_account @@ -2375,12 +2299,7 @@ fn test_statemint_like() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); Statemint::execute_with(|| { @@ -2490,12 +2409,7 @@ fn send_statemint_asset_from_para_a_to_statemint_with_relay_fee() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - relay_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(relay_location.clone(), 0u128)); assert_ok!(AssetManager::register_foreign_asset( parachain::RuntimeOrigin::root(), @@ -2504,12 +2418,7 @@ fn send_statemint_asset_from_para_a_to_statemint_with_relay_fee() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - statemint_location_asset, - 0u128, - 1 - )); + assert_ok!(add_supported_asset(relay_location.clone(), 0u128)); }); let parachain_beneficiary_from_relay: Location = Junction::AccountKey20 { @@ -2976,7 +2885,7 @@ fn transact_through_signed_multilocation_para_to_para() { assert_ok!(XcmTransactor::set_fee_per_second( parachain::RuntimeOrigin::root(), Box::new(xcm::VersionedLocation::V4(para_b_balances.clone())), - parachain::ParaTokensPerSecond::get().1 as u128, + parachain::ParaTokensPerSecond::get(), )); ancestry = parachain::UniversalLocation::get().into(); }); @@ -3074,7 +2983,7 @@ fn transact_through_signed_multilocation_para_to_para_refund() { assert_ok!(XcmTransactor::set_fee_per_second( parachain::RuntimeOrigin::root(), Box::new(xcm::VersionedLocation::V4(para_b_balances.clone())), - parachain::ParaTokensPerSecond::get().1 as u128, + parachain::ParaTokensPerSecond::get(), )); ancestry = parachain::UniversalLocation::get().into(); }); @@ -3186,7 +3095,7 @@ fn transact_through_signed_multilocation_para_to_para_ethereum() { assert_ok!(XcmTransactor::set_fee_per_second( parachain::RuntimeOrigin::root(), Box::new(xcm::VersionedLocation::V4(para_b_balances.clone())), - parachain::ParaTokensPerSecond::get().1 as u128, + parachain::ParaTokensPerSecond::get(), )); ancestry = parachain::UniversalLocation::get().into(); }); @@ -3313,7 +3222,7 @@ fn transact_through_signed_multilocation_para_to_para_ethereum_no_proxy_fails() assert_ok!(XcmTransactor::set_fee_per_second( parachain::RuntimeOrigin::root(), Box::new(xcm::VersionedLocation::V4(para_b_balances.clone())), - parachain::ParaTokensPerSecond::get().1 as u128, + parachain::ParaTokensPerSecond::get(), )); ancestry = parachain::UniversalLocation::get().into(); }); @@ -3436,7 +3345,7 @@ fn transact_through_signed_multilocation_para_to_para_ethereum_proxy_succeeds() assert_ok!(XcmTransactor::set_fee_per_second( parachain::RuntimeOrigin::root(), Box::new(xcm::VersionedLocation::V4(para_b_balances.clone())), - parachain::ParaTokensPerSecond::get().1 as u128, + parachain::ParaTokensPerSecond::get(), )); ancestry = parachain::UniversalLocation::get().into(); }); diff --git a/runtime/moonriver/tests/xcm_mock/parachain.rs b/runtime/moonriver/tests/xcm_mock/parachain.rs index 4a7f38e165..a0cfaef334 100644 --- a/runtime/moonriver/tests/xcm_mock/parachain.rs +++ b/runtime/moonriver/tests/xcm_mock/parachain.rs @@ -43,15 +43,15 @@ use pallet_ethereum::PostLogContent; use polkadot_core_primitives::BlockNumber as RelayBlockNumber; use polkadot_parachain::primitives::{Id as ParaId, Sibling}; use xcm::latest::{ - AssetId as XcmAssetId, Error as XcmError, ExecuteXcm, + Error as XcmError, ExecuteXcm, Junction::{PalletInstance, Parachain}, Location, NetworkId, Outcome, Xcm, }; use xcm_builder::{ AccountKey20Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, ConvertedConcreteId, EnsureXcmOrigin, FixedRateOfFungible, - FixedWeightBounds, FungibleAdapter as XcmCurrencyAdapter, FungiblesAdapter, IsConcrete, - NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + AllowTopLevelPaidExecutionFrom, ConvertedConcreteId, EnsureXcmOrigin, FixedWeightBounds, + FungibleAdapter as XcmCurrencyAdapter, FungiblesAdapter, IsConcrete, NoChecking, + ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountKey20AsNative, SovereignSignedViaLocation, TakeWeightCredit, WithComputedOrigin, }; @@ -282,31 +282,20 @@ pub type XcmBarrier = ( parameter_types! { /// Xcm fees will go to the treasury account pub XcmFeesAccount: AccountId = Treasury::account_id(); + /// Parachain token units per second of execution + pub ParaTokensPerSecond: u128 = 1000000000000; } -/// This is the struct that will handle the revenue from xcm fees -pub type XcmFeesToAccount_ = xcm_primitives::XcmFeesToAccount< - Assets, - ( - ConvertedConcreteId< - AssetId, - Balance, - xcm_primitives::AsAssetType, - JustTry, - >, - ), - AccountId, - XcmFeesAccount, ->; +pub struct WeightToFee; +impl sp_weights::WeightToFee for WeightToFee { + type Balance = Balance; -parameter_types! { - // We cannot skip the native trader for some specific tests, so we will have to work with - // a native trader that charges same number of units as weight - pub ParaTokensPerSecond: (XcmAssetId, u128, u128) = ( - AssetId(SelfReserve::get()), - 1000000000000, - 0, - ); + fn weight_to_fee(weight: &Weight) -> Self::Balance { + use sp_runtime::SaturatedConversion as _; + Self::Balance::saturated_from(weight.ref_time()) + .saturating_mul(ParaTokensPerSecond::get()) + .saturating_div(frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND as u128) + } } parameter_types! { @@ -342,14 +331,7 @@ impl Config for XcmConfig { type UniversalLocation = UniversalLocation; type Barrier = XcmBarrier; type Weigher = FixedWeightBounds; - // We use three traders - // When we receive either representation of the self-reserve asset, - // When we receive a non-reserve asset, we use AssetManager to fetch how many - // units per second we should charge - type Trader = ( - FixedRateOfFungible, - xcm_primitives::FirstAssetTrader, - ); + type Trader = pallet_xcm_weight_trader::Trader; type ResponseHandler = PolkadotXcm; type SubscriptionService = PolkadotXcm; type AssetTrap = PolkadotXcm; @@ -818,6 +800,25 @@ impl pallet_xcm_transactor::Config for Runtime { type MaxHrmpFee = xcm_builder::Case; } +impl pallet_xcm_weight_trader::Config for Runtime { + type AccountIdToLocation = xcm_primitives::AccountIdToLocation; + type AddSupportedAssetOrigin = EnsureRoot; + type AssetLocationFilter = Everything; + type AssetTransactor = AssetTransactors; + type Balance = Balance; + type EditSupportedAssetOrigin = EnsureRoot; + type NativeLocation = SelfReserve; + type PauseSupportedAssetOrigin = EnsureRoot; + type RemoveSupportedAssetOrigin = EnsureRoot; + type RuntimeEvent = RuntimeEvent; + type ResumeSupportedAssetOrigin = EnsureRoot; + type WeightInfo = (); + type WeightToFee = WeightToFee; + type XcmFeesAccount = XcmFeesAccount; + #[cfg(feature = "runtime-benchmarks")] + type NotFilteredLocation = Location::parent(); +} + parameter_types! { pub const MinimumPeriod: u64 = 1000; } @@ -1068,6 +1069,7 @@ construct_runtime!( XTokens: orml_xtokens, AssetManager: pallet_asset_manager, XcmTransactor: pallet_xcm_transactor, + XcmWeightTrader: pallet_xcm_weight_trader, Treasury: pallet_treasury, Proxy: pallet_proxy, diff --git a/runtime/moonriver/tests/xcm_tests.rs b/runtime/moonriver/tests/xcm_tests.rs index 2ca25f5530..e04ddde4c9 100644 --- a/runtime/moonriver/tests/xcm_tests.rs +++ b/runtime/moonriver/tests/xcm_tests.rs @@ -30,7 +30,7 @@ use xcm::latest::prelude::{ Junction, Junctions, Limited, Location, OriginKind, PalletInstance, Parachain, QueryResponse, Reanchorable, Response, WeightLimit, WithdrawAsset, Xcm, }; -use xcm::{VersionedLocation, WrapVersion}; +use xcm::{IntoVersion, VersionedLocation, WrapVersion}; use xcm_executor::traits::ConvertLocation; use xcm_mock::parachain; use xcm_mock::relay_chain; @@ -43,6 +43,36 @@ use pallet_xcm_transactor::{ }; use xcm_primitives::{UtilityEncodeCall, DEFAULT_PROOF_SIZE}; +fn add_supported_asset(asset_type: parachain::AssetType, units_per_second: u128) -> Result<(), ()> { + let parachain::AssetType::Xcm(location_v3) = asset_type; + let VersionedLocation::V4(location_v4) = VersionedLocation::V3(location_v3) + .into_version(4) + .map_err(|_| ())? + else { + return Err(()); + }; + use frame_support::weights::WeightToFee as _; + let native_amount_per_second: u128 = + ::WeightToFee::weight_to_fee( + &Weight::from_parts( + frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND, + 0, + ), + ) + .try_into() + .map_err(|_| ())?; + let relative_price: u128 = if units_per_second > 0u128 { + native_amount_per_second / units_per_second + } else { + 0u128 + }; + pallet_xcm_weight_trader::SupportedAssets::::insert( + location_v4, + (true, relative_price), + ); + Ok(()) +} + // Send a relay asset (like DOT) to a parachain A #[test] fn receive_relay_asset_from_relay() { @@ -64,12 +94,7 @@ fn receive_relay_asset_from_relay() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Actually send relay asset to parachain @@ -120,12 +145,7 @@ fn send_relay_asset_to_relay() { true )); // free execution - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); let dest: Location = Junction::AccountKey20 { @@ -210,12 +230,7 @@ fn send_relay_asset_to_para_b() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location.clone(), - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Register asset in paraB. Free execution @@ -227,12 +242,7 @@ fn send_relay_asset_to_para_b() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // First send relay chain asset to Parachain A like in previous test @@ -316,12 +326,7 @@ fn send_para_a_asset_to_para_b() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Send para A asset from para A to para B @@ -389,12 +394,7 @@ fn send_para_a_asset_from_para_b_to_para_c() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location.clone(), - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Register para A asset in parachain C. Free execution @@ -406,12 +406,7 @@ fn send_para_a_asset_from_para_b_to_para_c() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Send para A asset to para B @@ -505,12 +500,7 @@ fn send_para_a_asset_to_para_b_and_back_to_para_a() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Send para A asset to para B @@ -604,12 +594,7 @@ fn send_para_a_asset_to_para_b_and_back_to_para_a_with_new_reanchoring() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); let dest = Location { @@ -760,11 +745,9 @@ fn receive_relay_asset_with_trader() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 2500000000000u128, - 0 + assert_ok!(add_supported_asset( + source_location.clone(), + 2500000000000u128 )); }); @@ -822,11 +805,9 @@ fn send_para_a_asset_to_para_b_with_trader() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 2500000000000u128, - 0 + assert_ok!(add_supported_asset( + source_location.clone(), + 2500000000000u128 )); }); @@ -900,12 +881,7 @@ fn send_para_a_asset_to_para_b_with_trader_and_fee() { true )); // With these units per second, 80K weight convrets to 1 asset unit - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 12500000u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 12500000u128)); }); let dest = Location { @@ -975,11 +951,9 @@ fn error_when_not_paying_enough() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 2500000000000u128, - 0 + assert_ok!(add_supported_asset( + source_location.clone(), + 2500000000000u128 )); }); @@ -1024,12 +998,7 @@ fn transact_through_derivative_multilocation() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 1u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 1u128)); // Root can set transact info assert_ok!(XcmTransactor::set_transact_info( @@ -1184,12 +1153,7 @@ fn transact_through_derivative_with_custom_fee_weight() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 1u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 1u128)); }); // Let's construct the call to know how much weight it is going to require @@ -1340,12 +1304,7 @@ fn transact_through_derivative_with_custom_fee_weight_refund() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 1u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 1u128)); }); // Let's construct the call to know how much weight it is going to require @@ -1495,12 +1454,7 @@ fn transact_through_sovereign() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 1u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 1u128)); // Root can set transact info assert_ok!(XcmTransactor::set_transact_info( @@ -1768,12 +1722,7 @@ fn transact_through_sovereign_with_custom_fee_weight() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 1u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 1u128)); }); let dest: Location = AccountKey20 { @@ -1922,12 +1871,7 @@ fn transact_through_sovereign_with_custom_fee_weight_refund() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 1u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 1u128)); }); let dest: Location = AccountKey20 { @@ -2076,12 +2020,7 @@ fn test_automatic_versioning_on_runtime_upgrade_with_relay() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); let response = Response::Version(2); @@ -2231,12 +2170,7 @@ fn test_automatic_versioning_on_runtime_upgrade_with_para_b() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); ParaA::execute_with(|| { @@ -2363,12 +2297,7 @@ fn receive_asset_with_no_sufficients_not_possible_if_non_existent_account() { 1u128, false )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Actually send relay asset to parachain @@ -2443,12 +2372,7 @@ fn receive_assets_with_sufficients_true_allows_non_funded_account_to_receive_ass 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Actually send relay asset to parachain @@ -2504,12 +2428,7 @@ fn evm_account_receiving_assets_should_handle_sufficients_ref_count() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Actually send relay asset to parachain @@ -2574,12 +2493,7 @@ fn empty_account_should_not_be_reset() { 1u128, false )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); // Send native token to evm_account @@ -2685,12 +2599,7 @@ fn test_statemine_like() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - source_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(source_location.clone(), 0u128)); }); Statemine::execute_with(|| { @@ -2799,12 +2708,7 @@ fn send_statemint_asset_from_para_a_to_statemine_with_relay_fee() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - relay_location, - 0u128, - 0 - )); + assert_ok!(add_supported_asset(relay_location.clone(), 0u128)); assert_ok!(AssetManager::register_foreign_asset( parachain::RuntimeOrigin::root(), @@ -2813,12 +2717,7 @@ fn send_statemint_asset_from_para_a_to_statemine_with_relay_fee() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - statemine_location_asset, - 0u128, - 1 - )); + assert_ok!(add_supported_asset(statemine_location_asset.clone(), 0u128)); }); let parachain_beneficiary_from_relay: Location = Junction::AccountKey20 { @@ -3285,7 +3184,7 @@ fn transact_through_signed_multilocation_para_to_para() { assert_ok!(XcmTransactor::set_fee_per_second( parachain::RuntimeOrigin::root(), Box::new(xcm::VersionedLocation::V4(para_b_balances.clone())), - parachain::ParaTokensPerSecond::get().1 as u128, + parachain::ParaTokensPerSecond::get(), )); ancestry = parachain::UniversalLocation::get().into(); }); @@ -3383,7 +3282,7 @@ fn transact_through_signed_multilocation_para_to_para_refund() { assert_ok!(XcmTransactor::set_fee_per_second( parachain::RuntimeOrigin::root(), Box::new(xcm::VersionedLocation::V4(para_b_balances.clone())), - parachain::ParaTokensPerSecond::get().1 as u128, + parachain::ParaTokensPerSecond::get(), )); ancestry = parachain::UniversalLocation::get().into(); }); @@ -3495,7 +3394,7 @@ fn transact_through_signed_multilocation_para_to_para_ethereum() { assert_ok!(XcmTransactor::set_fee_per_second( parachain::RuntimeOrigin::root(), Box::new(xcm::VersionedLocation::V4(para_b_balances.clone())), - parachain::ParaTokensPerSecond::get().1 as u128, + parachain::ParaTokensPerSecond::get(), )); ancestry = parachain::UniversalLocation::get().into(); }); @@ -3622,7 +3521,7 @@ fn transact_through_signed_multilocation_para_to_para_ethereum_no_proxy_fails() assert_ok!(XcmTransactor::set_fee_per_second( parachain::RuntimeOrigin::root(), Box::new(xcm::VersionedLocation::V4(para_b_balances.clone())), - parachain::ParaTokensPerSecond::get().1 as u128, + parachain::ParaTokensPerSecond::get(), )); ancestry = parachain::UniversalLocation::get().into(); }); @@ -3745,7 +3644,7 @@ fn transact_through_signed_multilocation_para_to_para_ethereum_proxy_succeeds() assert_ok!(XcmTransactor::set_fee_per_second( parachain::RuntimeOrigin::root(), Box::new(xcm::VersionedLocation::V4(para_b_balances.clone())), - parachain::ParaTokensPerSecond::get().1 as u128, + parachain::ParaTokensPerSecond::get(), )); ancestry = parachain::UniversalLocation::get().into(); }); From 90537cb23c0089650d5e0e317559f332b4c12a0a Mon Sep 17 00:00:00 2001 From: Rodrigo Quelhas Date: Mon, 26 Aug 2024 09:18:24 +0100 Subject: [PATCH 09/27] fix pallet compilation with feature runtime-benchmark and tests --- pallets/asset-manager/src/benchmarks.rs | 8 +- pallets/asset-manager/src/lib.rs | 6 +- pallets/asset-manager/src/tests.rs | 110 +----------------- pallets/xcm-weight-trader/src/tests.rs | 4 +- runtime/common/src/apis.rs | 6 +- runtime/moonbase/Cargo.toml | 1 + runtime/moonbase/src/xcm_config.rs | 2 +- runtime/moonbase/tests/xcm_mock/parachain.rs | 6 +- runtime/moonbeam/Cargo.toml | 1 + runtime/moonbeam/src/xcm_config.rs | 2 +- runtime/moonbeam/tests/xcm_mock/parachain.rs | 6 +- runtime/moonriver/Cargo.toml | 1 + runtime/moonriver/src/xcm_config.rs | 2 +- runtime/moonriver/tests/xcm_mock/parachain.rs | 6 +- 14 files changed, 33 insertions(+), 128 deletions(-) diff --git a/pallets/asset-manager/src/benchmarks.rs b/pallets/asset-manager/src/benchmarks.rs index fafb37e9bf..e4c1ec26d7 100644 --- a/pallets/asset-manager/src/benchmarks.rs +++ b/pallets/asset-manager/src/benchmarks.rs @@ -37,7 +37,8 @@ benchmarks! { } change_existing_asset_type { - for i in 0..1 { + let x in 5..100; + for i in 0..x { let asset_type: T::ForeignAssetType = Location::new(0, X1(GeneralIndex(i as u128))).into(); let metadata = T::AssetRegistrarMetadata::default(); let amount = 1u32.into(); @@ -62,7 +63,8 @@ benchmarks! { } remove_existing_asset_type { - for i in 0..1 { + let x in 5..100; + for i in 0..x { let asset_type: T::ForeignAssetType = Location::new(0, X1(GeneralIndex(i as u128))).into(); let metadata = T::AssetRegistrarMetadata::default(); let amount = 1u32.into(); @@ -83,8 +85,6 @@ benchmarks! { }: _(RawOrigin::Root, asset_id, x) verify { assert!(Pallet::::asset_id_type(asset_id).is_none()); - assert!(Pallet::::asset_type_units_per_second(&asset_type_to_be_removed).is_none()); - assert!(!Pallet::::supported_fee_payment_assets().contains(&asset_type_to_be_removed)); } } diff --git a/pallets/asset-manager/src/lib.rs b/pallets/asset-manager/src/lib.rs index d825d5b3e2..4d5813a326 100644 --- a/pallets/asset-manager/src/lib.rs +++ b/pallets/asset-manager/src/lib.rs @@ -152,10 +152,8 @@ pub mod pallet { metadata: T::AssetRegistrarMetadata, }, /// Changed the amount of units we are charging per execution second for a given asset - UnitsPerSecondChanged { - asset_type: T::ForeignAssetType, - units_per_second: u128, - }, + #[deprecated(note = "Should not be used")] + UnitsPerSecondChanged, /// Changed the xcm type mapping for a given asset id ForeignAssetXcmLocationChanged { asset_id: T::AssetId, diff --git a/pallets/asset-manager/src/tests.rs b/pallets/asset-manager/src/tests.rs index e25a66bda9..aa2037b727 100644 --- a/pallets/asset-manager/src/tests.rs +++ b/pallets/asset-manager/src/tests.rs @@ -119,16 +119,7 @@ fn test_root_can_change_asset_id_type() { 1 )); - // New one contains the new asset type units per second - assert_eq!( - AssetManager::asset_type_units_per_second(MockAssetType::MockAsset(2)).unwrap(), - 200 - ); - - // Old one does not contain units per second - assert!(AssetManager::asset_type_units_per_second(MockAssetType::MockAsset(1)).is_none()); - - // New associations are stablished + // New associations are established assert_eq!( AssetManager::asset_id_type(1).unwrap(), MockAssetType::MockAsset(2) @@ -147,10 +138,6 @@ fn test_root_can_change_asset_id_type() { asset: MockAssetType::MockAsset(1), metadata: 0, }, - crate::Event::UnitsPerSecondChanged { - asset_type: MockAssetType::MockAsset(1), - units_per_second: 200, - }, crate::Event::ForeignAssetXcmLocationChanged { asset_id: 1, new_asset_type: MockAssetType::MockAsset(2), @@ -159,88 +146,6 @@ fn test_root_can_change_asset_id_type() { }); } -#[test] -fn test_change_units_per_second_after_setting_it_once() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(AssetManager::register_foreign_asset( - RuntimeOrigin::root(), - MockAssetType::MockAsset(1), - 0u32.into(), - 1u32.into(), - true, - )); - - assert_eq!( - AssetManager::asset_type_units_per_second(MockAssetType::MockAsset(1)).unwrap(), - 200 - ); - assert!(AssetManager::supported_fee_payment_assets().contains(&MockAssetType::MockAsset(1))); - - assert_eq!( - AssetManager::asset_type_units_per_second(MockAssetType::MockAsset(1)).unwrap(), - 100 - ); - assert!(AssetManager::supported_fee_payment_assets().contains(&MockAssetType::MockAsset(1))); - - expect_events(vec![crate::Event::ForeignAssetRegistered { - asset_id: 1, - asset: MockAssetType::MockAsset(1), - metadata: 0, - }]); - }); -} - -#[test] -fn test_root_can_change_units_per_second_and_then_remove() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(AssetManager::register_foreign_asset( - RuntimeOrigin::root(), - MockAssetType::MockAsset(1), - 0u32.into(), - 1u32.into(), - true, - )); - - assert_eq!( - AssetManager::asset_type_units_per_second(MockAssetType::MockAsset(1)).unwrap(), - 200 - ); - assert!(AssetManager::supported_fee_payment_assets().contains(&MockAssetType::MockAsset(1))); - - assert!( - !AssetManager::supported_fee_payment_assets().contains(&MockAssetType::MockAsset(1)) - ); - - expect_events(vec![crate::Event::ForeignAssetRegistered { - asset_id: 1, - asset: MockAssetType::MockAsset(1), - metadata: 0, - }]); - }); -} - -#[test] -fn test_weight_hint_error() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(AssetManager::register_foreign_asset( - RuntimeOrigin::root(), - MockAssetType::MockAsset(1), - 0u32.into(), - 1u32.into(), - true, - )); - - assert_noop!( - AssetManager::remove_supported_asset( - RuntimeOrigin::root(), - MockAssetType::MockAsset(1), - 0 - ), - Error::::TooLowNumAssetsWeightHint - ); - }); -} - #[test] fn test_asset_id_non_existent_error() { ExtBuilder::default().build().execute_with(|| { @@ -277,19 +182,12 @@ fn test_root_can_remove_asset_association() { assert!(AssetManager::asset_type_id(MockAssetType::MockAsset(1)).is_none()); assert!(AssetManager::asset_id_type(1).is_none()); - // Units per second removed - assert!(AssetManager::asset_type_units_per_second(MockAssetType::MockAsset(1)).is_none()); - expect_events(vec![ crate::Event::ForeignAssetRegistered { asset_id: 1, asset: MockAssetType::MockAsset(1), metadata: 0, }, - crate::Event::UnitsPerSecondChanged { - asset_type: MockAssetType::MockAsset(1), - units_per_second: 200, - }, crate::Event::ForeignAssetRemoved { asset_id: 1, asset_type: MockAssetType::MockAsset(1), @@ -319,9 +217,6 @@ fn test_removing_without_asset_units_per_second_does_not_panic() { assert!(AssetManager::asset_type_id(MockAssetType::MockAsset(1)).is_none()); assert!(AssetManager::asset_id_type(1).is_none()); - // Units per second removed - assert!(AssetManager::asset_type_units_per_second(MockAssetType::MockAsset(1)).is_none()); - expect_events(vec![ crate::Event::ForeignAssetRegistered { asset_id: 1, @@ -357,9 +252,6 @@ fn test_destroy_foreign_asset_also_removes_everything() { assert!(AssetManager::asset_type_id(MockAssetType::MockAsset(1)).is_none()); assert!(AssetManager::asset_id_type(1).is_none()); - // Units per second removed - assert!(AssetManager::asset_type_units_per_second(MockAssetType::MockAsset(1)).is_none()); - expect_events(vec![ crate::Event::ForeignAssetRegistered { asset_id: 1, diff --git a/pallets/xcm-weight-trader/src/tests.rs b/pallets/xcm-weight-trader/src/tests.rs index 5a32ea3730..71d3d5e35f 100644 --- a/pallets/xcm-weight-trader/src/tests.rs +++ b/pallets/xcm-weight-trader/src/tests.rs @@ -62,7 +62,7 @@ fn test_add_supported_asset() { Location::parent(), 0, ), - Error::::UnitsCannotBeZero + Error::::PriceCannotBeZero ); // Call with the right origin @@ -137,7 +137,7 @@ fn test_edit_supported_asset() { Location::parent(), 0, ), - Error::::UnitsCannotBeZero + Error::::PriceCannotBeZero ); // Call with right origin and valid params diff --git a/runtime/common/src/apis.rs b/runtime/common/src/apis.rs index 7db0247b36..c67d9f6702 100644 --- a/runtime/common/src/apis.rs +++ b/runtime/common/src/apis.rs @@ -952,13 +952,13 @@ macro_rules! impl_runtime_apis_plus_common { location.clone().try_into().expect("convert to v3"), i as u128 ); - // set 1-1 - ::ForeignAssetType> >::set_units_per_second( location.clone().try_into().expect("convert to v3"), 1_000_000_000_000u128 - ); + );*/ } } assets.into() diff --git a/runtime/moonbase/Cargo.toml b/runtime/moonbase/Cargo.toml index 98b96bd9fc..0e45799a6a 100644 --- a/runtime/moonbase/Cargo.toml +++ b/runtime/moonbase/Cargo.toml @@ -381,6 +381,7 @@ runtime-benchmarks = [ "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm-transactor/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", + "pallet-xcm-weight-trader/runtime-benchmarks", "session-keys-primitives/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", diff --git a/runtime/moonbase/src/xcm_config.rs b/runtime/moonbase/src/xcm_config.rs index e5468efe66..8c53f4cb67 100644 --- a/runtime/moonbase/src/xcm_config.rs +++ b/runtime/moonbase/src/xcm_config.rs @@ -777,7 +777,7 @@ impl pallet_xcm_weight_trader::Config for Runtime { type WeightToFee = ::WeightToFee; type XcmFeesAccount = XcmFeesAccount; #[cfg(feature = "runtime-benchmarks")] - type NotFilteredLocation = Location::parent(); + type NotFilteredLocation = RelayLocation; } #[cfg(feature = "runtime-benchmarks")] diff --git a/runtime/moonbase/tests/xcm_mock/parachain.rs b/runtime/moonbase/tests/xcm_mock/parachain.rs index da216325dd..ccc354b543 100644 --- a/runtime/moonbase/tests/xcm_mock/parachain.rs +++ b/runtime/moonbase/tests/xcm_mock/parachain.rs @@ -809,6 +809,10 @@ impl pallet_xcm_transactor::Config for Runtime { type MaxHrmpFee = xcm_builder::Case; } +parameter_types! { + pub RelayLocation: Location = Location::parent(); +} + impl pallet_xcm_weight_trader::Config for Runtime { type AccountIdToLocation = xcm_primitives::AccountIdToLocation; type AddSupportedAssetOrigin = EnsureRoot; @@ -825,7 +829,7 @@ impl pallet_xcm_weight_trader::Config for Runtime { type WeightToFee = WeightToFee; type XcmFeesAccount = XcmFeesAccount; #[cfg(feature = "runtime-benchmarks")] - type NotFilteredLocation = Location::parent(); + type NotFilteredLocation = RelayLocation; } parameter_types! { diff --git a/runtime/moonbeam/Cargo.toml b/runtime/moonbeam/Cargo.toml index fc046edbf2..8a1be991c3 100644 --- a/runtime/moonbeam/Cargo.toml +++ b/runtime/moonbeam/Cargo.toml @@ -366,6 +366,7 @@ runtime-benchmarks = [ "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm-transactor/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", + "pallet-xcm-weight-trader/runtime-benchmarks", "session-keys-primitives/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", diff --git a/runtime/moonbeam/src/xcm_config.rs b/runtime/moonbeam/src/xcm_config.rs index 25c4ffbbcf..627b0afbe0 100644 --- a/runtime/moonbeam/src/xcm_config.rs +++ b/runtime/moonbeam/src/xcm_config.rs @@ -728,7 +728,7 @@ impl pallet_xcm_weight_trader::Config for Runtime { type WeightToFee = ::WeightToFee; type XcmFeesAccount = XcmFeesAccount; #[cfg(feature = "runtime-benchmarks")] - type NotFilteredLocation = Location::parent(); + type NotFilteredLocation = RelayLocation; } #[cfg(feature = "runtime-benchmarks")] diff --git a/runtime/moonbeam/tests/xcm_mock/parachain.rs b/runtime/moonbeam/tests/xcm_mock/parachain.rs index 5b394c26bb..8316dfbcad 100644 --- a/runtime/moonbeam/tests/xcm_mock/parachain.rs +++ b/runtime/moonbeam/tests/xcm_mock/parachain.rs @@ -795,6 +795,10 @@ impl pallet_xcm_transactor::Config for Runtime { type MaxHrmpFee = xcm_builder::Case; } +parameter_types! { + pub RelayLocation: Location = Location::parent(); +} + impl pallet_xcm_weight_trader::Config for Runtime { type AccountIdToLocation = xcm_primitives::AccountIdToLocation; type AddSupportedAssetOrigin = EnsureRoot; @@ -811,7 +815,7 @@ impl pallet_xcm_weight_trader::Config for Runtime { type WeightToFee = WeightToFee; type XcmFeesAccount = XcmFeesAccount; #[cfg(feature = "runtime-benchmarks")] - type NotFilteredLocation = Location::parent(); + type NotFilteredLocation = RelayLocation; } parameter_types! { diff --git a/runtime/moonriver/Cargo.toml b/runtime/moonriver/Cargo.toml index 6075c2a7e0..bfc2a1b685 100644 --- a/runtime/moonriver/Cargo.toml +++ b/runtime/moonriver/Cargo.toml @@ -371,6 +371,7 @@ runtime-benchmarks = [ "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm-transactor/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", + "pallet-xcm-weight-trader/runtime-benchmarks", "session-keys-primitives/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", diff --git a/runtime/moonriver/src/xcm_config.rs b/runtime/moonriver/src/xcm_config.rs index 05b79565ac..94c4bc97ea 100644 --- a/runtime/moonriver/src/xcm_config.rs +++ b/runtime/moonriver/src/xcm_config.rs @@ -741,7 +741,7 @@ impl pallet_xcm_weight_trader::Config for Runtime { type WeightToFee = ::WeightToFee; type XcmFeesAccount = XcmFeesAccount; #[cfg(feature = "runtime-benchmarks")] - type NotFilteredLocation = Location::parent(); + type NotFilteredLocation = RelayLocation; } #[cfg(feature = "runtime-benchmarks")] diff --git a/runtime/moonriver/tests/xcm_mock/parachain.rs b/runtime/moonriver/tests/xcm_mock/parachain.rs index a0cfaef334..991ed7ad42 100644 --- a/runtime/moonriver/tests/xcm_mock/parachain.rs +++ b/runtime/moonriver/tests/xcm_mock/parachain.rs @@ -800,6 +800,10 @@ impl pallet_xcm_transactor::Config for Runtime { type MaxHrmpFee = xcm_builder::Case; } +parameter_types! { + pub RelayLocation: Location = Location::parent(); +} + impl pallet_xcm_weight_trader::Config for Runtime { type AccountIdToLocation = xcm_primitives::AccountIdToLocation; type AddSupportedAssetOrigin = EnsureRoot; @@ -816,7 +820,7 @@ impl pallet_xcm_weight_trader::Config for Runtime { type WeightToFee = WeightToFee; type XcmFeesAccount = XcmFeesAccount; #[cfg(feature = "runtime-benchmarks")] - type NotFilteredLocation = Location::parent(); + type NotFilteredLocation = RelayLocation; } parameter_types! { From 9a399e35a6883653f2f515accc6f047e24fac736 Mon Sep 17 00:00:00 2001 From: Rodrigo Quelhas Date: Mon, 26 Aug 2024 13:06:03 +0100 Subject: [PATCH 10/27] fix rust tests --- pallets/xcm-weight-trader/src/lib.rs | 11 ++-- runtime/moonbase/tests/xcm_tests.rs | 68 +++++++++++--------- runtime/moonbeam/tests/xcm_mock/parachain.rs | 4 +- runtime/moonbeam/tests/xcm_tests.rs | 10 ++- runtime/moonriver/tests/xcm_tests.rs | 5 +- 5 files changed, 58 insertions(+), 40 deletions(-) diff --git a/pallets/xcm-weight-trader/src/lib.rs b/pallets/xcm-weight-trader/src/lib.rs index e35733b0c0..0fd0e3c335 100644 --- a/pallets/xcm-weight-trader/src/lib.rs +++ b/pallets/xcm-weight-trader/src/lib.rs @@ -43,7 +43,7 @@ use xcm::{IntoVersion, VersionedAssetId}; use xcm_executor::traits::{TransactAsset, WeightTrader}; use xcm_fee_payment_runtime_api::Error as XcmPaymentApiError; -const RELATIVE_PRICE_DECIMALS: u32 = 9; +pub const RELATIVE_PRICE_DECIMALS: u32 = 18; #[pallet] pub mod pallet { @@ -105,7 +105,7 @@ pub mod pallet { } /// Stores all supported assets per XCM Location. - /// The u128 is the asset price relative to native asset with 9 decimals + /// The u128 is the asset price relative to native asset with 18 decimals /// The boolean specify if the support for this asset is active #[pallet::storage] #[pallet::getter(fn supported_assets)] @@ -371,7 +371,7 @@ impl WeightTrader for Trader { (XcmAssetId(location), Fungibility::Fungible(_)) => { let amount: u128 = Self::compute_amount_to_charge(&weight, &location)?; - // We dont need to proceed if the amount is 0 + // We don't need to proceed if the amount is 0 // For cases (specially tests) where the asset is very cheap with respect // to the weight needed if amount.is_zero() { @@ -389,9 +389,9 @@ impl WeightTrader for Trader { self.0 = weight; self.1 = Some(required); - return Ok(unused); + Ok(unused) } - _ => return Err(XcmError::AssetNotFound), + _ => Err(XcmError::AssetNotFound), } } @@ -440,6 +440,7 @@ impl WeightTrader for Trader { impl Drop for Trader { fn drop(&mut self) { + log::trace!(target: "xcm-weight-trader", "Dropping `Trader` instance: (weight: {:?}, asset: {:?})", &self.0, &self.1); if let Some(asset) = self.1.take() { let res = T::AssetTransactor::deposit_asset( &asset, diff --git a/runtime/moonbase/tests/xcm_tests.rs b/runtime/moonbase/tests/xcm_tests.rs index dced70b2fd..3df0e1595f 100644 --- a/runtime/moonbase/tests/xcm_tests.rs +++ b/runtime/moonbase/tests/xcm_tests.rs @@ -60,8 +60,11 @@ fn add_supported_asset(asset_type: parachain::AssetType, units_per_second: u128) ) .try_into() .map_err(|_| ())?; + let precision_factor = 10u128.pow(pallet_xcm_weight_trader::RELATIVE_PRICE_DECIMALS); let relative_price: u128 = if units_per_second > 0u128 { - native_amount_per_second / units_per_second + native_amount_per_second + .saturating_mul(precision_factor) + .saturating_div(units_per_second) } else { 0u128 }; @@ -93,7 +96,7 @@ fn receive_relay_asset_from_relay() { 1u128, true )); - assert_ok!(add_supported_asset(source_location.clone(), 0u128,)); + assert_ok!(add_supported_asset(source_location.clone(), 0)); }); // Actually send relay asset to parachain @@ -144,7 +147,7 @@ fn send_relay_asset_to_relay() { true )); // Free execution - assert_ok!(add_supported_asset(source_location, 0u128,)); + assert_ok!(add_supported_asset(source_location, 0)); }); let dest: Location = Junction::AccountKey20 { @@ -231,7 +234,7 @@ fn send_relay_asset_to_para_b() { 1u128, true )); - assert_ok!(add_supported_asset(source_location.clone(), 0u128,)); + assert_ok!(add_supported_asset(source_location.clone(), 0)); }); // Register asset in paraB. Free execution @@ -243,7 +246,7 @@ fn send_relay_asset_to_para_b() { 1u128, true )); - assert_ok!(add_supported_asset(source_location, 0u128,)); + assert_ok!(add_supported_asset(source_location, 0)); }); // First send relay chain asset to Parachain A like in previous test @@ -328,7 +331,7 @@ fn send_para_a_asset_to_para_b() { 1u128, true )); - assert_ok!(add_supported_asset(source_location, 0u128,)); + assert_ok!(add_supported_asset(source_location, 0)); }); // Send para A asset from para A to para B @@ -395,7 +398,7 @@ fn send_para_a_asset_from_para_b_to_para_c() { 1u128, true )); - assert_ok!(add_supported_asset(source_location.clone(), 0u128,)); + assert_ok!(add_supported_asset(source_location.clone(), 0)); }); // Register para A asset in parachain C. Free execution @@ -407,7 +410,7 @@ fn send_para_a_asset_from_para_b_to_para_c() { 1u128, true )); - assert_ok!(add_supported_asset(source_location, 0u128,)); + assert_ok!(add_supported_asset(source_location, 0)); }); // Send para A asset to para B @@ -501,7 +504,7 @@ fn send_para_a_asset_to_para_b_and_back_to_para_a() { 1u128, true )); - assert_ok!(add_supported_asset(source_location, 0u128,)); + assert_ok!(add_supported_asset(source_location, 0)); }); // Send para A asset to para B @@ -594,7 +597,7 @@ fn send_para_a_asset_to_para_b_and_back_to_para_a_with_new_reanchoring() { 1u128, true )); - assert_ok!(add_supported_asset(source_location, 0u128,)); + assert_ok!(add_supported_asset(source_location, 0)); }); let dest = Location { @@ -702,7 +705,7 @@ fn receive_relay_asset_with_trader() { 1u128, true )); - assert_ok!(add_supported_asset(source_location, 2500000000000u128,)); + assert_ok!(add_supported_asset(source_location, 2_500_000_000_000)); }); let dest: Location = Junction::AccountKey20 { @@ -759,7 +762,7 @@ fn send_para_a_asset_to_para_b_with_trader() { 1u128, true )); - assert_ok!(add_supported_asset(source_location, 2500000000000u128,)); + assert_ok!(add_supported_asset(source_location, 2500000000000)); }); let dest = Location { @@ -832,7 +835,7 @@ fn send_para_a_asset_to_para_b_with_trader_and_fee() { true )); // With these units per second, 80K weight convrets to 1 asset unit - assert_ok!(add_supported_asset(source_location, 12500000u128,)); + assert_ok!(add_supported_asset(source_location, 12500000)); }); let dest = Location { @@ -867,7 +870,7 @@ fn send_para_a_asset_to_para_b_with_trader_and_fee() { }); ParaB::execute_with(|| { - // free execution, full amount received because trully the xcm instruction does not cost + // free execution, full amount received because the xcm instruction does not cost // what it is specified assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 101); }); @@ -902,7 +905,12 @@ fn error_when_not_paying_enough() { 1u128, true )); - assert_ok!(add_supported_asset(source_location, 2500000000000u128,)); + assert_ok!(add_supported_asset(source_location, 2500000000000)); + }); + + ParaA::execute_with(|| { + // amount not received as it is not paying enough + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 0); }); // We are sending 100 tokens from relay. @@ -946,7 +954,7 @@ fn transact_through_derivative_multilocation() { 1u128, true )); - assert_ok!(add_supported_asset(source_location, 1u128,)); + assert_ok!(add_supported_asset(source_location, 1)); // Root can set transact info assert_ok!(XcmTransactor::set_transact_info( @@ -1111,7 +1119,7 @@ fn transact_through_derivative_with_custom_fee_weight() { 1u128, true )); - assert_ok!(add_supported_asset(source_location, 1u128,)); + assert_ok!(add_supported_asset(source_location, 1)); }); // Let's construct the call to know how much weight it is going to require @@ -1262,7 +1270,7 @@ fn transact_through_derivative_with_custom_fee_weight_refund() { 1u128, true )); - assert_ok!(add_supported_asset(source_location, 1u128,)); + assert_ok!(add_supported_asset(source_location, 1)); }); // Let's construct the call to know how much weight it is going to require @@ -1412,7 +1420,7 @@ fn transact_through_sovereign() { 1u128, true )); - assert_ok!(add_supported_asset(source_location, 1u128,)); + assert_ok!(add_supported_asset(source_location, 1)); // Root can set transact info assert_ok!(XcmTransactor::set_transact_info( @@ -1680,7 +1688,7 @@ fn transact_through_sovereign_with_custom_fee_weight() { 1u128, true )); - assert_ok!(add_supported_asset(source_location, 1u128,)); + assert_ok!(add_supported_asset(source_location, 1)); }); let dest: Location = AccountKey20 { @@ -1829,7 +1837,7 @@ fn transact_through_sovereign_with_custom_fee_weight_refund() { 1u128, true )); - assert_ok!(add_supported_asset(source_location, 1u128,)); + assert_ok!(add_supported_asset(source_location, 1)); }); let dest: Location = AccountKey20 { @@ -1978,7 +1986,7 @@ fn test_automatic_versioning_on_runtime_upgrade_with_relay() { 1u128, true )); - assert_ok!(add_supported_asset(source_location, 0u128,)); + assert_ok!(add_supported_asset(source_location, 0)); }); let response = Response::Version(2); @@ -2127,7 +2135,7 @@ fn test_automatic_versioning_on_runtime_upgrade_with_para_b() { 1u128, true )); - assert_ok!(add_supported_asset(source_location, 0u128,)); + assert_ok!(add_supported_asset(source_location, 0)); }); ParaA::execute_with(|| { @@ -2255,7 +2263,7 @@ fn receive_asset_with_no_sufficients_not_possible_if_non_existent_account() { 1u128, false )); - assert_ok!(add_supported_asset(source_location, 0u128,)); + assert_ok!(add_supported_asset(source_location, 0)); }); // Actually send relay asset to parachain @@ -2330,7 +2338,7 @@ fn receive_assets_with_sufficients_true_allows_non_funded_account_to_receive_ass 1u128, true )); - assert_ok!(add_supported_asset(source_location, 0u128,)); + assert_ok!(add_supported_asset(source_location, 0)); }); // Actually send relay asset to parachain @@ -2386,7 +2394,7 @@ fn evm_account_receiving_assets_should_handle_sufficients_ref_count() { 1u128, true )); - assert_ok!(add_supported_asset(source_location, 0u128,)); + assert_ok!(add_supported_asset(source_location, 0)); }); // Actually send relay asset to parachain @@ -2451,7 +2459,7 @@ fn empty_account_should_not_be_reset() { 1u128, false )); - assert_ok!(add_supported_asset(source_location, 0u128,)); + assert_ok!(add_supported_asset(source_location, 0)); }); // Send native token to evm_account @@ -2557,7 +2565,7 @@ fn test_statemint_like() { 1u128, true )); - assert_ok!(add_supported_asset(source_location, 0u128,)); + assert_ok!(add_supported_asset(source_location, 0)); }); Statemint::execute_with(|| { @@ -2666,7 +2674,7 @@ fn send_statemint_asset_from_para_a_to_statemint_with_relay_fee() { 1u128, true )); - assert_ok!(add_supported_asset(relay_location, 0u128,)); + assert_ok!(add_supported_asset(relay_location, 0)); assert_ok!(AssetManager::register_foreign_asset( parachain::RuntimeOrigin::root(), @@ -2675,7 +2683,7 @@ fn send_statemint_asset_from_para_a_to_statemint_with_relay_fee() { 1u128, true )); - assert_ok!(add_supported_asset(statemint_location_asset, 0u128,)); + assert_ok!(add_supported_asset(statemint_location_asset, 0)); }); let parachain_beneficiary_from_relay: Location = Junction::AccountKey20 { diff --git a/runtime/moonbeam/tests/xcm_mock/parachain.rs b/runtime/moonbeam/tests/xcm_mock/parachain.rs index 8316dfbcad..a01560327a 100644 --- a/runtime/moonbeam/tests/xcm_mock/parachain.rs +++ b/runtime/moonbeam/tests/xcm_mock/parachain.rs @@ -283,7 +283,7 @@ parameter_types! { /// Xcm fees will go to the treasury account pub XcmFeesAccount: AccountId = Treasury::account_id(); /// Parachain token units per second of execution - pub ParaTokensPerSecond: u128 = 1000000000000; + pub ParaTokensPerSecond: u128 = WEIGHT_REF_TIME_PER_SECOND as u128; } pub struct WeightToFee; @@ -1088,6 +1088,8 @@ pub(crate) fn para_events() -> Vec { use frame_support::traits::tokens::{PayFromAccount, UnityAssetBalanceConversion}; use frame_support::traits::{OnFinalize, OnInitialize, UncheckedOnRuntimeUpgrade}; +use sp_weights::constants::WEIGHT_REF_TIME_PER_SECOND; + pub(crate) fn on_runtime_upgrade() { VersionUncheckedMigrateToV1::::on_runtime_upgrade(); } diff --git a/runtime/moonbeam/tests/xcm_tests.rs b/runtime/moonbeam/tests/xcm_tests.rs index fb37466bb6..37530ce646 100644 --- a/runtime/moonbeam/tests/xcm_tests.rs +++ b/runtime/moonbeam/tests/xcm_tests.rs @@ -60,8 +60,11 @@ fn add_supported_asset(asset_type: parachain::AssetType, units_per_second: u128) ) .try_into() .map_err(|_| ())?; + let precision_factor = 10u128.pow(pallet_xcm_weight_trader::RELATIVE_PRICE_DECIMALS); let relative_price: u128 = if units_per_second > 0u128 { - native_amount_per_second / units_per_second + native_amount_per_second + .saturating_mul(precision_factor) + .saturating_div(units_per_second) } else { 0u128 }; @@ -2364,6 +2367,7 @@ fn test_statemint_like() { } #[test] + fn send_statemint_asset_from_para_a_to_statemint_with_relay_fee() { MockNet::reset(); @@ -2409,7 +2413,7 @@ fn send_statemint_asset_from_para_a_to_statemint_with_relay_fee() { 1u128, true )); - assert_ok!(add_supported_asset(relay_location.clone(), 0u128)); + assert_ok!(add_supported_asset(relay_location, 0u128)); assert_ok!(AssetManager::register_foreign_asset( parachain::RuntimeOrigin::root(), @@ -2418,7 +2422,7 @@ fn send_statemint_asset_from_para_a_to_statemint_with_relay_fee() { 1u128, true )); - assert_ok!(add_supported_asset(relay_location.clone(), 0u128)); + assert_ok!(add_supported_asset(statemint_location_asset, 0u128)); }); let parachain_beneficiary_from_relay: Location = Junction::AccountKey20 { diff --git a/runtime/moonriver/tests/xcm_tests.rs b/runtime/moonriver/tests/xcm_tests.rs index e04ddde4c9..485c44ce16 100644 --- a/runtime/moonriver/tests/xcm_tests.rs +++ b/runtime/moonriver/tests/xcm_tests.rs @@ -61,8 +61,11 @@ fn add_supported_asset(asset_type: parachain::AssetType, units_per_second: u128) ) .try_into() .map_err(|_| ())?; + let precision_factor = 10u128.pow(pallet_xcm_weight_trader::RELATIVE_PRICE_DECIMALS); let relative_price: u128 = if units_per_second > 0u128 { - native_amount_per_second / units_per_second + native_amount_per_second + .saturating_mul(precision_factor) + .saturating_div(units_per_second) } else { 0u128 }; From 167802148de56984a721d7c8cb14543458a05bf8 Mon Sep 17 00:00:00 2001 From: Rodrigo Quelhas Date: Mon, 26 Aug 2024 13:29:17 +0100 Subject: [PATCH 11/27] add weight info for pallet_xcm_weight_trader --- runtime/common/src/weights/mod.rs | 1 + .../src/weights/pallet_xcm_weight_trader.rs | 104 ++++++++++++++++++ runtime/moonbase/src/lib.rs | 1 + runtime/moonbase/src/xcm_config.rs | 4 +- runtime/moonbeam/src/xcm_config.rs | 4 +- runtime/moonriver/src/xcm_config.rs | 4 +- 6 files changed, 109 insertions(+), 9 deletions(-) create mode 100644 runtime/common/src/weights/pallet_xcm_weight_trader.rs diff --git a/runtime/common/src/weights/mod.rs b/runtime/common/src/weights/mod.rs index 6108d9c228..0b6ba9dcdf 100644 --- a/runtime/common/src/weights/mod.rs +++ b/runtime/common/src/weights/mod.rs @@ -50,3 +50,4 @@ pub mod pallet_utility; pub mod pallet_whitelist; pub mod pallet_xcm; pub mod pallet_xcm_transactor; +pub mod pallet_xcm_weight_trader; diff --git a/runtime/common/src/weights/pallet_xcm_weight_trader.rs b/runtime/common/src/weights/pallet_xcm_weight_trader.rs new file mode 100644 index 0000000000..6680f603b0 --- /dev/null +++ b/runtime/common/src/weights/pallet_xcm_weight_trader.rs @@ -0,0 +1,104 @@ +// Copyright 2024 Moonbeam foundation +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Autogenerated weights for `pallet_xcm_weight_trader` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-08-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `MacBook-Pro-de-romarq.local`, CPU: `` +//! WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_xcm_weight_trader +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --template=./benchmarking/frame-weight-template.hbs +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for `pallet_xcm_weight_trader`. +pub struct WeightInfo(PhantomData); +impl pallet_xcm_weight_trader::WeightInfo for WeightInfo { + /// Storage: `XcmWeightTrader::SupportedAssets` (r:1 w:1) + /// Proof: `XcmWeightTrader::SupportedAssets` (`max_values`: None, `max_size`: Some(635), added: 3110, mode: `MaxEncodedLen`) + fn add_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `42` + // Estimated: `4100` + // Minimum execution time: 6_000_000 picoseconds. + Weight::from_parts(7_000_000, 4100) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `XcmWeightTrader::SupportedAssets` (r:1 w:1) + /// Proof: `XcmWeightTrader::SupportedAssets` (`max_values`: None, `max_size`: Some(635), added: 3110, mode: `MaxEncodedLen`) + fn edit_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `102` + // Estimated: `4100` + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(8_000_000, 4100) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `XcmWeightTrader::SupportedAssets` (r:1 w:1) + /// Proof: `XcmWeightTrader::SupportedAssets` (`max_values`: None, `max_size`: Some(635), added: 3110, mode: `MaxEncodedLen`) + fn resume_asset_support() -> Weight { + // Proof Size summary in bytes: + // Measured: `102` + // Estimated: `4100` + // Minimum execution time: 8_000_000 picoseconds. + Weight::from_parts(8_000_000, 4100) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `XcmWeightTrader::SupportedAssets` (r:1 w:1) + /// Proof: `XcmWeightTrader::SupportedAssets` (`max_values`: None, `max_size`: Some(635), added: 3110, mode: `MaxEncodedLen`) + fn pause_asset_support() -> Weight { + // Proof Size summary in bytes: + // Measured: `102` + // Estimated: `4100` + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(8_000_000, 4100) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `XcmWeightTrader::SupportedAssets` (r:1 w:1) + /// Proof: `XcmWeightTrader::SupportedAssets` (`max_values`: None, `max_size`: Some(635), added: 3110, mode: `MaxEncodedLen`) + fn remove_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `102` + // Estimated: `4100` + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(8_000_000, 4100) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } +} diff --git a/runtime/moonbase/src/lib.rs b/runtime/moonbase/src/lib.rs index d9c79486ee..30976f99f5 100644 --- a/runtime/moonbase/src/lib.rs +++ b/runtime/moonbase/src/lib.rs @@ -1514,6 +1514,7 @@ mod benches { [pallet_relay_storage_roots, RelayStorageRoots] [pallet_precompile_benchmarks, PrecompileBenchmarks] [pallet_moonbeam_lazy_migrations, MoonbeamLazyMigrations] + [pallet_xcm_weight_trader, XcmWeightTrader] ); } diff --git a/runtime/moonbase/src/xcm_config.rs b/runtime/moonbase/src/xcm_config.rs index 8c53f4cb67..28cf68f535 100644 --- a/runtime/moonbase/src/xcm_config.rs +++ b/runtime/moonbase/src/xcm_config.rs @@ -354,7 +354,6 @@ impl pallet_xcm::Config for Runtime { type MaxLockers = ConstU32<8>; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); - // TODO pallet-xcm weights type WeightInfo = moonbase_weights::pallet_xcm::WeightInfo; type AdminOrigin = EnsureRoot; } @@ -772,8 +771,7 @@ impl pallet_xcm_weight_trader::Config for Runtime { type RemoveSupportedAssetOrigin = EnsureRoot; type RuntimeEvent = RuntimeEvent; type ResumeSupportedAssetOrigin = EnsureRoot; - // TODO generate weights - type WeightInfo = (); + type WeightInfo = moonbase_weights::pallet_xcm_weight_trader::WeightInfo; type WeightToFee = ::WeightToFee; type XcmFeesAccount = XcmFeesAccount; #[cfg(feature = "runtime-benchmarks")] diff --git a/runtime/moonbeam/src/xcm_config.rs b/runtime/moonbeam/src/xcm_config.rs index 627b0afbe0..48c3a4f577 100644 --- a/runtime/moonbeam/src/xcm_config.rs +++ b/runtime/moonbeam/src/xcm_config.rs @@ -342,7 +342,6 @@ impl pallet_xcm::Config for Runtime { type MaxLockers = ConstU32<8>; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); - // TODO pallet-xcm weights type WeightInfo = moonbeam_weights::pallet_xcm::WeightInfo; type AdminOrigin = EnsureRoot; } @@ -723,8 +722,7 @@ impl pallet_xcm_weight_trader::Config for Runtime { type RemoveSupportedAssetOrigin = EnsureRoot; type RuntimeEvent = RuntimeEvent; type ResumeSupportedAssetOrigin = EnsureRoot; - // TODO generate weights - type WeightInfo = (); + type WeightInfo = moonbeam_weights::pallet_xcm_weight_trader::WeightInfo; type WeightToFee = ::WeightToFee; type XcmFeesAccount = XcmFeesAccount; #[cfg(feature = "runtime-benchmarks")] diff --git a/runtime/moonriver/src/xcm_config.rs b/runtime/moonriver/src/xcm_config.rs index 94c4bc97ea..8ed6587496 100644 --- a/runtime/moonriver/src/xcm_config.rs +++ b/runtime/moonriver/src/xcm_config.rs @@ -350,7 +350,6 @@ impl pallet_xcm::Config for Runtime { type MaxLockers = ConstU32<8>; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); - // TODO pallet-xcm weights type WeightInfo = moonriver_weights::pallet_xcm::WeightInfo; type AdminOrigin = EnsureRoot; } @@ -736,8 +735,7 @@ impl pallet_xcm_weight_trader::Config for Runtime { type RemoveSupportedAssetOrigin = EnsureRoot; type RuntimeEvent = RuntimeEvent; type ResumeSupportedAssetOrigin = EnsureRoot; - // TODO generate weights - type WeightInfo = (); + type WeightInfo = moonriver_weights::pallet_xcm_weight_trader::WeightInfo; type WeightToFee = ::WeightToFee; type XcmFeesAccount = XcmFeesAccount; #[cfg(feature = "runtime-benchmarks")] From a1e7004c31980aff3c31956b7a684f217659fe52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Mon, 26 Aug 2024 14:51:05 +0200 Subject: [PATCH 12/27] fix migration formula --- runtime/common/src/migrations.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/runtime/common/src/migrations.rs b/runtime/common/src/migrations.rs index 1b2e277076..4f1ba2e29b 100644 --- a/runtime/common/src/migrations.rs +++ b/runtime/common/src/migrations.rs @@ -108,7 +108,9 @@ where ) .try_into() .unwrap_or(u128::MAX); - let relative_price: u128 = native_amount_per_second / units_per_second; + let relative_price: u128 = native_amount_per_second + .saturating_mul(10u128.pow(pallet_xcm_weight_trader::RELATIVE_PRICE_DECIMALS)) + .saturating_div(units_per_second); pallet_xcm_weight_trader::SupportedAssets::::insert( asset_location, (enabled, relative_price), From fd30cb7d38493a8bb2cfd2aea42de91b67d18a0c Mon Sep 17 00:00:00 2001 From: Rodrigo Quelhas Date: Mon, 26 Aug 2024 15:14:36 +0100 Subject: [PATCH 13/27] fix pallet tests --- pallets/xcm-weight-trader/src/tests.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pallets/xcm-weight-trader/src/tests.rs b/pallets/xcm-weight-trader/src/tests.rs index 71d3d5e35f..b24e63519c 100644 --- a/pallets/xcm-weight-trader/src/tests.rs +++ b/pallets/xcm-weight-trader/src/tests.rs @@ -489,14 +489,14 @@ fn test_trader_parent_asset() { trader.buy_weight( weight_to_buy, Asset { - fun: Fungibility::Fungible(22_000), + fun: Fungibility::Fungible(22_000_000_000_000), id: XcmAssetId(Location::parent()), } .into(), &dummy_xcm_context ), Ok(Asset { - fun: Fungibility::Fungible(2_000), + fun: Fungibility::Fungible(2_000_000_000_000), id: XcmAssetId(Location::parent()), } .into()) @@ -507,7 +507,7 @@ fn test_trader_parent_asset() { assert_eq!( trader.refund_weight(actual_weight, &dummy_xcm_context), Some(Asset { - fun: Fungibility::Fungible(4_000), + fun: Fungibility::Fungible(4_000_000_000_000), id: XcmAssetId(Location::parent()), }) ); @@ -516,7 +516,7 @@ fn test_trader_parent_asset() { drop(trader); assert_eq!( get_parent_asset_deposited(), - Some((xcm_fees_account(), 20_000 - 4_000)) + Some((xcm_fees_account(), 20_000_000_000_000 - 4_000_000_000_000)) ); // Should not be able to buy weight if the asset is not a first position @@ -642,7 +642,7 @@ fn test_query_weight_to_asset_fee() { // Parent asset price should be 0.5 assert_eq!( XcmWeightTrader::query_weight_to_asset_fee(weight_to_buy, parent_asset.clone()), - Ok(2 * 10_000) + Ok(2 * 10_000_000_000_000) ); // Setup: pause parent asset @@ -679,7 +679,7 @@ fn test_query_weight_to_asset_fee() { // We should support unpaused asset with new price assert_eq!( XcmWeightTrader::query_weight_to_asset_fee(weight_to_buy, parent_asset), - Ok(10_000 / 2) + Ok(10_000_000_000_000 / 2) ); }) } From af305a0b175df6a6a8e9734bbb80d81a3def52f7 Mon Sep 17 00:00:00 2001 From: Rodrigo Quelhas Date: Mon, 26 Aug 2024 15:17:08 +0100 Subject: [PATCH 14/27] fix linting --- pallets/xcm-weight-trader/src/lib.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/pallets/xcm-weight-trader/src/lib.rs b/pallets/xcm-weight-trader/src/lib.rs index 0fd0e3c335..7a7bffa41b 100644 --- a/pallets/xcm-weight-trader/src/lib.rs +++ b/pallets/xcm-weight-trader/src/lib.rs @@ -350,7 +350,13 @@ impl WeightTrader for Trader { payment: xcm_executor::AssetsInHolding, context: &XcmContext, ) -> Result { - log::trace!(target: "xcm::weight", "UsingComponents::buy_weight weight: {:?}, payment: {:?}, context: {:?}", weight, payment, context); + log::trace!( + target: "xcm::weight", + "UsingComponents::buy_weight weight: {:?}, payment: {:?}, context: {:?}", + weight, + payment, + context + ); // Can only call one time if self.1.is_some() { @@ -426,7 +432,11 @@ impl WeightTrader for Trader { fun: Fungibility::Fungible(final_amount), id: XcmAssetId(location.clone()), }); - log::trace!(target: "xcm-weight-trader", "refund_weight amount to refund: {:?}", amount_to_refound); + log::trace!( + target: "xcm-weight-trader", + "refund_weight amount to refund: {:?}", + amount_to_refound + ); Some(Asset { fun: Fungibility::Fungible(amount_to_refound), id: XcmAssetId(location), @@ -440,7 +450,12 @@ impl WeightTrader for Trader { impl Drop for Trader { fn drop(&mut self) { - log::trace!(target: "xcm-weight-trader", "Dropping `Trader` instance: (weight: {:?}, asset: {:?})", &self.0, &self.1); + log::trace!( + target: "xcm-weight-trader", + "Dropping `Trader` instance: (weight: {:?}, asset: {:?})", + &self.0, + &self.1 + ); if let Some(asset) = self.1.take() { let res = T::AssetTransactor::deposit_asset( &asset, From 01c317d36f4eab6333f213d6fac1bb352d11570f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Wed, 28 Aug 2024 15:20:02 +0200 Subject: [PATCH 15/27] fix typo --- runtime/common/src/migrations.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/common/src/migrations.rs b/runtime/common/src/migrations.rs index 4f1ba2e29b..383b403be7 100644 --- a/runtime/common/src/migrations.rs +++ b/runtime/common/src/migrations.rs @@ -55,7 +55,7 @@ where Runtime: pallet_xcm_weight_trader::Config, { fn friendly_name(&self) -> &str { - "MM_MigrateXcmFeesAssetsMeatdata" + "MM_MigrateXcmFeesAssetsMetadata" } fn migrate(&self, _available_weight: Weight) -> Weight { From 87dd27756337a6b7673731dbe075855b8643c5a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Wed, 28 Aug 2024 15:20:15 +0200 Subject: [PATCH 16/27] configure origins for xcmWeightTrader --- runtime/moonbeam/src/xcm_config.rs | 36 +++++++++++++++++++++++------ runtime/moonriver/src/xcm_config.rs | 36 +++++++++++++++++++++++------ 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/runtime/moonbeam/src/xcm_config.rs b/runtime/moonbeam/src/xcm_config.rs index 48c3a4f577..57b7aba0d6 100644 --- a/runtime/moonbeam/src/xcm_config.rs +++ b/runtime/moonbeam/src/xcm_config.rs @@ -19,8 +19,9 @@ use super::{ governance, AccountId, AssetId, AssetManager, Balance, Balances, Erc20XcmBridge, - MaintenanceMode, MessageQueue, ParachainInfo, ParachainSystem, Perbill, PolkadotXcm, Runtime, - RuntimeBlockWeights, RuntimeCall, RuntimeEvent, RuntimeOrigin, Treasury, XcmpQueue, + MaintenanceMode, MessageQueue, OpenTechCommitteeInstance, ParachainInfo, ParachainSystem, + Perbill, PolkadotXcm, Runtime, RuntimeBlockWeights, RuntimeCall, RuntimeEvent, RuntimeOrigin, + Treasury, XcmpQueue, }; use frame_support::{ @@ -710,18 +711,39 @@ impl frame_support::traits::Contains for AssetFeesFilter { } } +pub type AddSupportedAssetOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::GeneralAdmin, + >, +>; + +pub type EditSupportedAssetOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::FastGeneralAdmin, + >, +>; + +pub type RemoveSupportedAssetOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionMoreThan, +>; + impl pallet_xcm_weight_trader::Config for Runtime { type AccountIdToLocation = AccountIdToLocation; - type AddSupportedAssetOrigin = EnsureRoot; + type AddSupportedAssetOrigin = AddSupportedAssetOrigin; type AssetLocationFilter = AssetFeesFilter; type AssetTransactor = AssetTransactors; type Balance = Balance; - type EditSupportedAssetOrigin = EnsureRoot; + type EditSupportedAssetOrigin = EditSupportedAssetOrigin; type NativeLocation = SelfReserve; - type PauseSupportedAssetOrigin = EnsureRoot; - type RemoveSupportedAssetOrigin = EnsureRoot; + type PauseSupportedAssetOrigin = EditSupportedAssetOrigin; + type RemoveSupportedAssetOrigin = RemoveSupportedAssetOrigin; type RuntimeEvent = RuntimeEvent; - type ResumeSupportedAssetOrigin = EnsureRoot; + type ResumeSupportedAssetOrigin = RemoveSupportedAssetOrigin; type WeightInfo = moonbeam_weights::pallet_xcm_weight_trader::WeightInfo; type WeightToFee = ::WeightToFee; type XcmFeesAccount = XcmFeesAccount; diff --git a/runtime/moonriver/src/xcm_config.rs b/runtime/moonriver/src/xcm_config.rs index 8ed6587496..f6d1faeea8 100644 --- a/runtime/moonriver/src/xcm_config.rs +++ b/runtime/moonriver/src/xcm_config.rs @@ -19,8 +19,9 @@ use super::{ governance, AccountId, AssetId, AssetManager, Balance, Balances, Erc20XcmBridge, - MaintenanceMode, MessageQueue, ParachainInfo, ParachainSystem, Perbill, PolkadotXcm, Runtime, - RuntimeBlockWeights, RuntimeCall, RuntimeEvent, RuntimeOrigin, Treasury, XcmpQueue, + MaintenanceMode, MessageQueue, OpenTechCommitteeInstance, ParachainInfo, ParachainSystem, + Perbill, PolkadotXcm, Runtime, RuntimeBlockWeights, RuntimeCall, RuntimeEvent, RuntimeOrigin, + Treasury, XcmpQueue, }; use frame_support::{ @@ -723,18 +724,39 @@ impl frame_support::traits::Contains for AssetFeesFilter { } } +pub type AddSupportedAssetOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::GeneralAdmin, + >, +>; + +pub type EditSupportedAssetOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::FastGeneralAdmin, + >, +>; + +pub type RemoveSupportedAssetOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionMoreThan, +>; + impl pallet_xcm_weight_trader::Config for Runtime { type AccountIdToLocation = AccountIdToLocation; - type AddSupportedAssetOrigin = EnsureRoot; + type AddSupportedAssetOrigin = AddSupportedAssetOrigin; type AssetLocationFilter = AssetFeesFilter; type AssetTransactor = AssetTransactors; type Balance = Balance; - type EditSupportedAssetOrigin = EnsureRoot; + type EditSupportedAssetOrigin = EditSupportedAssetOrigin; type NativeLocation = SelfReserve; - type PauseSupportedAssetOrigin = EnsureRoot; - type RemoveSupportedAssetOrigin = EnsureRoot; + type PauseSupportedAssetOrigin = EditSupportedAssetOrigin; + type RemoveSupportedAssetOrigin = RemoveSupportedAssetOrigin; type RuntimeEvent = RuntimeEvent; - type ResumeSupportedAssetOrigin = EnsureRoot; + type ResumeSupportedAssetOrigin = RemoveSupportedAssetOrigin; type WeightInfo = moonriver_weights::pallet_xcm_weight_trader::WeightInfo; type WeightToFee = ::WeightToFee; type XcmFeesAccount = XcmFeesAccount; From 871626d34b5b521bc0689c791a2b9a4b0d54bc7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Thu, 29 Aug 2024 18:38:40 +0200 Subject: [PATCH 17/27] fix: edit asset should not unpause asset --- pallets/xcm-weight-trader/src/lib.rs | 10 +++++----- pallets/xcm-weight-trader/src/tests.rs | 21 ++++++++++++++++++++- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/pallets/xcm-weight-trader/src/lib.rs b/pallets/xcm-weight-trader/src/lib.rs index 7a7bffa41b..5de2035fd4 100644 --- a/pallets/xcm-weight-trader/src/lib.rs +++ b/pallets/xcm-weight-trader/src/lib.rs @@ -189,12 +189,12 @@ pub mod pallet { T::EditSupportedAssetOrigin::ensure_origin(origin)?; ensure!(relative_price != 0, Error::::PriceCannotBeZero); - ensure!( - SupportedAssets::::contains_key(&location), - Error::::AssetNotFound - ); - SupportedAssets::::insert(&location, (true, relative_price)); + let enabled = SupportedAssets::::get(&location) + .ok_or(Error::::AssetNotFound)? + .0; + + SupportedAssets::::insert(&location, (enabled, relative_price)); Self::deposit_event(Event::SupportedAssetEdited { location, diff --git a/pallets/xcm-weight-trader/src/tests.rs b/pallets/xcm-weight-trader/src/tests.rs index b24e63519c..daceed2445 100644 --- a/pallets/xcm-weight-trader/src/tests.rs +++ b/pallets/xcm-weight-trader/src/tests.rs @@ -199,7 +199,7 @@ fn test_pause_asset_support() { Location::parent(), )); - // The account should be paused + // The asset should be paused assert_eq!( XcmWeightTrader::get_asset_relative_price(&Location::parent()), None, @@ -219,6 +219,25 @@ fn test_pause_asset_support() { ), Error::::AssetAlreadyPaused ); + + // Should be able to udpate relative price of paused asset + assert_ok!(XcmWeightTrader::edit_asset( + RuntimeOrigin::signed(EditAccount::get()), + Location::parent(), + 500 + )); + + // The asset should still be paused + assert_eq!( + XcmWeightTrader::get_asset_relative_price(&Location::parent()), + None, + ); + + // Check storage + assert_eq!( + crate::pallet::SupportedAssets::::get(&Location::parent()), + Some((false, 500)) + ); }) } From 0a70b3f68863d8705bca063535b4811b4c0136c4 Mon Sep 17 00:00:00 2001 From: Pablo Labarta Date: Mon, 2 Sep 2024 09:25:11 -0300 Subject: [PATCH 18/27] update registerOldForeignAssets to use xcmWeightTrader --- test/helpers/assets.ts | 203 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 188 insertions(+), 15 deletions(-) diff --git a/test/helpers/assets.ts b/test/helpers/assets.ts index c4b47f6a7b..f954c3ef83 100644 --- a/test/helpers/assets.ts +++ b/test/helpers/assets.ts @@ -1,12 +1,21 @@ import "@moonbeam-network/api-augment/moonbase"; import { u128 } from "@polkadot/types"; -import { BN, hexToU8a, u8aToHex } from "@polkadot/util"; +import { BN, hexToU8a, u8aConcat, u8aToHex } from "@polkadot/util"; import { expect, DevModeContext } from "@moonwall/cli"; import { blake2AsU8a, xxhashAsU8a } from "@polkadot/util-crypto"; import { KeyringPair } from "@polkadot/keyring/types"; -import type { PalletAssetsAssetAccount, PalletAssetsAssetDetails } from "@polkadot/types/lookup"; +import type { + MoonbaseRuntimeXcmConfigAssetType, + PalletAssetsAssetAccount, + PalletAssetsAssetDetails, + StagingXcmV3MultiLocation, + StagingXcmV4Asset, + StagingXcmV4Location, +} from "@polkadot/types/lookup"; import type { AccountId20 } from "@polkadot/types/interfaces/runtime"; import { encodeFunctionData, parseAbi } from "viem"; +import { ApiPromise, WsProvider } from "@polkadot/api"; +import { relative } from "path"; export const EVM_FOREIGN_ASSETS_PALLET_ACCOUNT = "0x6d6f646c666f7267617373740000000000000000"; export const ARBITRARY_ASSET_ID = 42259045809535163221576417993425387648n; @@ -46,6 +55,120 @@ export function assetContractAddress(assetId: bigint | string): `0x${string}` { return `0xffffffff${BigInt(assetId).toString(16)}`; } +const patchLocationV4recursively = (value: any) => { + // e.g. Convert this: { X1: { Parachain: 1000 } } to { X1: [ { Parachain: 1000 } ] } + if (value && typeof value == "object") { + if (Array.isArray(value)) { + return value.map(patchLocationV4recursively); + } + for (const k of Object.keys(value)) { + if (k === "Concrete" || k === "Abstract") { + return patchLocationV4recursively(value[k]); + } + if (k.match(/^X\d$/g) && !Array.isArray(value[k])) { + value[k] = Object.entries(value[k]).map(([k, v]) => ({ + [k]: patchLocationV4recursively(v), + })); + } else { + value[k] = patchLocationV4recursively(value[k]); + } + } + } + return value; +}; + +const runtimeApi = { + runtime: { + XcmPaymentApi: [ + { + methods: { + query_acceptable_payment_assets: { + description: "The API to query acceptable payment assets", + params: [ + { + name: "version", + type: "u32", + }, + ], + type: "Result, XcmPaymentApiError>", + }, + query_weight_to_asset_fee: { + description: "", + params: [ + { + name: "weight", + type: "WeightV2", + }, + { + name: "asset", + type: "XcmVersionedAssetId", + }, + ], + type: "Result", + }, + query_xcm_weight: { + description: "", + params: [ + { + name: "message", + type: "XcmVersionedXcm", + }, + ], + type: "Result", + }, + query_delivery_fees: { + description: "", + params: [ + { + name: "destination", + type: "XcmVersionedLocation", + }, + { + name: "message", + type: "XcmVersionedXcm", + }, + ], + type: "Result", + }, + }, + version: 1, + }, + ], + XcmWeightTrader: [ + { + methods: { + add_asset: { + description: "Add an asset to the supported assets", + params: [ + { + name: "asset", + type: "XcmVersionedAssetId", + }, + { + name: "relative_price", + type: "u128", + }, + ], + type: "Result<(), XcmPaymentApiError>", + }, + }, + version: 1, + }, + ], + }, + types: { + XcmPaymentApiError: { + _enum: { + Unimplemented: "Null", + VersionedConversionFailed: "Null", + WeightNotComputable: "Null", + UnhandledXcmVersion: "Null", + AssetNotFound: "Null", + }, + }, + }, +}; + // This registers an old foreign asset via the asset-manager pallet. // DEPRECATED: Please don't use for new tests export async function registerOldForeignAsset( @@ -55,7 +178,6 @@ export async function registerOldForeignAsset( unitsPerSecond?: number, numAssetsWeightHint?: number ) { - unitsPerSecond = unitsPerSecond != null ? unitsPerSecond : 0; const { result } = await context.createBlock( context .polkadotJs() @@ -63,26 +185,77 @@ export async function registerOldForeignAsset( context.polkadotJs().tx.assetManager.registerForeignAsset(asset, metadata, new BN(1), true) ) ); - // Look for assetId in events - const registeredAssetId = result!.events - .find(({ event: { section } }) => section.toString() === "assetManager")! - .event.data[0].toHex() - .replace(/,/g, ""); - // setAssetUnitsPerSecond + const polkadotJs = await ApiPromise.create({ + provider: new WsProvider(`ws://localhost:${process.env.MOONWALL_RPC_PORT}/`), + ...runtimeApi, + }); + + const WEIGHT_REF_TIME_PER_SECOND = 1_000_000_000_000; + const weight = { + refTime: WEIGHT_REF_TIME_PER_SECOND, + proofSize: 0, + }; + + const nativeAmountPerSecond = await context + .polkadotJs() + .call.transactionPaymentApi.queryWeightToFee(weight); + + const relativePriceDecimals = new BN(18); + const relativePrice = nativeAmountPerSecond + .mul(new BN(10).pow(relativePriceDecimals)) + .div(unitsPerSecond ? new BN(unitsPerSecond) : new BN(1)); + + const assetV4 = patchLocationV4recursively(asset.Xcm); const { result: result2 } = await context.createBlock( context .polkadotJs() - .tx.sudo.sudo( - context - .polkadotJs() - .tx.assetManager.setAssetUnitsPerSecond(asset, unitsPerSecond, numAssetsWeightHint!) - ), + .tx.sudo.sudo(context.polkadotJs().tx.xcmWeightTrader.addAsset(assetV4, relativePrice)), { - expectEvents: [context.polkadotJs().events.assetManager.UnitsPerSecondChanged], + expectEvents: [context.polkadotJs().events.xcmWeightTrader.SupportedAssetAdded], allowFailures: false, } ); + + // If no unitspersecond is provided, we add the asset to the supported assets + // and force-set the relative price to 0 + if (unitsPerSecond == null) { + const module = xxhashAsU8a(new TextEncoder().encode("XcmWeightTrader"), 128); + const method = xxhashAsU8a(new TextEncoder().encode("SupportedAssets"), 128); + + const assetLocationU8a = context + .polkadotJs() + .createType("StagingXcmV4Location", assetV4) + .toU8a(); + + const blake2concatStagingXcmV4Location = new Uint8Array([ + ...blake2AsU8a(assetLocationU8a, 128), + ...assetLocationU8a, + ]); + + const overallAssetKey = new Uint8Array([ + ...module, + ...method, + ...blake2concatStagingXcmV4Location, + ]); + + await context.createBlock( + context.polkadotJs().tx.sudo.sudo( + context.polkadotJs().tx.system.setStorage([ + [ + u8aToHex(overallAssetKey), + "0x0100000000000000000000000000000000", // (enabled bool, 0 u128) + ], + ]) + ) + ); + } + + const registeredAssetId = result!.events + .find(({ event: { section } }) => section.toString() === "assetManager")! + .event.data[0].toHex() + .replace(/,/g, ""); + // check asset in storage const registeredAsset = ( (await context.polkadotJs().query.assets.asset(registeredAssetId)) as any From dff2a26c6f476efa28f47530f88f1c4904090871 Mon Sep 17 00:00:00 2001 From: Pablo Labarta Date: Mon, 2 Sep 2024 14:03:12 -0300 Subject: [PATCH 19/27] fix tests using setAssetUnitsPerSecond --- test/helpers/assets.ts | 92 +++++++++++++++++-- .../test-maintenance-filter2.ts | 16 ++-- .../test-maintenance-filter3.ts | 11 +-- 3 files changed, 92 insertions(+), 27 deletions(-) diff --git a/test/helpers/assets.ts b/test/helpers/assets.ts index f954c3ef83..d048fd2fd9 100644 --- a/test/helpers/assets.ts +++ b/test/helpers/assets.ts @@ -1,21 +1,13 @@ import "@moonbeam-network/api-augment/moonbase"; import { u128 } from "@polkadot/types"; -import { BN, hexToU8a, u8aConcat, u8aToHex } from "@polkadot/util"; +import { BN, hexToU8a, u8aToHex } from "@polkadot/util"; import { expect, DevModeContext } from "@moonwall/cli"; import { blake2AsU8a, xxhashAsU8a } from "@polkadot/util-crypto"; import { KeyringPair } from "@polkadot/keyring/types"; -import type { - MoonbaseRuntimeXcmConfigAssetType, - PalletAssetsAssetAccount, - PalletAssetsAssetDetails, - StagingXcmV3MultiLocation, - StagingXcmV4Asset, - StagingXcmV4Location, -} from "@polkadot/types/lookup"; +import type { PalletAssetsAssetAccount, PalletAssetsAssetDetails } from "@polkadot/types/lookup"; import type { AccountId20 } from "@polkadot/types/interfaces/runtime"; import { encodeFunctionData, parseAbi } from "viem"; import { ApiPromise, WsProvider } from "@polkadot/api"; -import { relative } from "path"; export const EVM_FOREIGN_ASSETS_PALLET_ACCOUNT = "0x6d6f646c666f7267617373740000000000000000"; export const ARBITRARY_ASSET_ID = 42259045809535163221576417993425387648n; @@ -169,6 +161,86 @@ const runtimeApi = { }, }; +export async function calculateRelativePrice( + context: any, + unitsPerSecond: number +): Promise { + if (unitsPerSecond === 0) { + return 0n; + } + + const WEIGHT_REF_TIME_PER_SECOND = 1_000_000_000_000; + const weight = { + refTime: WEIGHT_REF_TIME_PER_SECOND, + proofSize: 0, + }; + + const nativeAmountPerSecond = await context + .polkadotJs() + .tx.transactionPaymentApi.queryWeightToFee(weight); + + const relativePriceDecimals = new BN(18); + const relativePrice = nativeAmountPerSecond + .mul(new BN(10).pow(relativePriceDecimals)) + .div(new BN(unitsPerSecond)); + + return relativePrice; +} + +function getSupportedAssedStorageKey(asset: any, context: any) { + const assetV4 = patchLocationV4recursively(asset); + + const module = xxhashAsU8a(new TextEncoder().encode("XcmWeightTrader"), 128); + const method = xxhashAsU8a(new TextEncoder().encode("SupportedAssets"), 128); + + const assetLocationU8a = context.polkadotJs().createType("StagingXcmV4Location", assetV4).toU8a(); + + const blake2concatStagingXcmV4Location = new Uint8Array([ + ...blake2AsU8a(assetLocationU8a, 128), + ...assetLocationU8a, + ]); + + return new Uint8Array([...module, ...method, ...blake2concatStagingXcmV4Location]); +} + +export async function addAssetToWeightTrader(asset: any, relativePrice: number, context: any) { + const assetV4 = patchLocationV4recursively(asset.Xcm); + + if (relativePrice == 0) { + const addAssetWithPlaceholderPrice = context + .polkadotJs() + .tx.sudo.sudo(context.polkadotJs().tx.xcmWeightTrader.addAsset(assetV4, 1n)); + const overallAssetKey = getSupportedAssedStorageKey(assetV4, context); + + const overrideAssetPrice = context.polkadotJs().tx.sudo.sudo( + context.polkadotJs().tx.system.setStorage([ + [ + u8aToHex(overallAssetKey), + "0x0100000000000000000000000000000000", // (enabled bool, 0 u128) + ], + ]) + ); + const batch = context + .polkadotJs() + .tx.utility.batch([addAssetWithPlaceholderPrice, overrideAssetPrice]); + + await context.createBlock(batch, { + expectEvents: [context.polkadotJs().events.xcmWeightTrader.SupportedAssetAdded], + allowFailures: false, + }); + } else { + await context.createBlock( + context + .polkadotJs() + .tx.sudo.sudo(context.polkadotJs().tx.xcmWeightTrader.addAsset(assetV4, relativePrice)), + { + expectEvents: [context.polkadotJs().events.xcmWeightTrader.SupportedAssetAdded], + allowFailures: false, + } + ); + } +} + // This registers an old foreign asset via the asset-manager pallet. // DEPRECATED: Please don't use for new tests export async function registerOldForeignAsset( diff --git a/test/suites/dev/moonbase/test-maintenance/test-maintenance-filter2.ts b/test/suites/dev/moonbase/test-maintenance/test-maintenance-filter2.ts index bd633b956c..858846f45e 100644 --- a/test/suites/dev/moonbase/test-maintenance/test-maintenance-filter2.ts +++ b/test/suites/dev/moonbase/test-maintenance/test-maintenance-filter2.ts @@ -9,7 +9,11 @@ import { import { ALITH_ADDRESS, alith, baltathar } from "@moonwall/util"; import { u128 } from "@polkadot/types-codec"; import { PalletAssetsAssetAccount, PalletAssetsAssetDetails } from "@polkadot/types/lookup"; -import { RELAY_SOURCE_LOCATION, mockOldAssetBalance } from "../../../../helpers"; +import { + RELAY_SOURCE_LOCATION, + addAssetToWeightTrader, + mockOldAssetBalance, +} from "../../../../helpers"; const ARBITRARY_ASSET_ID = 42259045809535163221576417993425387648n; @@ -47,14 +51,8 @@ describeSuite({ baltathar.address ); - // setAssetUnitsPerSecond - await context.createBlock( - context - .polkadotJs() - .tx.sudo.sudo( - context.polkadotJs().tx.assetManager.setAssetUnitsPerSecond(RELAY_SOURCE_LOCATION, 0, 0) - ) - ); + // set relative price in xcmWeightTrader + await addAssetToWeightTrader(RELAY_SOURCE_LOCATION, 0, context); await execOpenTechCommitteeProposal( context, diff --git a/test/suites/dev/moonbase/test-maintenance/test-maintenance-filter3.ts b/test/suites/dev/moonbase/test-maintenance/test-maintenance-filter3.ts index edf0784781..a08fcf3b80 100644 --- a/test/suites/dev/moonbase/test-maintenance/test-maintenance-filter3.ts +++ b/test/suites/dev/moonbase/test-maintenance/test-maintenance-filter3.ts @@ -9,6 +9,7 @@ import { } from "@moonwall/cli"; import { ALITH_ADDRESS } from "@moonwall/util"; import { BN } from "@polkadot/util"; +import { addAssetToWeightTrader } from "../../../../helpers"; describeSuite({ id: "D012003", @@ -51,14 +52,8 @@ describeSuite({ assetId = events.event.data[0].toHex().replace(/,/g, ""); - // setAssetUnitsPerSecond - await context.createBlock( - context - .polkadotJs() - .tx.sudo.sudo( - context.polkadotJs().tx.assetManager.setAssetUnitsPerSecond(sourceLocation, 0, 0) - ) - ); + // set relative price in xcmWeightTrader + await addAssetToWeightTrader(sourceLocation, 0, context); }); beforeEach(async () => { From 6d7be3be1370516c1b1d28b6bcb4a772527f8edb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Fri, 6 Sep 2024 11:55:54 +0200 Subject: [PATCH 20/27] Update pallets/xcm-weight-trader/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Agustín Rodriguez --- pallets/xcm-weight-trader/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/xcm-weight-trader/src/lib.rs b/pallets/xcm-weight-trader/src/lib.rs index 5de2035fd4..fc6a3954c8 100644 --- a/pallets/xcm-weight-trader/src/lib.rs +++ b/pallets/xcm-weight-trader/src/lib.rs @@ -426,7 +426,7 @@ impl WeightTrader for Trader { let amount: u128 = Self::compute_amount_to_charge(&weight, &location).unwrap_or(u128::MAX); let final_amount = amount.min(initial_amount); - let amount_to_refound = initial_amount.saturating_sub(final_amount); + let amount_to_refund = initial_amount.saturating_sub(final_amount); self.0 -= weight; self.1 = Some(Asset { fun: Fungibility::Fungible(final_amount), From 86f837e34dacaaa77129e7b13e2917b2728e581f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Fri, 6 Sep 2024 12:04:37 +0200 Subject: [PATCH 21/27] fix rust compilation --- pallets/xcm-weight-trader/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pallets/xcm-weight-trader/src/lib.rs b/pallets/xcm-weight-trader/src/lib.rs index fc6a3954c8..6acb15564f 100644 --- a/pallets/xcm-weight-trader/src/lib.rs +++ b/pallets/xcm-weight-trader/src/lib.rs @@ -435,10 +435,10 @@ impl WeightTrader for Trader { log::trace!( target: "xcm-weight-trader", "refund_weight amount to refund: {:?}", - amount_to_refound + amount_to_refund ); Some(Asset { - fun: Fungibility::Fungible(amount_to_refound), + fun: Fungibility::Fungible(amount_to_refund), id: XcmAssetId(location), }) } From a6bdc476dcce48c37f303e89400fe018ed5268ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Fri, 6 Sep 2024 12:05:43 +0200 Subject: [PATCH 22/27] benchmarks: use evm foreign assets for worst_case_holding --- pallets/moonbeam-foreign-assets/src/lib.rs | 5 +++++ pallets/xcm-weight-trader/src/lib.rs | 4 ++++ runtime/common/src/apis.rs | 18 ++++++------------ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/pallets/moonbeam-foreign-assets/src/lib.rs b/pallets/moonbeam-foreign-assets/src/lib.rs index 5e826eb7a1..88611e928d 100644 --- a/pallets/moonbeam-foreign-assets/src/lib.rs +++ b/pallets/moonbeam-foreign-assets/src/lib.rs @@ -268,6 +268,11 @@ pub mod pallet { pub fn weight_of_erc20_transfer() -> Weight { T::GasWeightMapping::gas_to_weight(evm::ERC20_TRANSFER_GAS_LIMIT, true) } + #[cfg(feature = "runtime-benchmarks")] + pub fn set_asset(asset_location: Location, asset_id: AssetId) { + AssetsByLocation::::insert(&asset_location, (asset_id, AssetStatus::Active)); + AssetsById::::insert(&asset_id, asset_location); + } } #[pallet::call] diff --git a/pallets/xcm-weight-trader/src/lib.rs b/pallets/xcm-weight-trader/src/lib.rs index 6acb15564f..120f3507eb 100644 --- a/pallets/xcm-weight-trader/src/lib.rs +++ b/pallets/xcm-weight-trader/src/lib.rs @@ -307,6 +307,10 @@ pub mod pallet { Err(XcmPaymentApiError::UnhandledXcmVersion) } } + #[cfg(feature = "runtime-benchmarks")] + pub fn set_asset_price(asset_location: Location, relative_price: u128) { + SupportedAssets::::insert(&asset_location, (true, relative_price)); + } } } diff --git a/runtime/common/src/apis.rs b/runtime/common/src/apis.rs index 53733f315c..f7df98d191 100644 --- a/runtime/common/src/apis.rs +++ b/runtime/common/src/apis.rs @@ -945,20 +945,14 @@ macro_rules! impl_runtime_apis_plus_common { id: AssetId(location), fun: Fungible(_) } = asset { - ::AssetId, - ::ForeignAssetType> - >::set_asset_type_asset_id( - location.clone().try_into().expect("convert to v3"), + EvmForeignAssets::set_asset( + location.clone(), i as u128 ); - // set 1-1 TODO: update before merging PR-2908 - /*::ForeignAssetType> - >::set_units_per_second( - location.clone().try_into().expect("convert to v3"), - 1_000_000_000_000u128 - );*/ + XcmWeightTrader::set_asset_price( + location.clone(), + 1u128.pow(18) + ); } } assets.into() From 7cd1b355597d9e2fa9cfaaf19f0daa3790c12d11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Thu, 12 Sep 2024 16:31:36 +0200 Subject: [PATCH 23/27] impl post-upgrade --- runtime/common/src/migrations.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/runtime/common/src/migrations.rs b/runtime/common/src/migrations.rs index 383b403be7..186b4949fc 100644 --- a/runtime/common/src/migrations.rs +++ b/runtime/common/src/migrations.rs @@ -75,7 +75,7 @@ where .map(|OldAssetType::Xcm(location_v3)| location_v3), ) } else { - return Weight::MAX; + return Weight::default(); }; let mut assets: Vec<(xcm::v4::Location, (bool, u128))> = Vec::new(); @@ -96,7 +96,7 @@ where //***** Start mutate storage *****// - // Write asset metadat in new pallet_xcm_weight_trader + // Write asset metadata in new pallet_xcm_weight_trader use frame_support::weights::WeightToFee as _; for (asset_location, (enabled, units_per_second)) in assets { let native_amount_per_second: u128 = @@ -132,17 +132,25 @@ where None, ); - Weight::MAX + Weight::default() } #[cfg(feature = "try-runtime")] fn pre_upgrade(&self) -> Result, sp_runtime::DispatchError> { - todo!() + Ok(Default::default()) } #[cfg(feature = "try-runtime")] fn post_upgrade(&self, state: Vec) -> Result<(), sp_runtime::DispatchError> { - todo!() + assert!(frame_support::storage::migration::storage_key_iter::< + OldAssetType, + u128, + frame_support::Blake2_128Concat, + >(b"AssetManager", b"AssetTypeUnitsPerSecond") + .next() + .is_none()); + + Ok(()) } } From 3c772e5bcb1f3b53b307caf274f5163ec7407f9b Mon Sep 17 00:00:00 2001 From: Rodrigo Quelhas Date: Thu, 12 Sep 2024 17:27:27 +0100 Subject: [PATCH 24/27] fix migration code --- runtime/common/src/migrations.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/runtime/common/src/migrations.rs b/runtime/common/src/migrations.rs index 186b4949fc..ef94f52b87 100644 --- a/runtime/common/src/migrations.rs +++ b/runtime/common/src/migrations.rs @@ -48,6 +48,11 @@ where } } +#[derive(parity_scale_codec::Decode, Eq, Ord, PartialEq, PartialOrd)] +enum OldAssetType { + Xcm(xcm::v3::Location), +} + pub struct MigrateXcmFeesAssetsMeatdata(PhantomData); impl Migration for MigrateXcmFeesAssetsMeatdata where @@ -59,11 +64,6 @@ where } fn migrate(&self, _available_weight: Weight) -> Weight { - #[derive(parity_scale_codec::Decode, Eq, Ord, PartialEq, PartialOrd)] - enum OldAssetType { - Xcm(xcm::v3::Location), - } - let supported_assets = if let Some(supported_assets) = frame_support::storage::migration::get_storage_value::< Vec, From 58a5b40b76c28083fb4a0a528da40d4e0acb0fd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Fri, 13 Sep 2024 15:51:27 +0200 Subject: [PATCH 25/27] fix rust test --- pallets/xcm-weight-trader/src/lib.rs | 2 +- runtime/moonbase/tests/xcm_mock/mod.rs | 1 + runtime/moonbase/tests/xcm_mock/parachain.rs | 3 +- runtime/moonbase/tests/xcm_tests.rs | 56 +++++++------------ runtime/moonbeam/tests/xcm_mock/mod.rs | 1 + runtime/moonbeam/tests/xcm_mock/parachain.rs | 3 +- runtime/moonbeam/tests/xcm_tests.rs | 56 +++++++------------ runtime/moonriver/tests/xcm_mock/mod.rs | 1 + runtime/moonriver/tests/xcm_mock/parachain.rs | 3 +- runtime/moonriver/tests/xcm_tests.rs | 56 +++++++------------ 10 files changed, 70 insertions(+), 112 deletions(-) diff --git a/pallets/xcm-weight-trader/src/lib.rs b/pallets/xcm-weight-trader/src/lib.rs index 120f3507eb..6fef42f452 100644 --- a/pallets/xcm-weight-trader/src/lib.rs +++ b/pallets/xcm-weight-trader/src/lib.rs @@ -307,7 +307,7 @@ pub mod pallet { Err(XcmPaymentApiError::UnhandledXcmVersion) } } - #[cfg(feature = "runtime-benchmarks")] + #[cfg(any(feature = "std", feature = "runtime-benchmarks"))] pub fn set_asset_price(asset_location: Location, relative_price: u128) { SupportedAssets::::insert(&asset_location, (true, relative_price)); } diff --git a/runtime/moonbase/tests/xcm_mock/mod.rs b/runtime/moonbase/tests/xcm_mock/mod.rs index 6c23384729..4a9e567d99 100644 --- a/runtime/moonbase/tests/xcm_mock/mod.rs +++ b/runtime/moonbase/tests/xcm_mock/mod.rs @@ -270,3 +270,4 @@ pub type XTokens = orml_xtokens::Pallet; pub type RelayBalances = pallet_balances::Pallet; pub type ParaBalances = pallet_balances::Pallet; pub type XcmTransactor = pallet_xcm_transactor::Pallet; +pub type XcmWeightTrader = pallet_xcm_weight_trader::Pallet; diff --git a/runtime/moonbase/tests/xcm_mock/parachain.rs b/runtime/moonbase/tests/xcm_mock/parachain.rs index 0d4f096a5b..4ee5ea120b 100644 --- a/runtime/moonbase/tests/xcm_mock/parachain.rs +++ b/runtime/moonbase/tests/xcm_mock/parachain.rs @@ -320,10 +320,9 @@ parameter_types! { pub const MaxAssetsIntoHolding: u32 = 64; pub AssetHubLocation: Location = Location::new(1, [Parachain(1000)]); - pub const RelayLocation: Location = Location::parent(); pub RelayLocationFilter: AssetFilter = Wild(AllOf { fun: WildFungible, - id: xcm::prelude::AssetId(RelayLocation::get()), + id: xcm::prelude::AssetId(Location::parent()), }); pub RelayChainNativeAssetFromAssetHub: (AssetFilter, Location) = ( diff --git a/runtime/moonbase/tests/xcm_tests.rs b/runtime/moonbase/tests/xcm_tests.rs index f33b1a4281..c406889ed8 100644 --- a/runtime/moonbase/tests/xcm_tests.rs +++ b/runtime/moonbase/tests/xcm_tests.rs @@ -2866,12 +2866,10 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - relay_location, + XcmWeightTrader::set_asset_price( + Location::parent(), 0u128, - 0 - )); + ); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3024,12 +3022,10 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_with_fee() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - relay_location, + XcmWeightTrader::set_asset_price( + Location::parent(), 0u128, - 0 - )); + ); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3186,12 +3182,10 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multiasset() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - relay_location, + XcmWeightTrader::set_asset_price( + Location::parent(), 0u128, - 0 - )); + ); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3363,12 +3357,10 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multicurrencies() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - relay_location, + XcmWeightTrader::set_asset_price( + Location::parent(), 0u128, - 0 - )); + ); assert_ok!(AssetManager::register_foreign_asset( parachain::RuntimeOrigin::root(), @@ -3377,12 +3369,10 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multicurrencies() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - statemint_location_asset, + XcmWeightTrader::set_asset_price( + statemint_asset, 0u128, - 1 - )); + ); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3619,12 +3609,10 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multiassets() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - relay_location, + XcmWeightTrader::set_asset_price( + Location::parent(), 0u128, - 0 - )); + ); assert_ok!(AssetManager::register_foreign_asset( parachain::RuntimeOrigin::root(), @@ -3633,12 +3621,10 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multiassets() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - statemint_location_asset, + XcmWeightTrader::set_asset_price( + statemint_asset.clone(), 0u128, - 1 - )); + ); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { diff --git a/runtime/moonbeam/tests/xcm_mock/mod.rs b/runtime/moonbeam/tests/xcm_mock/mod.rs index 96ba4b9ec4..231196031e 100644 --- a/runtime/moonbeam/tests/xcm_mock/mod.rs +++ b/runtime/moonbeam/tests/xcm_mock/mod.rs @@ -269,3 +269,4 @@ pub type XTokens = orml_xtokens::Pallet; pub type RelayBalances = pallet_balances::Pallet; pub type ParaBalances = pallet_balances::Pallet; pub type XcmTransactor = pallet_xcm_transactor::Pallet; +pub type XcmWeightTrader = pallet_xcm_weight_trader::Pallet; diff --git a/runtime/moonbeam/tests/xcm_mock/parachain.rs b/runtime/moonbeam/tests/xcm_mock/parachain.rs index 2d72108234..0ecc5cea07 100644 --- a/runtime/moonbeam/tests/xcm_mock/parachain.rs +++ b/runtime/moonbeam/tests/xcm_mock/parachain.rs @@ -312,10 +312,9 @@ parameter_types! { pub const MaxAssetsIntoHolding: u32 = 64; pub AssetHubLocation: Location = Location::new(1, [Parachain(1000)]); - pub const RelayLocation: Location = Location::parent(); pub RelayLocationFilter: AssetFilter = Wild(AllOf { fun: WildFungible, - id: xcm::prelude::AssetId(RelayLocation::get()), + id: xcm::prelude::AssetId(Location::parent()), }); pub RelayChainNativeAssetFromAssetHub: (AssetFilter, Location) = ( diff --git a/runtime/moonbeam/tests/xcm_tests.rs b/runtime/moonbeam/tests/xcm_tests.rs index ffab42a2a5..772d9dab5b 100644 --- a/runtime/moonbeam/tests/xcm_tests.rs +++ b/runtime/moonbeam/tests/xcm_tests.rs @@ -2606,12 +2606,10 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - relay_location, + XcmWeightTrader::set_asset_price( + Location::parent(), 0u128, - 0 - )); + ); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -2764,12 +2762,10 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_with_fee() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - relay_location, + XcmWeightTrader::set_asset_price( + Location::parent(), 0u128, - 0 - )); + ); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -2926,12 +2922,10 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multiasset() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - relay_location, + XcmWeightTrader::set_asset_price( + Location::parent(), 0u128, - 0 - )); + ); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3103,12 +3097,10 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multicurrencies() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - relay_location, + XcmWeightTrader::set_asset_price( + Location::parent(), 0u128, - 0 - )); + ); assert_ok!(AssetManager::register_foreign_asset( parachain::RuntimeOrigin::root(), @@ -3117,12 +3109,10 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multicurrencies() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - statemint_location_asset, + XcmWeightTrader::set_asset_price( + statemint_asset.clone(), 0u128, - 1 - )); + ); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3359,12 +3349,10 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multiassets() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - relay_location, + XcmWeightTrader::set_asset_price( + Location::parent(), 0u128, - 0 - )); + ); assert_ok!(AssetManager::register_foreign_asset( parachain::RuntimeOrigin::root(), @@ -3373,12 +3361,10 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multiassets() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - statemint_location_asset, + XcmWeightTrader::set_asset_price( + statemint_asset.clone(), 0u128, - 1 - )); + ); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { diff --git a/runtime/moonriver/tests/xcm_mock/mod.rs b/runtime/moonriver/tests/xcm_mock/mod.rs index 9b8f3ea50d..cb1cacc488 100644 --- a/runtime/moonriver/tests/xcm_mock/mod.rs +++ b/runtime/moonriver/tests/xcm_mock/mod.rs @@ -271,3 +271,4 @@ pub type XTokens = orml_xtokens::Pallet; pub type RelayBalances = pallet_balances::Pallet; pub type ParaBalances = pallet_balances::Pallet; pub type XcmTransactor = pallet_xcm_transactor::Pallet; +pub type XcmWeightTrader = pallet_xcm_weight_trader::Pallet; diff --git a/runtime/moonriver/tests/xcm_mock/parachain.rs b/runtime/moonriver/tests/xcm_mock/parachain.rs index 13e6d4d307..7ccf60dbd0 100644 --- a/runtime/moonriver/tests/xcm_mock/parachain.rs +++ b/runtime/moonriver/tests/xcm_mock/parachain.rs @@ -312,10 +312,9 @@ parameter_types! { pub const MaxAssetsIntoHolding: u32 = 64; pub AssetHubLocation: Location = Location::new(1, [Parachain(1000)]); - pub const RelayLocation: Location = Location::parent(); pub RelayLocationFilter: AssetFilter = Wild(AllOf { fun: WildFungible, - id: xcm::prelude::AssetId(RelayLocation::get()), + id: xcm::prelude::AssetId(Location::parent()), }); pub RelayChainNativeAssetFromAssetHub: (AssetFilter, Location) = ( diff --git a/runtime/moonriver/tests/xcm_tests.rs b/runtime/moonriver/tests/xcm_tests.rs index 97a8a91e00..a84a0d74f1 100644 --- a/runtime/moonriver/tests/xcm_tests.rs +++ b/runtime/moonriver/tests/xcm_tests.rs @@ -2903,12 +2903,10 @@ fn send_dot_from_moonbeam_to_statemine_via_xtokens_transfer() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - relay_location, + XcmWeightTrader::set_asset_price( + Location::parent(), 0u128, - 0 - )); + ); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3061,12 +3059,10 @@ fn send_dot_from_moonbeam_to_statemine_via_xtokens_transfer_with_fee() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - relay_location, + XcmWeightTrader::set_asset_price( + Location::parent(), 0u128, - 0 - )); + ); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3223,12 +3219,10 @@ fn send_dot_from_moonbeam_to_statemine_via_xtokens_transfer_multiasset() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - relay_location, + XcmWeightTrader::set_asset_price( + Location::parent(), 0u128, - 0 - )); + ); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3400,12 +3394,10 @@ fn send_dot_from_moonbeam_to_statemine_via_xtokens_transfer_multicurrencies() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - relay_location, + XcmWeightTrader::set_asset_price( + Location::parent(), 0u128, - 0 - )); + ); assert_ok!(AssetManager::register_foreign_asset( parachain::RuntimeOrigin::root(), @@ -3414,12 +3406,10 @@ fn send_dot_from_moonbeam_to_statemine_via_xtokens_transfer_multicurrencies() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - statemine_location_asset, + XcmWeightTrader::set_asset_price( + statemine_asset.clone(), 0u128, - 1 - )); + ); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3656,12 +3646,10 @@ fn send_dot_from_moonbeam_to_statemine_via_xtokens_transfer_multiassets() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - relay_location, + XcmWeightTrader::set_asset_price( + Location::parent(), 0u128, - 0 - )); + ); assert_ok!(AssetManager::register_foreign_asset( parachain::RuntimeOrigin::root(), @@ -3670,12 +3658,10 @@ fn send_dot_from_moonbeam_to_statemine_via_xtokens_transfer_multiassets() { 1u128, true )); - assert_ok!(AssetManager::set_asset_units_per_second( - parachain::RuntimeOrigin::root(), - statemine_location_asset, + XcmWeightTrader::set_asset_price( + statemine_asset.clone(), 0u128, - 1 - )); + ); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { From 6c028153b32b630fa49e676cce7b0f0e5d3ea2e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Fri, 13 Sep 2024 15:57:00 +0200 Subject: [PATCH 26/27] rustfmt --- runtime/moonbase/tests/xcm_tests.rs | 35 ++++++---------------------- runtime/moonbeam/tests/xcm_tests.rs | 35 ++++++---------------------- runtime/moonriver/tests/xcm_tests.rs | 35 ++++++---------------------- 3 files changed, 21 insertions(+), 84 deletions(-) diff --git a/runtime/moonbase/tests/xcm_tests.rs b/runtime/moonbase/tests/xcm_tests.rs index c406889ed8..e9234554ff 100644 --- a/runtime/moonbase/tests/xcm_tests.rs +++ b/runtime/moonbase/tests/xcm_tests.rs @@ -2866,10 +2866,7 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer() { 1u128, true )); - XcmWeightTrader::set_asset_price( - Location::parent(), - 0u128, - ); + XcmWeightTrader::set_asset_price(Location::parent(), 0u128); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3022,10 +3019,7 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_with_fee() { 1u128, true )); - XcmWeightTrader::set_asset_price( - Location::parent(), - 0u128, - ); + XcmWeightTrader::set_asset_price(Location::parent(), 0u128); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3182,10 +3176,7 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multiasset() { 1u128, true )); - XcmWeightTrader::set_asset_price( - Location::parent(), - 0u128, - ); + XcmWeightTrader::set_asset_price(Location::parent(), 0u128); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3357,10 +3348,7 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multicurrencies() { 1u128, true )); - XcmWeightTrader::set_asset_price( - Location::parent(), - 0u128, - ); + XcmWeightTrader::set_asset_price(Location::parent(), 0u128); assert_ok!(AssetManager::register_foreign_asset( parachain::RuntimeOrigin::root(), @@ -3369,10 +3357,7 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multicurrencies() { 1u128, true )); - XcmWeightTrader::set_asset_price( - statemint_asset, - 0u128, - ); + XcmWeightTrader::set_asset_price(statemint_asset, 0u128); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3609,10 +3594,7 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multiassets() { 1u128, true )); - XcmWeightTrader::set_asset_price( - Location::parent(), - 0u128, - ); + XcmWeightTrader::set_asset_price(Location::parent(), 0u128); assert_ok!(AssetManager::register_foreign_asset( parachain::RuntimeOrigin::root(), @@ -3621,10 +3603,7 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multiassets() { 1u128, true )); - XcmWeightTrader::set_asset_price( - statemint_asset.clone(), - 0u128, - ); + XcmWeightTrader::set_asset_price(statemint_asset.clone(), 0u128); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { diff --git a/runtime/moonbeam/tests/xcm_tests.rs b/runtime/moonbeam/tests/xcm_tests.rs index 772d9dab5b..1fdaa220d3 100644 --- a/runtime/moonbeam/tests/xcm_tests.rs +++ b/runtime/moonbeam/tests/xcm_tests.rs @@ -2606,10 +2606,7 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer() { 1u128, true )); - XcmWeightTrader::set_asset_price( - Location::parent(), - 0u128, - ); + XcmWeightTrader::set_asset_price(Location::parent(), 0u128); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -2762,10 +2759,7 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_with_fee() { 1u128, true )); - XcmWeightTrader::set_asset_price( - Location::parent(), - 0u128, - ); + XcmWeightTrader::set_asset_price(Location::parent(), 0u128); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -2922,10 +2916,7 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multiasset() { 1u128, true )); - XcmWeightTrader::set_asset_price( - Location::parent(), - 0u128, - ); + XcmWeightTrader::set_asset_price(Location::parent(), 0u128); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3097,10 +3088,7 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multicurrencies() { 1u128, true )); - XcmWeightTrader::set_asset_price( - Location::parent(), - 0u128, - ); + XcmWeightTrader::set_asset_price(Location::parent(), 0u128); assert_ok!(AssetManager::register_foreign_asset( parachain::RuntimeOrigin::root(), @@ -3109,10 +3097,7 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multicurrencies() { 1u128, true )); - XcmWeightTrader::set_asset_price( - statemint_asset.clone(), - 0u128, - ); + XcmWeightTrader::set_asset_price(statemint_asset.clone(), 0u128); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3349,10 +3334,7 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multiassets() { 1u128, true )); - XcmWeightTrader::set_asset_price( - Location::parent(), - 0u128, - ); + XcmWeightTrader::set_asset_price(Location::parent(), 0u128); assert_ok!(AssetManager::register_foreign_asset( parachain::RuntimeOrigin::root(), @@ -3361,10 +3343,7 @@ fn send_dot_from_moonbeam_to_statemint_via_xtokens_transfer_multiassets() { 1u128, true )); - XcmWeightTrader::set_asset_price( - statemint_asset.clone(), - 0u128, - ); + XcmWeightTrader::set_asset_price(statemint_asset.clone(), 0u128); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { diff --git a/runtime/moonriver/tests/xcm_tests.rs b/runtime/moonriver/tests/xcm_tests.rs index a84a0d74f1..ceee8aa521 100644 --- a/runtime/moonriver/tests/xcm_tests.rs +++ b/runtime/moonriver/tests/xcm_tests.rs @@ -2903,10 +2903,7 @@ fn send_dot_from_moonbeam_to_statemine_via_xtokens_transfer() { 1u128, true )); - XcmWeightTrader::set_asset_price( - Location::parent(), - 0u128, - ); + XcmWeightTrader::set_asset_price(Location::parent(), 0u128); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3059,10 +3056,7 @@ fn send_dot_from_moonbeam_to_statemine_via_xtokens_transfer_with_fee() { 1u128, true )); - XcmWeightTrader::set_asset_price( - Location::parent(), - 0u128, - ); + XcmWeightTrader::set_asset_price(Location::parent(), 0u128); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3219,10 +3213,7 @@ fn send_dot_from_moonbeam_to_statemine_via_xtokens_transfer_multiasset() { 1u128, true )); - XcmWeightTrader::set_asset_price( - Location::parent(), - 0u128, - ); + XcmWeightTrader::set_asset_price(Location::parent(), 0u128); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3394,10 +3385,7 @@ fn send_dot_from_moonbeam_to_statemine_via_xtokens_transfer_multicurrencies() { 1u128, true )); - XcmWeightTrader::set_asset_price( - Location::parent(), - 0u128, - ); + XcmWeightTrader::set_asset_price(Location::parent(), 0u128); assert_ok!(AssetManager::register_foreign_asset( parachain::RuntimeOrigin::root(), @@ -3406,10 +3394,7 @@ fn send_dot_from_moonbeam_to_statemine_via_xtokens_transfer_multicurrencies() { 1u128, true )); - XcmWeightTrader::set_asset_price( - statemine_asset.clone(), - 0u128, - ); + XcmWeightTrader::set_asset_price(statemine_asset.clone(), 0u128); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { @@ -3646,10 +3631,7 @@ fn send_dot_from_moonbeam_to_statemine_via_xtokens_transfer_multiassets() { 1u128, true )); - XcmWeightTrader::set_asset_price( - Location::parent(), - 0u128, - ); + XcmWeightTrader::set_asset_price(Location::parent(), 0u128); assert_ok!(AssetManager::register_foreign_asset( parachain::RuntimeOrigin::root(), @@ -3658,10 +3640,7 @@ fn send_dot_from_moonbeam_to_statemine_via_xtokens_transfer_multiassets() { 1u128, true )); - XcmWeightTrader::set_asset_price( - statemine_asset.clone(), - 0u128, - ); + XcmWeightTrader::set_asset_price(statemine_asset.clone(), 0u128); }); let parachain_beneficiary_absolute: Location = Junction::AccountKey20 { From c8d8a7f9a04ab75ea8c2f821e7ef1dfa3f227b0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Fri, 13 Sep 2024 16:18:42 +0200 Subject: [PATCH 27/27] remove unused import --- runtime/moonbase/tests/xcm_mock/parachain.rs | 10 +++++----- runtime/moonbeam/tests/xcm_mock/parachain.rs | 10 +++++----- runtime/moonriver/tests/xcm_mock/parachain.rs | 10 +++++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/runtime/moonbase/tests/xcm_mock/parachain.rs b/runtime/moonbase/tests/xcm_mock/parachain.rs index 4ee5ea120b..7dbc8584aa 100644 --- a/runtime/moonbase/tests/xcm_mock/parachain.rs +++ b/runtime/moonbase/tests/xcm_mock/parachain.rs @@ -50,11 +50,11 @@ use xcm::latest::{ }; use xcm_builder::{ AccountKey20Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, Case, ConvertedConcreteId, EnsureXcmOrigin, - FixedRateOfFungible, FixedWeightBounds, FungibleAdapter as XcmCurrencyAdapter, - FungiblesAdapter, IsConcrete, NoChecking, ParentAsSuperuser, ParentIsPreset, - RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountKey20AsNative, SovereignSignedViaLocation, TakeWeightCredit, WithComputedOrigin, + AllowTopLevelPaidExecutionFrom, Case, ConvertedConcreteId, EnsureXcmOrigin, FixedWeightBounds, + FungibleAdapter as XcmCurrencyAdapter, FungiblesAdapter, IsConcrete, NoChecking, + ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + SiblingParachainConvertsVia, SignedAccountKey20AsNative, SovereignSignedViaLocation, + TakeWeightCredit, WithComputedOrigin, }; use xcm_executor::{traits::JustTry, Config, XcmExecutor}; diff --git a/runtime/moonbeam/tests/xcm_mock/parachain.rs b/runtime/moonbeam/tests/xcm_mock/parachain.rs index 0ecc5cea07..3f41bcad58 100644 --- a/runtime/moonbeam/tests/xcm_mock/parachain.rs +++ b/runtime/moonbeam/tests/xcm_mock/parachain.rs @@ -51,11 +51,11 @@ use xcm::latest::{ }; use xcm_builder::{ AccountKey20Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, Case, ConvertedConcreteId, EnsureXcmOrigin, - FixedRateOfFungible, FixedWeightBounds, FungibleAdapter as XcmCurrencyAdapter, - FungiblesAdapter, IsConcrete, NoChecking, ParentAsSuperuser, ParentIsPreset, - RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountKey20AsNative, SovereignSignedViaLocation, TakeWeightCredit, WithComputedOrigin, + AllowTopLevelPaidExecutionFrom, Case, ConvertedConcreteId, EnsureXcmOrigin, FixedWeightBounds, + FungibleAdapter as XcmCurrencyAdapter, FungiblesAdapter, IsConcrete, NoChecking, + ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + SiblingParachainConvertsVia, SignedAccountKey20AsNative, SovereignSignedViaLocation, + TakeWeightCredit, WithComputedOrigin, }; use xcm_executor::{traits::JustTry, Config, XcmExecutor}; diff --git a/runtime/moonriver/tests/xcm_mock/parachain.rs b/runtime/moonriver/tests/xcm_mock/parachain.rs index 7ccf60dbd0..e71bc1e21e 100644 --- a/runtime/moonriver/tests/xcm_mock/parachain.rs +++ b/runtime/moonriver/tests/xcm_mock/parachain.rs @@ -49,11 +49,11 @@ use xcm::latest::{ }; use xcm_builder::{ AccountKey20Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, Case, ConvertedConcreteId, EnsureXcmOrigin, - FixedRateOfFungible, FixedWeightBounds, FungibleAdapter as XcmCurrencyAdapter, - FungiblesAdapter, IsConcrete, NoChecking, ParentAsSuperuser, ParentIsPreset, - RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountKey20AsNative, SovereignSignedViaLocation, TakeWeightCredit, WithComputedOrigin, + AllowTopLevelPaidExecutionFrom, Case, ConvertedConcreteId, EnsureXcmOrigin, FixedWeightBounds, + FungibleAdapter as XcmCurrencyAdapter, FungiblesAdapter, IsConcrete, NoChecking, + ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + SiblingParachainConvertsVia, SignedAccountKey20AsNative, SovereignSignedViaLocation, + TakeWeightCredit, WithComputedOrigin, }; use xcm_executor::{traits::JustTry, Config, XcmExecutor};