[pallet-xcm] Adjust benchmarks (teleport_assets/reserve_transfer_assets) not relying on ED (#3464)

## Problem
During the bumping of the `polkadot-fellows` repository to
`polkadot-sdk@1.6.0`, I encountered a situation where the benchmarks
`teleport_assets` and `reserve_transfer_assets` in AssetHubKusama
started to fail. This issue arose due to a decreased ED balance for
AssetHubs introduced
[here](https://github.com/polkadot-fellows/runtimes/pull/158/files#diff-80668ff8e793b64f36a9a3ec512df5cbca4ad448c157a5d81abda1b15f35f1daR213),
and also because of a [missing CI
pipeline](https://github.com/polkadot-fellows/runtimes/issues/197) to
check the benchmarks, which went unnoticed.

These benchmarks expect the `caller` to have enough:
1. balance to transfer (BTT)
2. balance for paying delivery (BFPD).
 
So the initial balance was calculated as `ED * 100`, which seems
reasonable:
```
const ED_MULTIPLIER: u32 = 100;
let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into());`
```
The problem arises when the price for delivery is 100 times higher than
the existential deposit. In other words, when `ED * 100` does not cover
`BTT` + `BFPD`.

I check AHR/AHW/AHK/AHP and this problem has only AssetHubKusama
```
ED: 3333333
calculated price to parent delivery:  1031666634  (from xcm logs from the benchmark)
---

3333333 * 100 - BTT(3333333) - BFPD(1031666634) = −701666667
```
which results in the error;
```
2024-02-23 09:19:42 Unable to charge fee with error Module(ModuleError { index: 31, error: [17, 0, 0, 0], message: Some("FeesNotMet") })
Error: Input("Benchmark pallet_xcm::reserve_transfer_assets failed: FeesNotMet")
     
```

## Solution

The benchmarks `teleport_assets` and `reserve_transfer_assets` were
fixed by removing `ED * 100` and replacing it with `DeliveryHelper`
logic, which calculates the (almost real) price for delivery and sets it
along with the existential deposit as the initial balance for the
account used in the benchmark.


## TODO

- [ ] patch for 1.6 -
https://github.com/paritytech/polkadot-sdk/pull/3466
- [ ] patch for 1.7 -
https://github.com/paritytech/polkadot-sdk/pull/3465
- [ ] patch for 1.8 - TODO: PR

---------

Co-authored-by: Francisco Aguirre <franciscoaguirreperez@gmail.com>
This commit is contained in:
Branislav Kontur
2024-02-26 09:12:28 +01:00
committed by GitHub
parent b9c792a4b8
commit 3d9439f646
28 changed files with 329 additions and 136 deletions
Generated
+1 -2
View File
@@ -3874,6 +3874,7 @@ dependencies = [
"pallet-message-queue",
"parity-scale-codec",
"polkadot-parachain-primitives",
"polkadot-runtime-common",
"polkadot-runtime-parachains",
"rand",
"sc-client-api",
@@ -4086,7 +4087,6 @@ dependencies = [
"frame-support",
"log",
"pallet-asset-conversion",
"pallet-xcm-benchmarks",
"parity-scale-codec",
"polkadot-runtime-common",
"polkadot-runtime-parachains",
@@ -13277,7 +13277,6 @@ dependencies = [
"pallet-transaction-payment",
"pallet-treasury",
"pallet-vesting",
"pallet-xcm-benchmarks",
"parity-scale-codec",
"polkadot-primitives",
"polkadot-primitives-test-helpers",
@@ -36,6 +36,7 @@ sp-version = { path = "../../../substrate/primitives/version", default-features
# Polkadot
polkadot-parachain-primitives = { path = "../../../polkadot/parachain", default-features = false, features = ["wasm-api"] }
polkadot-runtime-parachains = { path = "../../../polkadot/runtime/parachains", default-features = false }
polkadot-runtime-common = { path = "../../../polkadot/runtime/common", default-features = false, optional = true }
xcm = { package = "staging-xcm", path = "../../../polkadot/xcm", default-features = false }
# Cumulus
@@ -79,6 +80,7 @@ std = [
"log/std",
"pallet-message-queue/std",
"polkadot-parachain-primitives/std",
"polkadot-runtime-common/std",
"polkadot-runtime-parachains/std",
"scale-info/std",
"sp-core/std",
@@ -102,6 +104,7 @@ runtime-benchmarks = [
"frame-system/runtime-benchmarks",
"pallet-message-queue/runtime-benchmarks",
"polkadot-parachain-primitives/runtime-benchmarks",
"polkadot-runtime-common/runtime-benchmarks",
"polkadot-runtime-parachains/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
]
@@ -110,6 +113,7 @@ try-runtime = [
"frame-support/try-runtime",
"frame-system/try-runtime",
"pallet-message-queue/try-runtime",
"polkadot-runtime-common?/try-runtime",
"polkadot-runtime-parachains/try-runtime",
"sp-runtime/try-runtime",
]
@@ -1610,6 +1610,15 @@ impl<T: Config> UpwardMessageSender for Pallet<T> {
}
}
#[cfg(feature = "runtime-benchmarks")]
impl<T: Config> polkadot_runtime_common::xcm_sender::EnsureForParachain for Pallet<T> {
fn ensure(para_id: ParaId) {
if let ChannelStatus::Closed = Self::get_channel_status(para_id) {
Self::open_outbound_hrmp_channel_for_benchmarks_or_tests(para_id)
}
}
}
/// Something that can check the inherents of a block.
#[cfg_attr(
feature = "parameterized-consensus-hook",
@@ -1355,8 +1355,31 @@ impl_runtime_apis! {
Config as XcmBridgeHubRouterConfig,
};
parameter_types! {
pub ExistentialDepositAsset: Option<Asset> = Some((
TokenLocation::get(),
ExistentialDeposit::get()
).into());
pub const RandomParaId: ParaId = ParaId::new(43211234);
}
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
type DeliveryHelper = (
cumulus_primitives_utility::ToParentDeliveryHelper<
xcm_config::XcmConfig,
ExistentialDepositAsset,
xcm_config::PriceForParentDelivery,
>,
polkadot_runtime_common::xcm_sender::ToParachainDeliveryHelper<
xcm_config::XcmConfig,
ExistentialDepositAsset,
PriceForSiblingParachainDelivery,
RandomParaId,
ParachainSystem,
>
);
fn reachable_dest() -> Option<Location> {
Some(Parent.into())
}
@@ -1365,7 +1388,7 @@ impl_runtime_apis! {
// Relay/native token can be teleported between AH and Relay.
Some((
Asset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
fun: Fungible(ExistentialDeposit::get()),
id: AssetId(Parent.into())
},
Parent.into(),
@@ -1373,17 +1396,13 @@ impl_runtime_apis! {
}
fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> {
// AH can reserve transfer native token to some random parachain.
let random_para_id = 43211234;
ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
random_para_id.into()
);
Some((
Asset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
fun: Fungible(ExistentialDeposit::get()),
id: AssetId(Parent.into())
},
ParentThen(Parachain(random_para_id).into()).into(),
// AH can reserve transfer native token to some random parachain.
ParentThen(Parachain(RandomParaId::get().into()).into()).into(),
))
}
@@ -1469,13 +1488,6 @@ impl_runtime_apis! {
use xcm_config::{TokenLocation, MaxAssetsIntoHolding};
use pallet_xcm_benchmarks::asset_instance_from;
parameter_types! {
pub ExistentialDepositAsset: Option<Asset> = Some((
TokenLocation::get(),
ExistentialDeposit::get()
).into());
}
impl pallet_xcm_benchmarks::Config for Runtime {
type XcmConfig = xcm_config::XcmConfig;
type AccountIdConverter = xcm_config::LocationToAccountId;
@@ -1427,8 +1427,31 @@ impl_runtime_apis! {
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
impl cumulus_pallet_session_benchmarking::Config for Runtime {}
parameter_types! {
pub ExistentialDepositAsset: Option<Asset> = Some((
WestendLocation::get(),
ExistentialDeposit::get()
).into());
pub const RandomParaId: ParaId = ParaId::new(43211234);
}
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
type DeliveryHelper = (
cumulus_primitives_utility::ToParentDeliveryHelper<
xcm_config::XcmConfig,
ExistentialDepositAsset,
xcm_config::PriceForParentDelivery,
>,
polkadot_runtime_common::xcm_sender::ToParachainDeliveryHelper<
xcm_config::XcmConfig,
ExistentialDepositAsset,
PriceForSiblingParachainDelivery,
RandomParaId,
ParachainSystem,
>
);
fn reachable_dest() -> Option<Location> {
Some(Parent.into())
}
@@ -1437,7 +1460,7 @@ impl_runtime_apis! {
// Relay/native token can be teleported between AH and Relay.
Some((
Asset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
fun: Fungible(ExistentialDeposit::get()),
id: AssetId(Parent.into())
},
Parent.into(),
@@ -1445,17 +1468,13 @@ impl_runtime_apis! {
}
fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> {
// AH can reserve transfer native token to some random parachain.
let random_para_id = 43211234;
ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
random_para_id.into()
);
Some((
Asset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
fun: Fungible(ExistentialDeposit::get()),
id: AssetId(Parent.into())
},
ParentThen(Parachain(random_para_id).into()).into(),
// AH can reserve transfer native token to some random parachain.
ParentThen(Parachain(RandomParaId::get().into()).into()).into(),
))
}
@@ -1546,13 +1565,6 @@ impl_runtime_apis! {
use xcm_config::{MaxAssetsIntoHolding, WestendLocation};
use pallet_xcm_benchmarks::asset_instance_from;
parameter_types! {
pub ExistentialDepositAsset: Option<Asset> = Some((
WestendLocation::get(),
ExistentialDeposit::get()
).into());
}
impl pallet_xcm_benchmarks::Config for Runtime {
type XcmConfig = xcm_config::XcmConfig;
type AccountIdConverter = xcm_config::LocationToAccountId;
@@ -1109,6 +1109,12 @@ impl_runtime_apis! {
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper<
xcm_config::XcmConfig,
ExistentialDepositAsset,
xcm_config::PriceForParentDelivery,
>;
fn reachable_dest() -> Option<Location> {
Some(Parent.into())
}
@@ -1117,7 +1123,7 @@ impl_runtime_apis! {
// Relay/native token can be teleported between BH and Relay.
Some((
Asset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
fun: Fungible(ExistentialDeposit::get()),
id: AssetId(Parent.into())
},
Parent.into(),
@@ -806,6 +806,12 @@ impl_runtime_apis! {
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper<
xcm_config::XcmConfig,
ExistentialDepositAsset,
xcm_config::PriceForParentDelivery,
>;
fn reachable_dest() -> Option<Location> {
Some(Parent.into())
}
@@ -814,7 +820,7 @@ impl_runtime_apis! {
// Relay/native token can be teleported between BH and Relay.
Some((
Asset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
fun: Fungible(ExistentialDeposit::get()),
id: AssetId(Parent.into())
},
Parent.into(),
@@ -986,8 +986,21 @@ impl_runtime_apis! {
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
impl cumulus_pallet_session_benchmarking::Config for Runtime {}
parameter_types! {
pub ExistentialDepositAsset: Option<Asset> = Some((
xcm_config::WndLocation::get(),
ExistentialDeposit::get()
).into());
}
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper<
xcm_config::XcmConfig,
ExistentialDepositAsset,
xcm_config::PriceForParentDelivery,
>;
fn reachable_dest() -> Option<Location> {
Some(Parent.into())
}
@@ -996,7 +1009,7 @@ impl_runtime_apis! {
// Relay/native token can be teleported between Collectives and Relay.
Some((
Asset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
fun: Fungible(ExistentialDeposit::get()),
id: AssetId(Parent.into())
}.into(),
Parent.into(),
@@ -50,7 +50,7 @@ use frame_support::{
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
parameter_types,
traits::{ConstBool, ConstU128, ConstU16, ConstU32, ConstU64, ConstU8},
traits::{ConstBool, ConstU16, ConstU32, ConstU64, ConstU8},
weights::{ConstantMultiplier, Weight},
PalletId,
};
@@ -205,6 +205,10 @@ impl pallet_authorship::Config for Runtime {
type EventHandler = (CollatorSelection,);
}
parameter_types! {
pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT;
}
impl pallet_balances::Config for Runtime {
type MaxLocks = ConstU32<50>;
/// The type for recording an account's balance.
@@ -212,7 +216,7 @@ impl pallet_balances::Config for Runtime {
/// The ubiquitous event type.
type RuntimeEvent = RuntimeEvent;
type DustRemoval = ();
type ExistentialDeposit = ConstU128<EXISTENTIAL_DEPOSIT>;
type ExistentialDeposit = ExistentialDeposit;
type AccountStore = System;
type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
type MaxReserves = ConstU32<50>;
@@ -713,9 +717,22 @@ impl_runtime_apis! {
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
impl cumulus_pallet_session_benchmarking::Config for Runtime {}
parameter_types! {
pub ExistentialDepositAsset: Option<Asset> = Some((
xcm_config::RelayLocation::get(),
ExistentialDeposit::get()
).into());
}
use xcm::latest::prelude::*;
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper<
xcm_config::XcmConfig,
ExistentialDepositAsset,
xcm_config::PriceForParentDelivery,
>;
fn reachable_dest() -> Option<Location> {
Some(Parent.into())
}
@@ -724,7 +741,7 @@ impl_runtime_apis! {
// Relay/native token can be teleported between Contracts-System-Para and Relay.
Some((
Asset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
fun: Fungible(ExistentialDeposit::get()),
id: AssetId(Parent.into())
},
Parent.into(),
@@ -715,6 +715,12 @@ impl_runtime_apis! {
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper<
xcm_config::XcmConfig,
ExistentialDepositAsset,
xcm_config::PriceForParentDelivery,
>;
fn reachable_dest() -> Option<Location> {
Some(Parent.into())
}
@@ -723,7 +729,7 @@ impl_runtime_apis! {
// Relay/native token can be teleported between AH and Relay.
Some((
Asset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
fun: Fungible(ExistentialDeposit::get()),
id: AssetId(Parent.into())
},
Parent.into(),
@@ -706,6 +706,12 @@ impl_runtime_apis! {
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper<
xcm_config::XcmConfig,
ExistentialDepositAsset,
xcm_config::PriceForParentDelivery,
>;
fn reachable_dest() -> Option<Location> {
Some(Parent.into())
}
@@ -714,7 +720,7 @@ impl_runtime_apis! {
// Relay/native token can be teleported between AH and Relay.
Some((
Asset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
fun: Fungible(ExistentialDeposit::get()),
id: AssetId(Parent.into())
},
Parent.into(),
@@ -686,6 +686,12 @@ impl_runtime_apis! {
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper<
xcm_config::XcmConfig,
ExistentialDepositAsset,
xcm_config::PriceForParentDelivery,
>;
fn reachable_dest() -> Option<Location> {
Some(Parent.into())
}
@@ -694,7 +700,7 @@ impl_runtime_apis! {
// Relay/native token can be teleported between People and Relay.
Some((
Asset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
fun: Fungible(ExistentialDeposit::get()),
id: AssetId(Parent.into())
},
Parent.into(),
@@ -686,6 +686,12 @@ impl_runtime_apis! {
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper<
xcm_config::XcmConfig,
ExistentialDepositAsset,
xcm_config::PriceForParentDelivery,
>;
fn reachable_dest() -> Option<Location> {
Some(Parent.into())
}
@@ -694,7 +700,7 @@ impl_runtime_apis! {
// Relay/native token can be teleported between People and Relay.
Some((
Asset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
fun: Fungible(ExistentialDeposit::get()),
id: AssetId(Parent.into())
},
Parent.into(),
-3
View File
@@ -26,7 +26,6 @@ polkadot-runtime-parachains = { path = "../../../polkadot/runtime/parachains", d
xcm = { package = "staging-xcm", path = "../../../polkadot/xcm", default-features = false }
xcm-executor = { package = "staging-xcm-executor", path = "../../../polkadot/xcm/xcm-executor", default-features = false }
xcm-builder = { package = "staging-xcm-builder", path = "../../../polkadot/xcm/xcm-builder", default-features = false }
pallet-xcm-benchmarks = { path = "../../../polkadot/xcm/pallet-xcm-benchmarks", default-features = false }
# Cumulus
cumulus-primitives-core = { path = "../core", default-features = false }
@@ -39,7 +38,6 @@ std = [
"frame-support/std",
"log/std",
"pallet-asset-conversion/std",
"pallet-xcm-benchmarks/std",
"polkadot-runtime-common/std",
"polkadot-runtime-parachains/std",
"sp-io/std",
@@ -54,7 +52,6 @@ runtime-benchmarks = [
"cumulus-primitives-core/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"pallet-asset-conversion/runtime-benchmarks",
"pallet-xcm-benchmarks/runtime-benchmarks",
"polkadot-runtime-common/runtime-benchmarks",
"polkadot-runtime-parachains/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
+8 -3
View File
@@ -760,7 +760,7 @@ mod test_trader {
}
}
/// Implementation of `pallet_xcm_benchmarks::EnsureDelivery` which helps to ensure delivery to the
/// Implementation of `xcm_builder::EnsureDelivery` which helps to ensure delivery to the
/// parent relay chain. 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).
@@ -774,17 +774,22 @@ impl<
XcmConfig: xcm_executor::Config,
ExistentialDeposit: Get<Option<Asset>>,
PriceForDelivery: PriceForMessageDelivery<Id = ()>,
> pallet_xcm_benchmarks::EnsureDelivery
> xcm_builder::EnsureDelivery
for ToParentDeliveryHelper<XcmConfig, ExistentialDeposit, PriceForDelivery>
{
fn ensure_successful_delivery(
origin_ref: &Location,
_dest: &Location,
dest: &Location,
fee_reason: xcm_executor::traits::FeeReason,
) -> (Option<xcm_executor::FeesMode>, Option<Assets>) {
use xcm::latest::{MAX_INSTRUCTIONS_TO_DECODE, MAX_ITEMS_IN_ASSETS};
use xcm_executor::{traits::FeeManager, FeesMode};
// check if the destination is relay/parent
if dest.ne(&Location::parent()) {
return (None, None);
}
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
-4
View File
@@ -58,8 +58,6 @@ 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]
@@ -99,7 +97,6 @@ std = [
"pallet-transaction-payment/std",
"pallet-treasury/std",
"pallet-vesting/std",
"pallet-xcm-benchmarks/std",
"parity-scale-codec/std",
"primitives/std",
"runtime-parachains/std",
@@ -137,7 +134,6 @@ 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",
+12 -3
View File
@@ -136,7 +136,7 @@ where
}
}
/// Implementation of `pallet_xcm_benchmarks::EnsureDelivery` which helps to ensure delivery to the
/// Implementation of `xcm_builder::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).
@@ -164,7 +164,7 @@ impl<
PriceForDelivery: PriceForMessageDelivery<Id = ParaId>,
Parachain: Get<ParaId>,
ToParachainHelper: EnsureForParachain,
> pallet_xcm_benchmarks::EnsureDelivery
> xcm_builder::EnsureDelivery
for ToParachainDeliveryHelper<
XcmConfig,
ExistentialDeposit,
@@ -175,7 +175,7 @@ impl<
{
fn ensure_successful_delivery(
origin_ref: &Location,
_dest: &Location,
dest: &Location,
fee_reason: xcm_executor::traits::FeeReason,
) -> (Option<xcm_executor::FeesMode>, Option<Assets>) {
use xcm_executor::{
@@ -183,6 +183,15 @@ impl<
FeesMode,
};
// check if the destination matches the expected `Parachain`.
if let Some(Parachain(para_id)) = dest.first_interior() {
if ParaId::from(*para_id) != Parachain::get().into() {
return (None, None)
}
} else {
return (None, None)
}
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
+23 -5
View File
@@ -2272,12 +2272,30 @@ sp_api::impl_runtime_apis! {
TokenLocation::get(),
ExistentialDeposit::get()
).into());
pub ToParachain: ParaId = rococo_runtime_constants::system_parachain::ASSET_HUB_ID.into();
pub AssetHubParaId: ParaId = rococo_runtime_constants::system_parachain::ASSET_HUB_ID.into();
pub const RandomParaId: ParaId = ParaId::new(43211234);
}
impl frame_system_benchmarking::Config for Runtime {}
impl frame_benchmarking::baseline::Config for Runtime {}
impl pallet_xcm::benchmarking::Config for Runtime {
type DeliveryHelper = (
runtime_common::xcm_sender::ToParachainDeliveryHelper<
XcmConfig,
ExistentialDepositAsset,
xcm_config::PriceForChildParachainDelivery,
AssetHubParaId,
(),
>,
runtime_common::xcm_sender::ToParachainDeliveryHelper<
XcmConfig,
ExistentialDepositAsset,
xcm_config::PriceForChildParachainDelivery,
RandomParaId,
(),
>
);
fn reachable_dest() -> Option<Location> {
Some(crate::xcm_config::AssetHub::get())
}
@@ -2286,7 +2304,7 @@ sp_api::impl_runtime_apis! {
// Relay/native token can be teleported to/from AH.
Some((
Asset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
fun: Fungible(ExistentialDeposit::get()),
id: AssetId(Here.into())
},
crate::xcm_config::AssetHub::get(),
@@ -2297,10 +2315,10 @@ sp_api::impl_runtime_apis! {
// Relay can reserve transfer native token to some random parachain.
Some((
Asset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
fun: Fungible(ExistentialDeposit::get()),
id: AssetId(Here.into())
},
Parachain(43211234).into(),
Parachain(RandomParaId::get().into()).into(),
))
}
@@ -2325,7 +2343,7 @@ sp_api::impl_runtime_apis! {
XcmConfig,
ExistentialDepositAsset,
xcm_config::PriceForChildParachainDelivery,
ToParachain,
AssetHubParaId,
(),
>;
fn valid_destination() -> Result<Location, BenchmarkError> {
+33 -13
View File
@@ -2344,7 +2344,36 @@ sp_api::impl_runtime_apis! {
impl pallet_session_benchmarking::Config for Runtime {}
impl pallet_offences_benchmarking::Config for Runtime {}
impl pallet_election_provider_support_benchmarking::Config for Runtime {}
use xcm_config::{AssetHub, TokenLocation};
parameter_types! {
pub ExistentialDepositAsset: Option<Asset> = Some((
TokenLocation::get(),
ExistentialDeposit::get()
).into());
pub AssetHubParaId: ParaId = westend_runtime_constants::system_parachain::ASSET_HUB_ID.into();
pub const RandomParaId: ParaId = ParaId::new(43211234);
}
impl pallet_xcm::benchmarking::Config for Runtime {
type DeliveryHelper = (
runtime_common::xcm_sender::ToParachainDeliveryHelper<
xcm_config::XcmConfig,
ExistentialDepositAsset,
xcm_config::PriceForChildParachainDelivery,
AssetHubParaId,
(),
>,
runtime_common::xcm_sender::ToParachainDeliveryHelper<
xcm_config::XcmConfig,
ExistentialDepositAsset,
xcm_config::PriceForChildParachainDelivery,
RandomParaId,
(),
>
);
fn reachable_dest() -> Option<Location> {
Some(crate::xcm_config::AssetHub::get())
}
@@ -2352,7 +2381,7 @@ sp_api::impl_runtime_apis! {
fn teleportable_asset_and_dest() -> Option<(Asset, Location)> {
// Relay/native token can be teleported to/from AH.
Some((
Asset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: AssetId(Here.into()) },
Asset { fun: Fungible(ExistentialDeposit::get()), id: AssetId(Here.into()) },
crate::xcm_config::AssetHub::get(),
))
}
@@ -2361,10 +2390,10 @@ sp_api::impl_runtime_apis! {
// Relay can reserve transfer native token to some random parachain.
Some((
Asset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
fun: Fungible(ExistentialDeposit::get()),
id: AssetId(Here.into())
},
crate::Junction::Parachain(43211234).into(),
crate::Junction::Parachain(RandomParaId::get().into()).into(),
))
}
@@ -2391,15 +2420,6 @@ sp_api::impl_runtime_apis! {
AssetId, Fungibility::*, InteriorLocation, Junction, Junctions::*,
Asset, Assets, Location, NetworkId, Response,
};
use xcm_config::{AssetHub, TokenLocation};
parameter_types! {
pub ExistentialDepositAsset: Option<Asset> = 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;
@@ -2408,7 +2428,7 @@ sp_api::impl_runtime_apis! {
xcm_config::XcmConfig,
ExistentialDepositAsset,
xcm_config::PriceForChildParachainDelivery,
ToParachain,
AssetHubParaId,
(),
>;
fn valid_destination() -> Result<Location, BenchmarkError> {
+1 -1
View File
@@ -262,7 +262,7 @@ pub type LocalPalletOriginToLocation = (
StakingAdminToPlurality,
// FellowshipAdmin origin to be used in XCM as a corresponding Plurality `Location` value.
FellowshipAdminToPlurality,
// `Treasurer` origin to be used in XCM as a corresponding Plurality `MultiLocation` value.
// `Treasurer` origin to be used in XCM as a corresponding Plurality `Location` value.
TreasurerToPlurality,
);
+2 -30
View File
@@ -22,10 +22,8 @@ use codec::Encode;
use frame_benchmarking::{account, BenchmarkError};
use sp_std::prelude::*;
use xcm::latest::prelude::*;
use xcm_executor::{
traits::{ConvertLocation, FeeReason},
Config as XcmConfig, FeesMode,
};
use xcm_builder::EnsureDelivery;
use xcm_executor::{traits::ConvertLocation, Config as XcmConfig};
pub mod fungible;
pub mod generic;
@@ -114,29 +112,3 @@ pub fn account_and_location<T: Config>(index: u32) -> (T::AccountId, Location) {
(account, location)
}
/// Trait for a type which ensures all requirements for successful delivery with XCM transport
/// layers.
pub trait EnsureDelivery {
/// Prepare all requirements for successful `XcmSender: SendXcm` passing (accounts, balances,
/// channels ...). Returns:
/// - possible `FeesMode` which is expected to be set to executor
/// - possible `Assets` which are expected to be subsume to the Holding Register
fn ensure_successful_delivery(
origin_ref: &Location,
dest: &Location,
fee_reason: FeeReason,
) -> (Option<FeesMode>, Option<Assets>);
}
/// `()` implementation does nothing which means no special requirements for environment.
impl EnsureDelivery for () {
fn ensure_successful_delivery(
_origin_ref: &Location,
_dest: &Location,
_fee_reason: FeeReason,
) -> (Option<FeesMode>, Option<Assets>) {
// doing nothing
(None, None)
}
}
+45 -28
View File
@@ -17,21 +17,26 @@
use super::*;
use bounded_collections::{ConstU32, WeakBoundedVec};
use frame_benchmarking::{benchmarks, whitelisted_caller, BenchmarkError, BenchmarkResult};
use frame_support::{traits::Currency, weights::Weight};
use frame_support::{
traits::fungible::{Inspect, Mutate},
weights::Weight,
};
use frame_system::RawOrigin;
use sp_std::prelude::*;
use xcm::{latest::prelude::*, v2};
use xcm_builder::EnsureDelivery;
use xcm_executor::traits::FeeReason;
type RuntimeOrigin<T> = <T as frame_system::Config>::RuntimeOrigin;
// existential deposit multiplier
const ED_MULTIPLIER: u32 = 100;
/// Pallet we're benchmarking here.
pub struct Pallet<T: Config>(crate::Pallet<T>);
/// Trait that must be implemented by runtime to be able to benchmark pallet properly.
pub trait Config: crate::Config {
/// Helper that ensures successful delivery for extrinsics/benchmarks which need `SendXcm`.
type DeliveryHelper: EnsureDelivery;
/// A `Location` that can be reached via `XcmRouter`. Used only in benchmarks.
///
/// If `None`, the benchmarks that depend on a reachable destination will be skipped.
@@ -107,23 +112,29 @@ benchmarks! {
}.into();
let assets: Assets = asset.into();
let existential_deposit = T::ExistentialDeposit::get();
let caller = whitelisted_caller();
// Give some multiple of the existential deposit
let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into());
assert!(balance >= transferred_amount);
let _ = <pallet_balances::Pallet<T> as Currency<_>>::make_free_balance_be(&caller, balance);
// verify initial balance
assert_eq!(pallet_balances::Pallet::<T>::free_balance(&caller), balance);
let caller: T::AccountId = whitelisted_caller();
let send_origin = RawOrigin::Signed(caller.clone());
let origin_location = T::ExecuteXcmOrigin::try_origin(send_origin.clone().into())
.map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?;
if !T::XcmTeleportFilter::contains(&(origin_location, assets.clone().into_inner())) {
if !T::XcmTeleportFilter::contains(&(origin_location.clone(), assets.clone().into_inner())) {
return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))
}
// Ensure that origin can send to destination (e.g. setup delivery fees, ensure router setup, ...)
let (_, _) = T::DeliveryHelper::ensure_successful_delivery(
&origin_location,
&destination,
FeeReason::ChargeFees,
);
// Actual balance (e.g. `ensure_successful_delivery` could drip delivery fees, ...)
let balance = <pallet_balances::Pallet<T> as Inspect<_>>::balance(&caller);
// Add transferred_amount to origin
<pallet_balances::Pallet<T> as Mutate<_>>::mint_into(&caller, transferred_amount)?;
// verify initial balance
let balance = balance + transferred_amount;
assert_eq!(<pallet_balances::Pallet<T> as Inspect<_>>::balance(&caller), balance);
let recipient = [0u8; 32];
let versioned_dest: VersionedLocation = destination.into();
let versioned_beneficiary: VersionedLocation =
@@ -132,7 +143,7 @@ benchmarks! {
}: _<RuntimeOrigin<T>>(send_origin.into(), Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0)
verify {
// verify balance after transfer, decreased by transferred amount (+ maybe XCM delivery fees)
assert!(pallet_balances::Pallet::<T>::free_balance(&caller) <= balance - transferred_amount);
assert!(<pallet_balances::Pallet<T> as Inspect<_>>::balance(&caller) <= balance - transferred_amount);
}
reserve_transfer_assets {
@@ -146,23 +157,29 @@ benchmarks! {
}.into();
let assets: Assets = asset.into();
let existential_deposit = T::ExistentialDeposit::get();
let caller = whitelisted_caller();
// Give some multiple of the existential deposit
let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into());
assert!(balance >= transferred_amount);
let _ = <pallet_balances::Pallet<T> as Currency<_>>::make_free_balance_be(&caller, balance);
// verify initial balance
assert_eq!(pallet_balances::Pallet::<T>::free_balance(&caller), balance);
let caller: T::AccountId = whitelisted_caller();
let send_origin = RawOrigin::Signed(caller.clone());
let origin_location = T::ExecuteXcmOrigin::try_origin(send_origin.clone().into())
.map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?;
if !T::XcmReserveTransferFilter::contains(&(origin_location, assets.clone().into_inner())) {
if !T::XcmReserveTransferFilter::contains(&(origin_location.clone(), assets.clone().into_inner())) {
return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))
}
// Ensure that origin can send to destination (e.g. setup delivery fees, ensure router setup, ...)
let (_, _) = T::DeliveryHelper::ensure_successful_delivery(
&origin_location,
&destination,
FeeReason::ChargeFees,
);
// Actual balance (e.g. `ensure_successful_delivery` could drip delivery fees, ...)
let balance = <pallet_balances::Pallet<T> as Inspect<_>>::balance(&caller);
// Add transferred_amount to origin
<pallet_balances::Pallet<T> as Mutate<_>>::mint_into(&caller, transferred_amount)?;
// verify initial balance
let balance = balance + transferred_amount;
assert_eq!(<pallet_balances::Pallet<T> as Inspect<_>>::balance(&caller), balance);
let recipient = [0u8; 32];
let versioned_dest: VersionedLocation = destination.into();
let versioned_beneficiary: VersionedLocation =
@@ -171,7 +188,7 @@ benchmarks! {
}: _<RuntimeOrigin<T>>(send_origin.into(), Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0)
verify {
// verify balance after transfer, decreased by transferred amount (+ maybe XCM delivery fees)
assert!(pallet_balances::Pallet::<T>::free_balance(&caller) <= balance - transferred_amount);
assert!(<pallet_balances::Pallet<T> as Inspect<_>>::balance(&caller) <= balance - transferred_amount);
}
transfer_assets {
+22
View File
@@ -563,8 +563,30 @@ impl pallet_test_notifier::Config for Test {
type RuntimeCall = RuntimeCall;
}
#[cfg(feature = "runtime-benchmarks")]
pub struct TestDeliveryHelper;
#[cfg(feature = "runtime-benchmarks")]
impl xcm_builder::EnsureDelivery for TestDeliveryHelper {
fn ensure_successful_delivery(
origin_ref: &Location,
_dest: &Location,
_fee_reason: xcm_executor::traits::FeeReason,
) -> (Option<xcm_executor::FeesMode>, Option<Assets>) {
use xcm_executor::traits::ConvertLocation;
let account = SovereignAccountOf::convert_location(origin_ref).expect("Valid location");
// Give the existential deposit at least
let balance = ExistentialDeposit::get();
let _ = <Balances as frame_support::traits::Currency<_>>::make_free_balance_be(
&account, balance,
);
(None, None)
}
}
#[cfg(feature = "runtime-benchmarks")]
impl super::benchmarking::Config for Test {
type DeliveryHelper = TestDeliveryHelper;
fn reachable_dest() -> Option<Location> {
Some(Parachain(1000).into())
}
@@ -170,7 +170,7 @@ impl<
}
fn can_check_out(_dest: &Location, what: &Asset, _context: &XcmContext) -> Result {
log::trace!(target: "xcm::currency_adapter", "check_out dest: {:?}, what: {:?}", _dest, what);
log::trace!(target: "xcm::currency_adapter", "can_check_out dest: {:?}, what: {:?}", _dest, what);
let amount = Matcher::matches_fungible(what).ok_or(Error::AssetNotHandled)?;
match CheckedAccount::get() {
Some((checked_account, MintLocation::Local)) =>
@@ -151,7 +151,7 @@ impl<
fn can_check_out(_dest: &Location, what: &Asset, _context: &XcmContext) -> XcmResult {
log::trace!(
target: "xcm::fungible_adapter",
"check_out dest: {:?}, what: {:?}",
"can_check_out dest: {:?}, what: {:?}",
_dest,
what
);
@@ -235,7 +235,7 @@ impl<
fn can_check_out(_origin: &Location, what: &Asset, _context: &XcmContext) -> XcmResult {
log::trace!(
target: "xcm::fungibles_adapter",
"can_check_in origin: {:?}, what: {:?}",
"can_check_out origin: {:?}, what: {:?}",
_origin, what
);
// Check we handle this asset.
+1 -1
View File
@@ -117,7 +117,7 @@ mod process_xcm_message;
pub use process_xcm_message::ProcessXcmMessage;
mod routing;
pub use routing::{WithTopicSource, WithUniqueTopic};
pub use routing::{EnsureDelivery, WithTopicSource, WithUniqueTopic};
mod transactional;
pub use transactional::FrameTransactionalProcessor;
+35
View File
@@ -20,6 +20,7 @@ use frame_system::unique;
use parity_scale_codec::Encode;
use sp_std::{marker::PhantomData, result::Result};
use xcm::prelude::*;
use xcm_executor::{traits::FeeReason, FeesMode};
/// Wrapper router which, if the message does not already end with a `SetTopic` instruction,
/// appends one to the message filled with a universally unique ID. This ID is returned from a
@@ -104,3 +105,37 @@ impl<Inner: SendXcm, TopicSource: SourceTopic> SendXcm for WithTopicSource<Inner
Ok(unique_id)
}
}
/// Trait for a type which ensures all requirements for successful delivery with XCM transport
/// layers.
pub trait EnsureDelivery {
/// Prepare all requirements for successful `XcmSender: SendXcm` passing (accounts, balances,
/// channels ...). Returns:
/// - possible `FeesMode` which is expected to be set to executor
/// - possible `Assets` which are expected to be subsume to the Holding Register
fn ensure_successful_delivery(
origin_ref: &Location,
dest: &Location,
fee_reason: FeeReason,
) -> (Option<FeesMode>, Option<Assets>);
}
/// Tuple implementation for `EnsureDelivery`.
#[impl_trait_for_tuples::impl_for_tuples(30)]
impl EnsureDelivery for Tuple {
fn ensure_successful_delivery(
origin_ref: &Location,
dest: &Location,
fee_reason: FeeReason,
) -> (Option<FeesMode>, Option<Assets>) {
for_tuples!( #(
// If the implementation returns something, we're done; if not, let others try.
match Tuple::ensure_successful_delivery(origin_ref, dest, fee_reason.clone()) {
r @ (Some(_), Some(_)) | r @ (Some(_), None) | r @ (None, Some(_)) => return r,
(None, None) => (),
}
)* );
// doing nothing
(None, None)
}
}