Introduce XcmFeesToAccount fee manager (#1234)

Combination of paritytech/polkadot#7005, its addon PR
paritytech/polkadot#7585 and its companion paritytech/cumulus#2433.

This PR introduces a new XcmFeesToAccount struct which implements the
`FeeManager` trait, and assigns this struct as the `FeeManager` in the
XCM config for all runtimes.

The struct simply deposits all fees handled by the XCM executor to a
specified account. In all runtimes, the specified account is configured
as the treasury account.

XCM __delivery__ fees are now being introduced (unless the root origin
is sending a message to a system parachain on behalf of the originating
chain).

# Note for reviewers

Most file changes are tests that had to be modified to account for the
new fees.
Main changes are in:
- cumulus/pallets/xcmp-queue/src/lib.rs <- To make it track the delivery
fees exponential factor
- polkadot/xcm/xcm-builder/src/fee_handling.rs <- Added. Has the
FeeManager implementation
- All runtime xcm_config files <- To add the FeeManager to the XCM
configuration

# Important note

After this change, instructions that create and send a new XCM (Query*,
Report*, ExportMessage, InitiateReserveWithdraw, InitiateTeleport,
DepositReserveAsset, TransferReserveAsset, LockAsset and RequestUnlock)
will require the corresponding origin account in the origin register to
pay for transport delivery fees, and the onward message will fail to be
sent if the origin account does not have the required amount. This
delivery fee is on top of what we already collect as tx fees in
pallet-xcm and XCM BuyExecution fees!

Wallet UIs that want to expose the new delivery fee can do so using the
formula:

```
delivery_fee_factor * (base_fee + encoded_msg_len * per_byte_fee)
```

where the delivery fee factor can be obtained from the corresponding
pallet based on which transport you are using (UMP, HRMP or bridges),
the base fee is a constant, the encoded message length from the message
itself and the per byte fee is the same as the configured per byte fee
for txs (i.e. `TransactionByteFee`).

---------

Co-authored-by: Branislav Kontur <bkontur@gmail.com>
Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
Co-authored-by: Giles Cope <gilescope@gmail.com>
Co-authored-by: command-bot <>
Co-authored-by: Francisco Aguirre <franciscoaguirreperez@gmail.com>
Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>
Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
This commit is contained in:
Keith Yeung
2023-10-18 23:22:25 +08:00
committed by GitHub
parent 1cf7d3aafa
commit 3dece311be
99 changed files with 2229 additions and 468 deletions
+7
View File
@@ -52,6 +52,9 @@ runtime-parachains = { package = "polkadot-runtime-parachains", path = "../parac
slot-range-helper = { path = "slot_range_helper", default-features = false }
xcm = { package = "staging-xcm", path = "../../xcm", default-features = false }
xcm-executor = { package = "staging-xcm-executor", path = "../../xcm/xcm-executor", default-features = false, optional = true }
pallet-xcm-benchmarks = { path = "../../xcm/pallet-xcm-benchmarks", default-features = false, optional = true }
xcm-builder = { package = "staging-xcm-builder", path = "../../xcm/xcm-builder", default-features = false }
[dev-dependencies]
@@ -89,6 +92,7 @@ std = [
"pallet-transaction-payment/std",
"pallet-treasury/std",
"pallet-vesting/std",
"pallet-xcm-benchmarks/std",
"parity-scale-codec/std",
"primitives/std",
"runtime-parachains/std",
@@ -105,6 +109,7 @@ std = [
"sp-staking/std",
"sp-std/std",
"xcm-builder/std",
"xcm-executor/std",
"xcm/std",
]
runtime-benchmarks = [
@@ -123,11 +128,13 @@ runtime-benchmarks = [
"pallet-timestamp/runtime-benchmarks",
"pallet-treasury/runtime-benchmarks",
"pallet-vesting/runtime-benchmarks",
"pallet-xcm-benchmarks/runtime-benchmarks",
"primitives/runtime-benchmarks",
"runtime-parachains/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"sp-staking/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
"xcm-executor/runtime-benchmarks",
]
try-runtime = [
"frame-election-provider-support/try-runtime",
+147 -22
View File
@@ -31,38 +31,63 @@ use SendError::*;
/// Simple value-bearing trait for determining/expressing the assets required to be paid for a
/// messages to be delivered to a parachain.
pub trait PriceForParachainDelivery {
pub trait PriceForMessageDelivery {
/// Type used for charging different prices to different destinations
type Id;
/// Return the assets required to deliver `message` to the given `para` destination.
fn price_for_parachain_delivery(para: ParaId, message: &Xcm<()>) -> MultiAssets;
fn price_for_delivery(id: Self::Id, message: &Xcm<()>) -> MultiAssets;
}
impl PriceForParachainDelivery for () {
fn price_for_parachain_delivery(_: ParaId, _: &Xcm<()>) -> MultiAssets {
impl PriceForMessageDelivery for () {
type Id = ();
fn price_for_delivery(_: Self::Id, _: &Xcm<()>) -> MultiAssets {
MultiAssets::new()
}
}
/// Implementation of `PriceForParachainDelivery` which returns a fixed price.
pub struct NoPriceForMessageDelivery<Id>(PhantomData<Id>);
impl<Id> PriceForMessageDelivery for NoPriceForMessageDelivery<Id> {
type Id = Id;
fn price_for_delivery(_: Self::Id, _: &Xcm<()>) -> MultiAssets {
MultiAssets::new()
}
}
/// Implementation of [`PriceForMessageDelivery`] which returns a fixed price.
pub struct ConstantPrice<T>(sp_std::marker::PhantomData<T>);
impl<T: Get<MultiAssets>> PriceForParachainDelivery for ConstantPrice<T> {
fn price_for_parachain_delivery(_: ParaId, _: &Xcm<()>) -> MultiAssets {
impl<T: Get<MultiAssets>> PriceForMessageDelivery for ConstantPrice<T> {
type Id = ();
fn price_for_delivery(_: Self::Id, _: &Xcm<()>) -> MultiAssets {
T::get()
}
}
/// Implementation of `PriceForParachainDelivery` which returns an exponentially increasing price.
/// The `A` type parameter is used to denote the asset ID that will be used for paying the delivery
/// fee.
///
/// Implementation of [`PriceForMessageDelivery`] which returns an exponentially increasing price.
/// The formula for the fee is based on the sum of a base fee plus a message length fee, multiplied
/// by a specified factor. In mathematical form, it is `F * (B + encoded_msg_len * M)`.
/// by a specified factor. In mathematical form:
///
/// `F * (B + encoded_msg_len * M)`
///
/// Thus, if F = 1 and M = 0, this type is equivalent to [`ConstantPrice<B>`].
///
/// The type parameters are understood as follows:
///
/// - `A`: Used to denote the asset ID that will be used for paying the delivery fee.
/// - `B`: The base fee to pay for message delivery.
/// - `M`: The fee to pay for each and every byte of the message after encoding it.
/// - `F`: A fee factor multiplier. It can be understood as the exponent term in the formula.
pub struct ExponentialPrice<A, B, M, F>(sp_std::marker::PhantomData<(A, B, M, F)>);
impl<A: Get<AssetId>, B: Get<u128>, M: Get<u128>, F: FeeTracker> PriceForParachainDelivery
impl<A: Get<AssetId>, B: Get<u128>, M: Get<u128>, F: FeeTracker> PriceForMessageDelivery
for ExponentialPrice<A, B, M, F>
{
fn price_for_parachain_delivery(para: ParaId, msg: &Xcm<()>) -> MultiAssets {
type Id = F::Id;
fn price_for_delivery(id: Self::Id, msg: &Xcm<()>) -> MultiAssets {
let msg_fee = (msg.encoded_size() as u128).saturating_mul(M::get());
let fee_sum = B::get().saturating_add(msg_fee);
let amount = F::get_fee_factor(para).saturating_mul_int(fee_sum);
let amount = F::get_fee_factor(id).saturating_mul_int(fee_sum);
(A::get(), amount).into()
}
}
@@ -70,8 +95,10 @@ impl<A: Get<AssetId>, B: Get<u128>, M: Get<u128>, F: FeeTracker> PriceForParacha
/// XCM sender for relay chain. It only sends downward message.
pub struct ChildParachainRouter<T, W, P>(PhantomData<(T, W, P)>);
impl<T: configuration::Config + dmp::Config, W: xcm::WrapVersion, P: PriceForParachainDelivery>
SendXcm for ChildParachainRouter<T, W, P>
impl<T: configuration::Config + dmp::Config, W: xcm::WrapVersion, P> SendXcm
for ChildParachainRouter<T, W, P>
where
P: PriceForMessageDelivery<Id = ParaId>,
{
type Ticket = (HostConfiguration<BlockNumberFor<T>>, ParaId, Vec<u8>);
@@ -91,7 +118,7 @@ impl<T: configuration::Config + dmp::Config, W: xcm::WrapVersion, P: PriceForPar
let xcm = msg.take().ok_or(MissingArgument)?;
let config = <configuration::Pallet<T>>::config();
let para = id.into();
let price = P::price_for_parachain_delivery(para, &xcm);
let price = P::price_for_delivery(para, &xcm);
let blob = W::wrap_version(&d, xcm).map_err(|()| DestinationUnsupported)?.encode();
<dmp::Pallet<T>>::can_queue_downward_message(&config, &para, &blob)
.map_err(Into::<SendError>::into)?;
@@ -109,6 +136,94 @@ impl<T: configuration::Config + dmp::Config, W: xcm::WrapVersion, P: PriceForPar
}
}
/// Implementation of `pallet_xcm_benchmarks::EnsureDelivery` which helps to ensure delivery to the
/// `ParaId` parachain (sibling or child). Deposits existential deposit for origin (if needed).
/// Deposits estimated fee to the origin account (if needed).
/// Allows to trigger additional logic for specific `ParaId` (e.g. open HRMP channel) (if neeeded).
#[cfg(feature = "runtime-benchmarks")]
pub struct ToParachainDeliveryHelper<
XcmConfig,
ExistentialDeposit,
PriceForDelivery,
ParaId,
ToParaIdHelper,
>(
sp_std::marker::PhantomData<(
XcmConfig,
ExistentialDeposit,
PriceForDelivery,
ParaId,
ToParaIdHelper,
)>,
);
#[cfg(feature = "runtime-benchmarks")]
impl<
XcmConfig: xcm_executor::Config,
ExistentialDeposit: Get<Option<MultiAsset>>,
PriceForDelivery: PriceForMessageDelivery<Id = ParaId>,
Parachain: Get<ParaId>,
ToParachainHelper: EnsureForParachain,
> pallet_xcm_benchmarks::EnsureDelivery
for ToParachainDeliveryHelper<
XcmConfig,
ExistentialDeposit,
PriceForDelivery,
Parachain,
ToParachainHelper,
>
{
fn ensure_successful_delivery(
origin_ref: &MultiLocation,
_dest: &MultiLocation,
fee_reason: xcm_executor::traits::FeeReason,
) -> (Option<xcm_executor::FeesMode>, Option<MultiAssets>) {
use xcm_executor::{
traits::{FeeManager, TransactAsset},
FeesMode,
};
let mut fees_mode = None;
if !XcmConfig::FeeManager::is_waived(Some(origin_ref), fee_reason) {
// if not waived, we need to set up accounts for paying and receiving fees
// mint ED to origin if needed
if let Some(ed) = ExistentialDeposit::get() {
XcmConfig::AssetTransactor::deposit_asset(&ed, &origin_ref, None).unwrap();
}
// overestimate delivery fee
let overestimated_xcm = vec![ClearOrigin; 128].into();
let overestimated_fees =
PriceForDelivery::price_for_delivery(Parachain::get(), &overestimated_xcm);
// mint overestimated fee to origin
for fee in overestimated_fees.inner() {
XcmConfig::AssetTransactor::deposit_asset(&fee, &origin_ref, None).unwrap();
}
// allow more initialization for target parachain
ToParachainHelper::ensure(Parachain::get());
// expected worst case - direct withdraw
fees_mode = Some(FeesMode { jit_withdraw: true });
}
(fees_mode, None)
}
}
/// Ensure more initialization for `ParaId`. (e.g. open HRMP channels, ...)
#[cfg(feature = "runtime-benchmarks")]
pub trait EnsureForParachain {
fn ensure(para_id: ParaId);
}
#[cfg(feature = "runtime-benchmarks")]
impl EnsureForParachain for () {
fn ensure(_: ParaId) {
// doing nothing
}
}
#[cfg(test)]
mod tests {
use super::*;
@@ -124,7 +239,17 @@ mod tests {
struct TestFeeTracker;
impl FeeTracker for TestFeeTracker {
fn get_fee_factor(_: ParaId) -> FixedU128 {
type Id = ParaId;
fn get_fee_factor(_: Self::Id) -> FixedU128 {
FixedU128::from_rational(101, 100)
}
fn increase_fee_factor(_: Self::Id, _: FixedU128) -> FixedU128 {
FixedU128::from_rational(101, 100)
}
fn decrease_fee_factor(_: Self::Id) -> FixedU128 {
FixedU128::from_rational(101, 100)
}
}
@@ -142,21 +267,21 @@ mod tests {
// message_length = 1
let result: u128 = TestFeeTracker::get_fee_factor(id).saturating_mul_int(b + m);
assert_eq!(
TestExponentialPrice::price_for_parachain_delivery(id, &Xcm(vec![])),
TestExponentialPrice::price_for_delivery(id, &Xcm(vec![])),
(FeeAssetId::get(), result).into()
);
// message size = 2
let result: u128 = TestFeeTracker::get_fee_factor(id).saturating_mul_int(b + (2 * m));
assert_eq!(
TestExponentialPrice::price_for_parachain_delivery(id, &Xcm(vec![ClearOrigin])),
TestExponentialPrice::price_for_delivery(id, &Xcm(vec![ClearOrigin])),
(FeeAssetId::get(), result).into()
);
// message size = 4
let result: u128 = TestFeeTracker::get_fee_factor(id).saturating_mul_int(b + (4 * m));
assert_eq!(
TestExponentialPrice::price_for_parachain_delivery(
TestExponentialPrice::price_for_delivery(
id,
&Xcm(vec![SetAppendix(Xcm(vec![ClearOrigin]))])
),
+20 -27
View File
@@ -17,12 +17,12 @@
//! To prevent Out of Memory errors on the `DownwardMessageQueue`, an
//! exponential fee factor (`DeliveryFeeFactor`) is set. The fee factor
//! increments exponentially after the number of messages in the
//! `DownwardMessageQueue` pass a threshold. This threshold is set as:
//! `DownwardMessageQueue` passes a threshold. This threshold is set as:
//!
//! ```ignore
//! // Maximum max sized messages that can be send to
//! // the DownwardMessageQueue before it runs out of memory
//! max_messsages = MAX_POSSIBLE_ALLOCATION / max_downward_message_size
//! max_messages = MAX_POSSIBLE_ALLOCATION / max_downward_message_size
//! threshold = max_messages / THRESHOLD_FACTOR
//! ```
//! Based on the THRESHOLD_FACTOR, the threshold is set as a fraction of the
@@ -144,7 +144,7 @@ pub mod pallet {
FixedU128::from_u32(1)
}
/// The number to multiply the base delivery fee by.
/// The factor to multiply the base delivery fee by.
#[pallet::storage]
pub(crate) type DeliveryFeeFactor<T: Config> =
StorageMap<_, Twox64Concat, ParaId, FixedU128, ValueQuery, InitialFactor>;
@@ -243,10 +243,9 @@ impl<T: Config> Pallet<T> {
let threshold =
Self::dmq_max_length(config.max_downward_message_size).saturating_div(THRESHOLD_FACTOR);
if q_len > (threshold as usize) {
let message_size_factor =
FixedU128::from_u32(serialized_len.saturating_div(1024) as u32)
.saturating_mul(MESSAGE_SIZE_FEE_BASE);
Self::increment_fee_factor(para, message_size_factor);
let message_size_factor = FixedU128::from((serialized_len / 1024) as u128)
.saturating_mul(MESSAGE_SIZE_FEE_BASE);
Self::increase_fee_factor(para, message_size_factor);
}
Ok(())
@@ -304,7 +303,7 @@ impl<T: Config> Pallet<T> {
let threshold =
Self::dmq_max_length(config.max_downward_message_size).saturating_div(THRESHOLD_FACTOR);
if q_len <= (threshold as usize) {
Self::decrement_fee_factor(para);
Self::decrease_fee_factor(para);
}
T::DbWeight::get().reads_writes(1, 1)
}
@@ -337,32 +336,26 @@ impl<T: Config> Pallet<T> {
) -> Vec<InboundDownwardMessage<BlockNumberFor<T>>> {
DownwardMessageQueues::<T>::get(&recipient)
}
}
/// Raise the delivery fee factor by a multiplicative factor and stores the resulting value.
///
/// Returns the new delivery fee factor after the increment.
pub(crate) fn increment_fee_factor(para: ParaId, message_size_factor: FixedU128) -> FixedU128 {
<DeliveryFeeFactor<T>>::mutate(para, |f| {
*f = f.saturating_mul(EXPONENTIAL_FEE_BASE + message_size_factor);
impl<T: Config> FeeTracker for Pallet<T> {
type Id = ParaId;
fn get_fee_factor(id: Self::Id) -> FixedU128 {
DeliveryFeeFactor::<T>::get(id)
}
fn increase_fee_factor(id: Self::Id, message_size_factor: FixedU128) -> FixedU128 {
<DeliveryFeeFactor<T>>::mutate(id, |f| {
*f = f.saturating_mul(EXPONENTIAL_FEE_BASE.saturating_add(message_size_factor));
*f
})
}
/// Reduce the delivery fee factor by a multiplicative factor and stores the resulting value.
///
/// Does not reduce the fee factor below the initial value, which is currently set as 1.
///
/// Returns the new delivery fee factor after the decrement.
pub(crate) fn decrement_fee_factor(para: ParaId) -> FixedU128 {
<DeliveryFeeFactor<T>>::mutate(para, |f| {
fn decrease_fee_factor(id: Self::Id) -> FixedU128 {
<DeliveryFeeFactor<T>>::mutate(id, |f| {
*f = InitialFactor::get().max(*f / EXPONENTIAL_FEE_BASE);
*f
})
}
}
impl<T: Config> FeeTracker for Pallet<T> {
fn get_fee_factor(para: ParaId) -> FixedU128 {
DeliveryFeeFactor::<T>::get(para)
}
}
+1 -1
View File
@@ -233,7 +233,7 @@ fn verify_dmq_mqc_head_is_externally_accessible() {
}
#[test]
fn verify_fee_increment_and_decrement() {
fn verify_fee_increase_and_decrease() {
let a = ParaId::from(123);
let mut genesis = default_genesis_config();
genesis.configuration.config.max_downward_message_size = 16777216;
+15 -1
View File
@@ -59,7 +59,21 @@ use sp_runtime::{DispatchResult, FixedU128};
/// Trait for tracking message delivery fees on a transport protocol.
pub trait FeeTracker {
fn get_fee_factor(para: ParaId) -> FixedU128;
/// Type used for assigning different fee factors to different destinations
type Id;
/// Returns the evolving exponential fee factor which will be used to calculate the delivery
/// fees.
fn get_fee_factor(id: Self::Id) -> FixedU128;
/// Increases the delivery fee factor by a factor based on message size and records the result.
///
/// Returns the new delivery fee factor after the increase.
fn increase_fee_factor(id: Self::Id, message_size_factor: FixedU128) -> FixedU128;
/// Decreases the delivery fee factor by a constant factor and records the result.
///
/// Does not reduce the fee factor below the initial value, which is currently set as 1.
///
/// Returns the new delivery fee factor after the decrease.
fn decrease_fee_factor(id: Self::Id) -> FixedU128;
}
/// Schedule a para to be initialized at the start of the next session with the given genesis data.
@@ -16,6 +16,8 @@ sp-runtime = { path = "../../../../substrate/primitives/runtime", default-featur
sp-weights = { path = "../../../../substrate/primitives/weights", default-features = false }
sp-core = { path = "../../../../substrate/primitives/core", default-features = false }
xcm = { package = "staging-xcm", path = "../../../xcm", default-features = false }
[features]
default = [ "std" ]
std = [
@@ -25,4 +27,5 @@ std = [
"sp-core/std",
"sp-runtime/std",
"sp-weights/std",
"xcm/std",
]
@@ -100,6 +100,26 @@ pub mod fee {
}
}
/// System Parachains.
pub mod system_parachain {
use xcm::latest::prelude::*;
/// Network's Asset Hub parachain ID.
pub const ASSET_HUB_ID: u32 = 1000;
/// Contracts parachain ID.
pub const CONTRACTS_ID: u32 = 1002;
/// Encointer parachain ID.
pub const ENCOINTER_ID: u32 = 1003;
/// BridgeHub parachain ID.
pub const BRIDGE_HUB_ID: u32 = 1013;
frame_support::match_types! {
pub type SystemParachains: impl Contains<MultiLocation> = {
MultiLocation { parents: 0, interior: X1(Parachain(ASSET_HUB_ID | CONTRACTS_ID | ENCOINTER_ID | BRIDGE_HUB_ID)) }
};
}
}
#[cfg(test)]
mod tests {
use super::{
+17 -1
View File
@@ -2072,14 +2072,29 @@ sp_api::impl_runtime_apis! {
use sp_storage::TrackedStorageKey;
use xcm::latest::prelude::*;
use xcm_config::{
LocalCheckAccount, LocationConverter, AssetHub, TokenLocation, XcmConfig,
AssetHub, LocalCheckAccount, LocationConverter, TokenLocation, XcmConfig,
};
parameter_types! {
pub ExistentialDepositMultiAsset: Option<MultiAsset> = Some((
TokenLocation::get(),
ExistentialDeposit::get()
).into());
pub ToParachain: ParaId = rococo_runtime_constants::system_parachain::ASSET_HUB_ID.into();
}
impl frame_system_benchmarking::Config for Runtime {}
impl frame_benchmarking::baseline::Config for Runtime {}
impl pallet_xcm_benchmarks::Config for Runtime {
type XcmConfig = XcmConfig;
type AccountIdConverter = LocationConverter;
type DeliveryHelper = runtime_common::xcm_sender::ToParachainDeliveryHelper<
XcmConfig,
ExistentialDepositMultiAsset,
xcm_config::PriceForChildParachainDelivery,
ToParachain,
(),
>;
fn valid_destination() -> Result<MultiLocation, BenchmarkError> {
Ok(AssetHub::get())
}
@@ -2116,6 +2131,7 @@ sp_api::impl_runtime_apis! {
}
impl pallet_xcm_benchmarks::generic::Config for Runtime {
type TransactAsset = Balances;
type RuntimeCall = RuntimeCall;
fn worst_case_response() -> (u64, Response) {
+18 -15
View File
@@ -18,7 +18,7 @@
use super::{
parachains_origin, AccountId, AllPalletsWithSystem, Balances, Dmp, Fellows, ParaId, Runtime,
RuntimeCall, RuntimeEvent, RuntimeOrigin, TransactionByteFee, WeightToFee, XcmPallet,
RuntimeCall, RuntimeEvent, RuntimeOrigin, TransactionByteFee, Treasury, WeightToFee, XcmPallet,
};
use crate::governance::StakingAdmin;
@@ -29,7 +29,7 @@ use frame_support::{
weights::Weight,
};
use frame_system::EnsureRoot;
use rococo_runtime_constants::currency::CENTS;
use rococo_runtime_constants::{currency::CENTS, system_parachain::*};
use runtime_common::{
xcm_sender::{ChildParachainRouter, ExponentialPrice},
ToAuthor,
@@ -43,7 +43,7 @@ use xcm_builder::{
DescribeFamily, FixedWeightBounds, HashedDescription, IsChildSystemParachain, IsConcrete,
MintLocation, OriginToPluralityVoice, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeesToAccount,
};
use xcm_executor::XcmExecutor;
@@ -53,6 +53,7 @@ parameter_types! {
pub UniversalLocation: InteriorMultiLocation = ThisNetwork::get().into();
pub CheckAccount: AccountId = XcmPallet::check_account();
pub LocalCheckAccount: (AccountId, MintLocation) = (CheckAccount::get(), MintLocation::Local);
pub TreasuryAccount: Option<AccountId> = Some(Treasury::account_id());
}
pub type LocationConverter = (
@@ -100,22 +101,22 @@ parameter_types! {
pub const BaseDeliveryFee: u128 = CENTS.saturating_mul(3);
}
pub type PriceForChildParachainDelivery =
ExponentialPrice<FeeAssetId, BaseDeliveryFee, TransactionByteFee, Dmp>;
/// The XCM router. When we want to send an XCM message, we use this type. It amalgamates all of our
/// individual routers.
pub type XcmRouter = WithUniqueTopic<(
pub type XcmRouter = WithUniqueTopic<
// Only one router so far - use DMP to communicate with child parachains.
ChildParachainRouter<
Runtime,
XcmPallet,
ExponentialPrice<FeeAssetId, BaseDeliveryFee, TransactionByteFee, Dmp>,
>,
)>;
ChildParachainRouter<Runtime, XcmPallet, PriceForChildParachainDelivery>,
>;
parameter_types! {
pub const Roc: MultiAssetFilter = Wild(AllOf { fun: WildFungible, id: Concrete(TokenLocation::get()) });
pub const AssetHub: MultiLocation = Parachain(1000).into_location();
pub const Contracts: MultiLocation = Parachain(1002).into_location();
pub const Encointer: MultiLocation = Parachain(1003).into_location();
pub const AssetHub: MultiLocation = Parachain(ASSET_HUB_ID).into_location();
pub const Contracts: MultiLocation = Parachain(CONTRACTS_ID).into_location();
pub const Encointer: MultiLocation = Parachain(ENCOINTER_ID).into_location();
pub const BridgeHub: MultiLocation = Parachain(BRIDGE_HUB_ID).into_location();
pub const Tick: MultiLocation = Parachain(100).into_location();
pub const Trick: MultiLocation = Parachain(110).into_location();
pub const Track: MultiLocation = Parachain(120).into_location();
@@ -125,6 +126,7 @@ parameter_types! {
pub const RocForAssetHub: (MultiAssetFilter, MultiLocation) = (Roc::get(), AssetHub::get());
pub const RocForContracts: (MultiAssetFilter, MultiLocation) = (Roc::get(), Contracts::get());
pub const RocForEncointer: (MultiAssetFilter, MultiLocation) = (Roc::get(), Encointer::get());
pub const RocForBridgeHub: (MultiAssetFilter, MultiLocation) = (Roc::get(), BridgeHub::get());
pub const MaxInstructions: u32 = 100;
pub const MaxAssetsIntoHolding: u32 = 64;
}
@@ -135,6 +137,7 @@ pub type TrustedTeleporters = (
xcm_builder::Case<RocForAssetHub>,
xcm_builder::Case<RocForContracts>,
xcm_builder::Case<RocForEncointer>,
xcm_builder::Case<RocForBridgeHub>,
);
match_types! {
@@ -188,7 +191,7 @@ impl xcm_executor::Config for XcmConfig {
type SubscriptionService = XcmPallet;
type PalletInstancesInfo = AllPalletsWithSystem;
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
type FeeManager = ();
type FeeManager = XcmFeesToAccount<Self, SystemParachains, AccountId, TreasuryAccount>;
type MessageExporter = ();
type UniversalAliases = Nothing;
type CallDispatcher = RuntimeCall;
@@ -206,7 +209,7 @@ parameter_types! {
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub ReachableDest: Option<MultiLocation> = Some(Parachain(1000).into());
pub ReachableDest: Option<MultiLocation> = Some(Parachain(ASSET_HUB_ID).into());
}
/// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior
@@ -60,7 +60,11 @@ pub type Barrier = AllowUnpaidExecutionFrom<Everything>;
pub struct DummyAssetTransactor;
impl TransactAsset for DummyAssetTransactor {
fn deposit_asset(_what: &MultiAsset, _who: &MultiLocation, _context: &XcmContext) -> XcmResult {
fn deposit_asset(
_what: &MultiAsset,
_who: &MultiLocation,
_context: Option<&XcmContext>,
) -> XcmResult {
Ok(())
}
@@ -16,6 +16,8 @@ sp-runtime = { path = "../../../../substrate/primitives/runtime", default-featur
sp-weights = { path = "../../../../substrate/primitives/weights", default-features = false }
sp-core = { path = "../../../../substrate/primitives/core", default-features = false }
xcm = { package = "staging-xcm", path = "../../../xcm", default-features = false }
[features]
default = [ "std" ]
std = [
@@ -25,4 +27,5 @@ std = [
"sp-core/std",
"sp-runtime/std",
"sp-weights/std",
"xcm/std",
]
+18 -8
View File
@@ -96,6 +96,24 @@ pub mod fee {
}
}
/// System Parachains.
pub mod system_parachain {
use xcm::latest::prelude::*;
/// Network's Asset Hub parachain ID.
pub const ASSET_HUB_ID: u32 = 1000;
/// Collectives parachain ID.
pub const COLLECTIVES_ID: u32 = 1001;
/// BridgeHub parachain ID.
pub const BRIDGE_HUB_ID: u32 = 1002;
frame_support::match_types! {
pub type SystemParachains: impl Contains<MultiLocation> = {
MultiLocation { parents: 0, interior: X1(Parachain(ASSET_HUB_ID | COLLECTIVES_ID | BRIDGE_HUB_ID ))}
};
}
}
/// XCM protocol related constants.
pub mod xcm {
/// Pluralistic bodies existing within the consensus.
@@ -108,14 +126,6 @@ pub mod xcm {
}
}
/// System Parachains.
pub mod system_parachain {
/// Statemint parachain ID.
pub const ASSET_HUB_ID: u32 = 1000;
/// Collectives parachain ID.
pub const COLLECTIVES_ID: u32 = 1001;
}
#[cfg(test)]
mod tests {
use super::{
+16
View File
@@ -2182,9 +2182,24 @@ sp_api::impl_runtime_apis! {
};
use xcm_config::{AssetHub, TokenLocation};
parameter_types! {
pub ExistentialDepositMultiAsset: Option<MultiAsset> = Some((
TokenLocation::get(),
ExistentialDeposit::get()
).into());
pub ToParachain: ParaId = westend_runtime_constants::system_parachain::ASSET_HUB_ID.into();
}
impl pallet_xcm_benchmarks::Config for Runtime {
type XcmConfig = xcm_config::XcmConfig;
type AccountIdConverter = xcm_config::LocationConverter;
type DeliveryHelper = runtime_common::xcm_sender::ToParachainDeliveryHelper<
xcm_config::XcmConfig,
ExistentialDepositMultiAsset,
xcm_config::PriceForChildParachainDelivery,
ToParachain,
(),
>;
fn valid_destination() -> Result<MultiLocation, BenchmarkError> {
Ok(AssetHub::get())
}
@@ -2221,6 +2236,7 @@ sp_api::impl_runtime_apis! {
}
impl pallet_xcm_benchmarks::generic::Config for Runtime {
type TransactAsset = Balances;
type RuntimeCall = RuntimeCall;
fn worst_case_response() -> (u64, Response) {
@@ -17,7 +17,7 @@
//! Autogenerated weights for `pallet_xcm_benchmarks::fungible`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2023-09-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! DATE: 2023-10-03, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `runner-nbnwcyh-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
//! WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024
@@ -55,8 +55,8 @@ impl<T: frame_system::Config> WeightInfo<T> {
// Proof Size summary in bytes:
// Measured: `101`
// Estimated: `3593`
// Minimum execution time: 24_642_000 picoseconds.
Weight::from_parts(24_973_000, 3593)
// Minimum execution time: 24_815_000 picoseconds.
Weight::from_parts(25_098_000, 3593)
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
@@ -66,8 +66,8 @@ impl<T: frame_system::Config> WeightInfo<T> {
// Proof Size summary in bytes:
// Measured: `101`
// Estimated: `6196`
// Minimum execution time: 50_882_000 picoseconds.
Weight::from_parts(51_516_000, 6196)
// Minimum execution time: 51_268_000 picoseconds.
Weight::from_parts(51_857_000, 6196)
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(2))
}
@@ -85,8 +85,8 @@ impl<T: frame_system::Config> WeightInfo<T> {
// Proof Size summary in bytes:
// Measured: `210`
// Estimated: `6196`
// Minimum execution time: 73_923_000 picoseconds.
Weight::from_parts(75_454_000, 6196)
// Minimum execution time: 74_113_000 picoseconds.
Weight::from_parts(74_721_000, 6196)
.saturating_add(T::DbWeight::get().reads(6))
.saturating_add(T::DbWeight::get().writes(4))
}
@@ -111,8 +111,8 @@ impl<T: frame_system::Config> WeightInfo<T> {
// Proof Size summary in bytes:
// Measured: `109`
// Estimated: `3574`
// Minimum execution time: 29_035_000 picoseconds.
Weight::from_parts(30_086_000, 3574)
// Minimum execution time: 28_919_000 picoseconds.
Weight::from_parts(29_703_000, 3574)
.saturating_add(T::DbWeight::get().reads(4))
.saturating_add(T::DbWeight::get().writes(2))
}
@@ -122,8 +122,8 @@ impl<T: frame_system::Config> WeightInfo<T> {
// Proof Size summary in bytes:
// Measured: `103`
// Estimated: `3593`
// Minimum execution time: 22_094_000 picoseconds.
Weight::from_parts(22_560_000, 3593)
// Minimum execution time: 21_685_000 picoseconds.
Weight::from_parts(22_528_000, 3593)
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
@@ -133,8 +133,8 @@ impl<T: frame_system::Config> WeightInfo<T> {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `3593`
// Minimum execution time: 24_771_000 picoseconds.
Weight::from_parts(25_280_000, 3593)
// Minimum execution time: 25_192_000 picoseconds.
Weight::from_parts(25_445_000, 3593)
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
@@ -152,8 +152,8 @@ impl<T: frame_system::Config> WeightInfo<T> {
// Proof Size summary in bytes:
// Measured: `109`
// Estimated: `3593`
// Minimum execution time: 49_777_000 picoseconds.
Weight::from_parts(50_833_000, 3593)
// Minimum execution time: 49_349_000 picoseconds.
Weight::from_parts(50_476_000, 3593)
.saturating_add(T::DbWeight::get().reads(5))
.saturating_add(T::DbWeight::get().writes(3))
}
@@ -171,8 +171,8 @@ impl<T: frame_system::Config> WeightInfo<T> {
// Proof Size summary in bytes:
// Measured: `109`
// Estimated: `3593`
// Minimum execution time: 51_425_000 picoseconds.
Weight::from_parts(52_213_000, 3593)
// Minimum execution time: 51_386_000 picoseconds.
Weight::from_parts(52_141_000, 3593)
.saturating_add(T::DbWeight::get().reads(5))
.saturating_add(T::DbWeight::get().writes(3))
}
+24 -18
View File
@@ -19,7 +19,7 @@
use super::{
parachains_origin, AccountId, AllPalletsWithSystem, Balances, Dmp, FellowshipAdmin,
GeneralAdmin, ParaId, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, StakingAdmin,
TransactionByteFee, WeightToFee, XcmPallet,
TransactionByteFee, Treasury, WeightToFee, XcmPallet,
};
use frame_support::{
@@ -44,6 +44,7 @@ use xcm_builder::{
DescribeFamily, HashedDescription, IsConcrete, MintLocation, OriginToPluralityVoice,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
XcmFeesToAccount,
};
use xcm_executor::XcmExecutor;
@@ -53,6 +54,7 @@ parameter_types! {
pub const UniversalLocation: InteriorMultiLocation = X1(GlobalConsensus(ThisNetwork::get()));
pub CheckAccount: AccountId = XcmPallet::check_account();
pub LocalCheckAccount: (AccountId, MintLocation) = (CheckAccount::get(), MintLocation::Local);
pub TreasuryAccount: Option<AccountId> = Some(Treasury::account_id());
/// The asset ID for the asset that we use to pay for message delivery fees.
pub FeeAssetId: AssetId = Concrete(TokenLocation::get());
/// The base fee for the message delivery fees.
@@ -95,29 +97,38 @@ type LocalOriginConverter = (
XcmPassthrough<RuntimeOrigin>,
);
pub type PriceForChildParachainDelivery =
ExponentialPrice<FeeAssetId, BaseDeliveryFee, TransactionByteFee, Dmp>;
/// The XCM router. When we want to send an XCM message, we use this type. It amalgamates all of our
/// individual routers.
pub type XcmRouter = WithUniqueTopic<(
pub type XcmRouter = WithUniqueTopic<
// Only one router so far - use DMP to communicate with child parachains.
ChildParachainRouter<
Runtime,
XcmPallet,
ExponentialPrice<FeeAssetId, BaseDeliveryFee, TransactionByteFee, Dmp>,
>,
)>;
ChildParachainRouter<Runtime, XcmPallet, PriceForChildParachainDelivery>,
>;
parameter_types! {
pub const Wnd: MultiAssetFilter = Wild(AllOf { fun: WildFungible, id: Concrete(TokenLocation::get()) });
pub const AssetHub: MultiLocation = Parachain(ASSET_HUB_ID).into_location();
pub const WndForAssetHub: (MultiAssetFilter, MultiLocation) = (Wnd::get(), AssetHub::get());
pub const Collectives: MultiLocation = Parachain(COLLECTIVES_ID).into_location();
pub const BridgeHub: MultiLocation = Parachain(BRIDGE_HUB_ID).into_location();
pub const Wnd: MultiAssetFilter = Wild(AllOf { fun: WildFungible, id: Concrete(TokenLocation::get()) });
pub const WndForAssetHub: (MultiAssetFilter, MultiLocation) = (Wnd::get(), AssetHub::get());
pub const WndForCollectives: (MultiAssetFilter, MultiLocation) = (Wnd::get(), Collectives::get());
pub const WndForBridgeHub: (MultiAssetFilter, MultiLocation) = (Wnd::get(), BridgeHub::get());
pub const MaxInstructions: u32 = 100;
pub const MaxAssetsIntoHolding: u32 = 64;
}
pub type TrustedTeleporters =
(xcm_builder::Case<WndForAssetHub>, xcm_builder::Case<WndForCollectives>);
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub ReachableDest: Option<MultiLocation> = Some(Parachain(ASSET_HUB_ID).into());
}
pub type TrustedTeleporters = (
xcm_builder::Case<WndForAssetHub>,
xcm_builder::Case<WndForCollectives>,
xcm_builder::Case<WndForBridgeHub>,
);
match_types! {
pub type OnlyParachains: impl Contains<MultiLocation> = {
@@ -174,7 +185,7 @@ impl xcm_executor::Config for XcmConfig {
type SubscriptionService = XcmPallet;
type PalletInstancesInfo = AllPalletsWithSystem;
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
type FeeManager = ();
type FeeManager = XcmFeesToAccount<Self, SystemParachains, AccountId, TreasuryAccount>;
type MessageExporter = ();
type UniversalAliases = Nothing;
type CallDispatcher = RuntimeCall;
@@ -191,11 +202,6 @@ parameter_types! {
pub const FellowshipAdminBodyId: BodyId = BodyId::Index(FELLOWSHIP_ADMIN_INDEX);
}
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub ReachableDest: Option<MultiLocation> = Some(Parachain(1000).into());
}
/// Type to convert the `GeneralAdmin` origin to a Plurality `MultiLocation` value.
pub type GeneralAdminToPlurality =
OriginToPluralityVoice<RuntimeOrigin, GeneralAdmin, GeneralAdminBodyId>;