asset_hub_westend_runtime/
lib.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// SPDX-License-Identifier: Apache-2.0
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// 	http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16//! # Asset Hub Westend Runtime
17//!
18//! Testnet for Asset Hub Polkadot.
19
20#![cfg_attr(not(feature = "std"), no_std)]
21#![recursion_limit = "512"]
22
23// Make the WASM binary available.
24#[cfg(feature = "std")]
25include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
26
27mod bridge_to_ethereum_config;
28mod genesis_config_presets;
29mod weights;
30pub mod xcm_config;
31
32// Configurations for next functionality.
33mod bag_thresholds;
34pub mod governance;
35mod staking;
36use governance::{pallet_custom_origins, FellowshipAdmin, GeneralAdmin, StakingAdmin, Treasurer};
37
38extern crate alloc;
39
40use alloc::{vec, vec::Vec};
41use assets_common::{
42	local_and_foreign_assets::{LocalFromLeft, TargetFromLeft},
43	AssetIdForPoolAssets, AssetIdForPoolAssetsConvert, AssetIdForTrustBackedAssetsConvert,
44};
45use bp_asset_hub_westend::CreateForeignAssetDeposit;
46use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
47use cumulus_pallet_parachain_system::{RelayNumberMonotonicallyIncreases, RelaychainDataProvider};
48use cumulus_primitives_core::{
49	relay_chain::AccountIndex, AggregateMessageOrigin, ClaimQueueOffset, CoreSelector, ParaId,
50};
51use frame_support::{
52	construct_runtime, derive_impl,
53	dispatch::DispatchClass,
54	genesis_builder_helper::{build_state, get_preset},
55	ord_parameter_types, parameter_types,
56	traits::{
57		fungible::{self, HoldConsideration},
58		fungibles,
59		tokens::{imbalance::ResolveAssetTo, nonfungibles_v2::Inspect},
60		AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8,
61		ConstantStoragePrice, EitherOfDiverse, Equals, InstanceFilter, LinearStoragePrice, Nothing,
62		TransformOrigin, WithdrawReasons,
63	},
64	weights::{ConstantMultiplier, Weight},
65	BoundedVec, PalletId,
66};
67use frame_system::{
68	limits::{BlockLength, BlockWeights},
69	EnsureRoot, EnsureSigned, EnsureSignedBy,
70};
71use pallet_asset_conversion_tx_payment::SwapAssetAdapter;
72use pallet_assets::precompiles::{InlineIdConfig, ERC20};
73use pallet_nfts::{DestroyWitness, PalletFeatures};
74use pallet_nomination_pools::PoolId;
75use pallet_revive::evm::runtime::EthExtra;
76use pallet_xcm::{precompiles::XcmPrecompile, EnsureXcm};
77use parachains_common::{
78	impls::DealWithFees, message_queue::*, AccountId, AssetIdForTrustBackedAssets, AuraId, Balance,
79	BlockNumber, CollectionId, Hash, Header, ItemId, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO,
80	NORMAL_DISPATCH_RATIO,
81};
82use sp_api::impl_runtime_apis;
83use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
84use sp_runtime::{
85	generic, impl_opaque_keys,
86	traits::{AccountIdConversion, BlakeTwo256, Block as BlockT, ConvertInto, Saturating, Verify},
87	transaction_validity::{TransactionSource, TransactionValidity},
88	ApplyExtrinsicResult, Perbill, Permill, RuntimeDebug,
89};
90#[cfg(feature = "std")]
91use sp_version::NativeVersion;
92use sp_version::RuntimeVersion;
93use testnet_parachains_constants::westend::{
94	consensus::*, currency::*, fee::WeightToFee, snowbridge::EthereumNetwork, time::*,
95};
96use westend_runtime_constants::time::DAYS as RC_DAYS;
97use xcm_config::{
98	ForeignAssetsConvertedConcreteId, LocationToAccountId, PoolAssetsConvertedConcreteId,
99	PoolAssetsPalletLocation, TrustBackedAssetsConvertedConcreteId,
100	TrustBackedAssetsPalletLocation, WestendLocation, XcmOriginToTransactDispatchOrigin,
101};
102
103#[cfg(any(feature = "std", test))]
104pub use sp_runtime::BuildStorage;
105
106use assets_common::{
107	foreign_creators::ForeignCreators,
108	matching::{FromNetwork, FromSiblingParachain},
109};
110use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate};
111use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, InMemoryDbWeight};
112use xcm::{
113	latest::prelude::AssetId,
114	prelude::{
115		VersionedAsset, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm,
116		XcmVersion,
117	},
118};
119
120#[cfg(feature = "runtime-benchmarks")]
121use frame_support::traits::PalletInfoAccess;
122
123#[cfg(feature = "runtime-benchmarks")]
124use xcm::latest::prelude::{
125	Asset, Assets as XcmAssets, Fungible, Here, InteriorLocation, Junction, Junction::*, Location,
126	NetworkId, NonFungible, Parent, ParentThen, Response, WeightLimit, XCM_VERSION,
127};
128
129use xcm_runtime_apis::{
130	dry_run::{CallDryRunEffects, Error as XcmDryRunApiError, XcmDryRunEffects},
131	fees::Error as XcmPaymentApiError,
132};
133
134impl_opaque_keys! {
135	pub struct SessionKeys {
136		pub aura: Aura,
137	}
138}
139
140#[sp_version::runtime_version]
141pub const VERSION: RuntimeVersion = RuntimeVersion {
142	// Note: "westmint" is the legacy name for this chain. It has been renamed to
143	// "asset-hub-westend". Many wallets/tools depend on the `spec_name`, so it remains "westmint"
144	// for the time being. Wallets/tools should update to treat "asset-hub-westend" equally.
145	spec_name: alloc::borrow::Cow::Borrowed("westmint"),
146	impl_name: alloc::borrow::Cow::Borrowed("westmint"),
147	authoring_version: 1,
148	spec_version: 1_018_013,
149	impl_version: 0,
150	apis: RUNTIME_API_VERSIONS,
151	transaction_version: 16,
152	system_version: 1,
153};
154
155/// The version information used to identify this runtime when compiled natively.
156#[cfg(feature = "std")]
157pub fn native_version() -> NativeVersion {
158	NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
159}
160
161parameter_types! {
162	pub const Version: RuntimeVersion = VERSION;
163	pub RuntimeBlockLength: BlockLength =
164		BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
165	pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
166		.base_block(BlockExecutionWeight::get())
167		.for_class(DispatchClass::all(), |weights| {
168			weights.base_extrinsic = ExtrinsicBaseWeight::get();
169		})
170		.for_class(DispatchClass::Normal, |weights| {
171			weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
172		})
173		.for_class(DispatchClass::Operational, |weights| {
174			weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
175			// Operational transactions have some extra reserved space, so that they
176			// are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
177			weights.reserved = Some(
178				MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
179			);
180		})
181		.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
182		.build_or_panic();
183	pub const SS58Prefix: u8 = 42;
184}
185
186// Configure FRAME pallets to include in runtime.
187#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)]
188impl frame_system::Config for Runtime {
189	type BlockWeights = RuntimeBlockWeights;
190	type BlockLength = RuntimeBlockLength;
191	type AccountId = AccountId;
192	type Nonce = Nonce;
193	type Hash = Hash;
194	type Block = Block;
195	type BlockHashCount = BlockHashCount;
196	type DbWeight = InMemoryDbWeight;
197	type Version = Version;
198	type AccountData = pallet_balances::AccountData<Balance>;
199	type SystemWeightInfo = weights::frame_system::WeightInfo<Runtime>;
200	type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo<Runtime>;
201	type SS58Prefix = SS58Prefix;
202	type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
203	type MaxConsumers = frame_support::traits::ConstU32<16>;
204	type MultiBlockMigrator = MultiBlockMigrations;
205}
206
207impl cumulus_pallet_weight_reclaim::Config for Runtime {
208	type WeightInfo = weights::cumulus_pallet_weight_reclaim::WeightInfo<Runtime>;
209}
210
211impl pallet_timestamp::Config for Runtime {
212	/// A timestamp: milliseconds since the unix epoch.
213	type Moment = u64;
214	type OnTimestampSet = Aura;
215	type MinimumPeriod = ConstU64<0>;
216	type WeightInfo = weights::pallet_timestamp::WeightInfo<Runtime>;
217}
218
219impl pallet_authorship::Config for Runtime {
220	type FindAuthor = pallet_session::FindAccountFromAuthorIndex<Self, Aura>;
221	type EventHandler = (CollatorSelection,);
222}
223
224parameter_types! {
225	pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT;
226}
227
228impl pallet_balances::Config for Runtime {
229	type MaxLocks = ConstU32<50>;
230	/// The type for recording an account's balance.
231	type Balance = Balance;
232	/// The ubiquitous event type.
233	type RuntimeEvent = RuntimeEvent;
234	type DustRemoval = ();
235	type ExistentialDeposit = ExistentialDeposit;
236	type AccountStore = System;
237	type WeightInfo = weights::pallet_balances::WeightInfo<Runtime>;
238	type MaxReserves = ConstU32<50>;
239	type ReserveIdentifier = [u8; 8];
240	type RuntimeHoldReason = RuntimeHoldReason;
241	type RuntimeFreezeReason = RuntimeFreezeReason;
242	type FreezeIdentifier = RuntimeFreezeReason;
243	type MaxFreezes = frame_support::traits::VariantCountOf<RuntimeFreezeReason>;
244	type DoneSlashHandler = ();
245}
246
247parameter_types! {
248	/// Relay Chain `TransactionByteFee` / 10
249	pub const TransactionByteFee: Balance = MILLICENTS;
250}
251
252impl pallet_transaction_payment::Config for Runtime {
253	type RuntimeEvent = RuntimeEvent;
254	type OnChargeTransaction =
255		pallet_transaction_payment::FungibleAdapter<Balances, DealWithFees<Runtime>>;
256	type WeightToFee = WeightToFee;
257	type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
258	type FeeMultiplierUpdate = SlowAdjustingFeeUpdate<Self>;
259	type OperationalFeeMultiplier = ConstU8<5>;
260	type WeightInfo = weights::pallet_transaction_payment::WeightInfo<Runtime>;
261}
262
263parameter_types! {
264	pub const AssetDeposit: Balance = UNITS / 10; // 1 / 10 WND deposit to create asset
265	pub const AssetAccountDeposit: Balance = deposit(1, 16);
266	pub const ApprovalDeposit: Balance = EXISTENTIAL_DEPOSIT;
267	pub const AssetsStringLimit: u32 = 50;
268	/// Key = 32 bytes, Value = 36 bytes (32+1+1+1+1)
269	// https://github.com/paritytech/substrate/blob/069917b/frame/assets/src/lib.rs#L257L271
270	pub const MetadataDepositBase: Balance = deposit(1, 68);
271	pub const MetadataDepositPerByte: Balance = deposit(0, 1);
272}
273
274pub type AssetsForceOrigin = EnsureRoot<AccountId>;
275
276// Called "Trust Backed" assets because these are generally registered by some account, and users of
277// the asset assume it has some claimed backing. The pallet is called `Assets` in
278// `construct_runtime` to avoid breaking changes on storage reads.
279pub type TrustBackedAssetsInstance = pallet_assets::Instance1;
280type TrustBackedAssetsCall = pallet_assets::Call<Runtime, TrustBackedAssetsInstance>;
281impl pallet_assets::Config<TrustBackedAssetsInstance> for Runtime {
282	type RuntimeEvent = RuntimeEvent;
283	type Balance = Balance;
284	type AssetId = AssetIdForTrustBackedAssets;
285	type AssetIdParameter = codec::Compact<AssetIdForTrustBackedAssets>;
286	type Currency = Balances;
287	type CreateOrigin = AsEnsureOriginWithArg<EnsureSigned<AccountId>>;
288	type ForceOrigin = AssetsForceOrigin;
289	type AssetDeposit = AssetDeposit;
290	type MetadataDepositBase = MetadataDepositBase;
291	type MetadataDepositPerByte = MetadataDepositPerByte;
292	type ApprovalDeposit = ApprovalDeposit;
293	type StringLimit = AssetsStringLimit;
294	type Holder = ();
295	type Freezer = AssetsFreezer;
296	type Extra = ();
297	type WeightInfo = weights::pallet_assets_local::WeightInfo<Runtime>;
298	type CallbackHandle = pallet_assets::AutoIncAssetId<Runtime, TrustBackedAssetsInstance>;
299	type AssetAccountDeposit = AssetAccountDeposit;
300	type RemoveItemsLimit = ConstU32<1000>;
301	#[cfg(feature = "runtime-benchmarks")]
302	type BenchmarkHelper = ();
303}
304
305// Allow Freezes for the `Assets` pallet
306pub type AssetsFreezerInstance = pallet_assets_freezer::Instance1;
307impl pallet_assets_freezer::Config<AssetsFreezerInstance> for Runtime {
308	type RuntimeFreezeReason = RuntimeFreezeReason;
309	type RuntimeEvent = RuntimeEvent;
310}
311
312parameter_types! {
313	pub const AssetConversionPalletId: PalletId = PalletId(*b"py/ascon");
314	pub const LiquidityWithdrawalFee: Permill = Permill::from_percent(0);
315}
316
317ord_parameter_types! {
318	pub const AssetConversionOrigin: sp_runtime::AccountId32 =
319		AccountIdConversion::<sp_runtime::AccountId32>::into_account_truncating(&AssetConversionPalletId::get());
320}
321
322pub type PoolAssetsInstance = pallet_assets::Instance3;
323impl pallet_assets::Config<PoolAssetsInstance> for Runtime {
324	type RuntimeEvent = RuntimeEvent;
325	type Balance = Balance;
326	type RemoveItemsLimit = ConstU32<1000>;
327	type AssetId = u32;
328	type AssetIdParameter = u32;
329	type Currency = Balances;
330	type CreateOrigin =
331		AsEnsureOriginWithArg<EnsureSignedBy<AssetConversionOrigin, sp_runtime::AccountId32>>;
332	type ForceOrigin = AssetsForceOrigin;
333	type AssetDeposit = ConstU128<0>;
334	type AssetAccountDeposit = ConstU128<0>;
335	type MetadataDepositBase = ConstU128<0>;
336	type MetadataDepositPerByte = ConstU128<0>;
337	type ApprovalDeposit = ConstU128<0>;
338	type StringLimit = ConstU32<50>;
339	type Holder = ();
340	type Freezer = PoolAssetsFreezer;
341	type Extra = ();
342	type WeightInfo = weights::pallet_assets_pool::WeightInfo<Runtime>;
343	type CallbackHandle = ();
344	#[cfg(feature = "runtime-benchmarks")]
345	type BenchmarkHelper = ();
346}
347
348// Allow Freezes for the `PoolAssets` pallet
349pub type PoolAssetsFreezerInstance = pallet_assets_freezer::Instance3;
350impl pallet_assets_freezer::Config<PoolAssetsFreezerInstance> for Runtime {
351	type RuntimeFreezeReason = RuntimeFreezeReason;
352	type RuntimeEvent = RuntimeEvent;
353}
354
355/// Union fungibles implementation for `Assets` and `ForeignAssets`.
356pub type LocalAndForeignAssets = fungibles::UnionOf<
357	Assets,
358	ForeignAssets,
359	LocalFromLeft<
360		AssetIdForTrustBackedAssetsConvert<TrustBackedAssetsPalletLocation, xcm::v5::Location>,
361		AssetIdForTrustBackedAssets,
362		xcm::v5::Location,
363	>,
364	xcm::v5::Location,
365	AccountId,
366>;
367
368/// Union fungibles implementation for `AssetsFreezer` and `ForeignAssetsFreezer`.
369pub type LocalAndForeignAssetsFreezer = fungibles::UnionOf<
370	AssetsFreezer,
371	ForeignAssetsFreezer,
372	LocalFromLeft<
373		AssetIdForTrustBackedAssetsConvert<TrustBackedAssetsPalletLocation, xcm::v5::Location>,
374		AssetIdForTrustBackedAssets,
375		xcm::v5::Location,
376	>,
377	xcm::v5::Location,
378	AccountId,
379>;
380
381/// Union fungibles implementation for [`LocalAndForeignAssets`] and `Balances`.
382pub type NativeAndNonPoolAssets = fungible::UnionOf<
383	Balances,
384	LocalAndForeignAssets,
385	TargetFromLeft<WestendLocation, xcm::v5::Location>,
386	xcm::v5::Location,
387	AccountId,
388>;
389
390/// Union fungibles implementation for [`LocalAndForeignAssetsFreezer`] and [`Balances`].
391pub type NativeAndNonPoolAssetsFreezer = fungible::UnionOf<
392	Balances,
393	LocalAndForeignAssetsFreezer,
394	TargetFromLeft<WestendLocation, xcm::v5::Location>,
395	xcm::v5::Location,
396	AccountId,
397>;
398
399/// Union fungibles implementation for [`PoolAssets`] and [`NativeAndNonPoolAssets`].
400///
401/// NOTE: Should be kept updated to include ALL balances and assets in the runtime.
402pub type NativeAndAllAssets = fungibles::UnionOf<
403	PoolAssets,
404	NativeAndNonPoolAssets,
405	LocalFromLeft<
406		AssetIdForPoolAssetsConvert<PoolAssetsPalletLocation, xcm::v5::Location>,
407		AssetIdForPoolAssets,
408		xcm::v5::Location,
409	>,
410	xcm::v5::Location,
411	AccountId,
412>;
413
414/// Union fungibles implementation for [`PoolAssetsFreezer`] and [`NativeAndNonPoolAssetsFreezer`].
415///
416/// NOTE: Should be kept updated to include ALL balances and assets in the runtime.
417pub type NativeAndAllAssetsFreezer = fungibles::UnionOf<
418	PoolAssetsFreezer,
419	NativeAndNonPoolAssetsFreezer,
420	LocalFromLeft<
421		AssetIdForPoolAssetsConvert<PoolAssetsPalletLocation, xcm::v5::Location>,
422		AssetIdForPoolAssets,
423		xcm::v5::Location,
424	>,
425	xcm::v5::Location,
426	AccountId,
427>;
428
429pub type PoolIdToAccountId = pallet_asset_conversion::AccountIdConverter<
430	AssetConversionPalletId,
431	(xcm::v5::Location, xcm::v5::Location),
432>;
433
434impl pallet_asset_conversion::Config for Runtime {
435	type RuntimeEvent = RuntimeEvent;
436	type Balance = Balance;
437	type HigherPrecisionBalance = sp_core::U256;
438	type AssetKind = xcm::v5::Location;
439	type Assets = NativeAndNonPoolAssets;
440	type PoolId = (Self::AssetKind, Self::AssetKind);
441	type PoolLocator = pallet_asset_conversion::WithFirstAsset<
442		WestendLocation,
443		AccountId,
444		Self::AssetKind,
445		PoolIdToAccountId,
446	>;
447	type PoolAssetId = u32;
448	type PoolAssets = PoolAssets;
449	type PoolSetupFee = ConstU128<0>; // Asset class deposit fees are sufficient to prevent spam
450	type PoolSetupFeeAsset = WestendLocation;
451	type PoolSetupFeeTarget = ResolveAssetTo<AssetConversionOrigin, Self::Assets>;
452	type LiquidityWithdrawalFee = LiquidityWithdrawalFee;
453	type LPFee = ConstU32<3>;
454	type PalletId = AssetConversionPalletId;
455	type MaxSwapPathLength = ConstU32<3>;
456	type MintMinLiquidity = ConstU128<100>;
457	type WeightInfo = weights::pallet_asset_conversion::WeightInfo<Runtime>;
458	#[cfg(feature = "runtime-benchmarks")]
459	type BenchmarkHelper = assets_common::benchmarks::AssetPairFactory<
460		WestendLocation,
461		parachain_info::Pallet<Runtime>,
462		xcm_config::TrustBackedAssetsPalletIndex,
463		xcm::v5::Location,
464	>;
465}
466
467#[cfg(feature = "runtime-benchmarks")]
468pub struct PalletAssetRewardsBenchmarkHelper;
469
470#[cfg(feature = "runtime-benchmarks")]
471impl pallet_asset_rewards::benchmarking::BenchmarkHelper<xcm::v5::Location>
472	for PalletAssetRewardsBenchmarkHelper
473{
474	fn staked_asset() -> Location {
475		Location::new(
476			0,
477			[PalletInstance(<Assets as PalletInfoAccess>::index() as u8), GeneralIndex(100)],
478		)
479	}
480	fn reward_asset() -> Location {
481		Location::new(
482			0,
483			[PalletInstance(<Assets as PalletInfoAccess>::index() as u8), GeneralIndex(101)],
484		)
485	}
486}
487
488parameter_types! {
489	pub const MinVestedTransfer: Balance = 100 * CENTS;
490	pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons =
491		WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE);
492}
493
494impl pallet_vesting::Config for Runtime {
495	const MAX_VESTING_SCHEDULES: u32 = 100;
496	type BlockNumberProvider = RelaychainDataProvider<Runtime>;
497	type BlockNumberToBalance = ConvertInto;
498	type Currency = Balances;
499	type MinVestedTransfer = MinVestedTransfer;
500	type RuntimeEvent = RuntimeEvent;
501	type WeightInfo = weights::pallet_vesting::WeightInfo<Runtime>;
502	type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons;
503}
504
505parameter_types! {
506	pub const AssetRewardsPalletId: PalletId = PalletId(*b"py/astrd");
507	pub const RewardsPoolCreationHoldReason: RuntimeHoldReason =
508		RuntimeHoldReason::AssetRewards(pallet_asset_rewards::HoldReason::PoolCreation);
509	// 1 item, 135 bytes into the storage on pool creation.
510	pub const StakePoolCreationDeposit: Balance = deposit(1, 135);
511}
512
513impl pallet_asset_rewards::Config for Runtime {
514	type RuntimeEvent = RuntimeEvent;
515	type PalletId = AssetRewardsPalletId;
516	type Balance = Balance;
517	type Assets = NativeAndAllAssets;
518	type AssetsFreezer = NativeAndAllAssetsFreezer;
519	type AssetId = xcm::v5::Location;
520	type CreatePoolOrigin = EnsureSigned<AccountId>;
521	type RuntimeFreezeReason = RuntimeFreezeReason;
522	type Consideration = HoldConsideration<
523		AccountId,
524		Balances,
525		RewardsPoolCreationHoldReason,
526		ConstantStoragePrice<StakePoolCreationDeposit, Balance>,
527	>;
528	type WeightInfo = weights::pallet_asset_rewards::WeightInfo<Runtime>;
529	#[cfg(feature = "runtime-benchmarks")]
530	type BenchmarkHelper = PalletAssetRewardsBenchmarkHelper;
531}
532
533impl pallet_asset_conversion_ops::Config for Runtime {
534	type RuntimeEvent = RuntimeEvent;
535	type PriorAccountIdConverter = pallet_asset_conversion::AccountIdConverterNoSeed<
536		<Runtime as pallet_asset_conversion::Config>::PoolId,
537	>;
538	type AssetsRefund = <Runtime as pallet_asset_conversion::Config>::Assets;
539	type PoolAssetsRefund = <Runtime as pallet_asset_conversion::Config>::PoolAssets;
540	type PoolAssetsTeam = <Runtime as pallet_asset_conversion::Config>::PoolAssets;
541	type DepositAsset = Balances;
542	type WeightInfo = weights::pallet_asset_conversion_ops::WeightInfo<Runtime>;
543}
544
545parameter_types! {
546	pub const ForeignAssetsAssetDeposit: Balance = CreateForeignAssetDeposit::get();
547	pub const ForeignAssetsAssetAccountDeposit: Balance = AssetAccountDeposit::get();
548	pub const ForeignAssetsApprovalDeposit: Balance = ApprovalDeposit::get();
549	pub const ForeignAssetsAssetsStringLimit: u32 = AssetsStringLimit::get();
550	pub const ForeignAssetsMetadataDepositBase: Balance = MetadataDepositBase::get();
551	pub const ForeignAssetsMetadataDepositPerByte: Balance = MetadataDepositPerByte::get();
552}
553
554/// Assets managed by some foreign location. Note: we do not declare a `ForeignAssetsCall` type, as
555/// this type is used in proxy definitions. We assume that a foreign location would not want to set
556/// an individual, local account as a proxy for the issuance of their assets. This issuance should
557/// be managed by the foreign location's governance.
558pub type ForeignAssetsInstance = pallet_assets::Instance2;
559impl pallet_assets::Config<ForeignAssetsInstance> for Runtime {
560	type RuntimeEvent = RuntimeEvent;
561	type Balance = Balance;
562	type AssetId = xcm::v5::Location;
563	type AssetIdParameter = xcm::v5::Location;
564	type Currency = Balances;
565	type CreateOrigin = ForeignCreators<
566		(
567			FromSiblingParachain<parachain_info::Pallet<Runtime>, xcm::v5::Location>,
568			FromNetwork<xcm_config::UniversalLocation, EthereumNetwork, xcm::v5::Location>,
569			xcm_config::bridging::to_rococo::RococoAssetFromAssetHubRococo,
570		),
571		LocationToAccountId,
572		AccountId,
573		xcm::v5::Location,
574	>;
575	type ForceOrigin = AssetsForceOrigin;
576	type AssetDeposit = ForeignAssetsAssetDeposit;
577	type MetadataDepositBase = ForeignAssetsMetadataDepositBase;
578	type MetadataDepositPerByte = ForeignAssetsMetadataDepositPerByte;
579	type ApprovalDeposit = ForeignAssetsApprovalDeposit;
580	type StringLimit = ForeignAssetsAssetsStringLimit;
581	type Holder = ();
582	type Freezer = ForeignAssetsFreezer;
583	type Extra = ();
584	type WeightInfo = weights::pallet_assets_foreign::WeightInfo<Runtime>;
585	type CallbackHandle = ();
586	type AssetAccountDeposit = ForeignAssetsAssetAccountDeposit;
587	type RemoveItemsLimit = frame_support::traits::ConstU32<1000>;
588	#[cfg(feature = "runtime-benchmarks")]
589	type BenchmarkHelper = xcm_config::XcmBenchmarkHelper;
590}
591
592// Allow Freezes for the `ForeignAssets` pallet
593pub type ForeignAssetsFreezerInstance = pallet_assets_freezer::Instance2;
594impl pallet_assets_freezer::Config<ForeignAssetsFreezerInstance> for Runtime {
595	type RuntimeFreezeReason = RuntimeFreezeReason;
596	type RuntimeEvent = RuntimeEvent;
597}
598
599parameter_types! {
600	// One storage item; key size is 32; value is size 4+4+16+32 bytes = 56 bytes.
601	pub const DepositBase: Balance = deposit(1, 88);
602	// Additional storage item size of 32 bytes.
603	pub const DepositFactor: Balance = deposit(0, 32);
604	pub const MaxSignatories: u32 = 100;
605}
606
607impl pallet_multisig::Config for Runtime {
608	type RuntimeEvent = RuntimeEvent;
609	type RuntimeCall = RuntimeCall;
610	type Currency = Balances;
611	type DepositBase = DepositBase;
612	type DepositFactor = DepositFactor;
613	type MaxSignatories = MaxSignatories;
614	type WeightInfo = weights::pallet_multisig::WeightInfo<Runtime>;
615	type BlockNumberProvider = System;
616}
617
618impl pallet_utility::Config for Runtime {
619	type RuntimeEvent = RuntimeEvent;
620	type RuntimeCall = RuntimeCall;
621	type PalletsOrigin = OriginCaller;
622	type WeightInfo = weights::pallet_utility::WeightInfo<Runtime>;
623}
624
625parameter_types! {
626	// One storage item; key size 32, value size 8; .
627	pub const ProxyDepositBase: Balance = deposit(1, 40);
628	// Additional storage item size of 33 bytes.
629	pub const ProxyDepositFactor: Balance = deposit(0, 33);
630	pub const MaxProxies: u16 = 32;
631	// One storage item; key size 32, value size 16
632	pub const AnnouncementDepositBase: Balance = deposit(1, 48);
633	pub const AnnouncementDepositFactor: Balance = deposit(0, 66);
634	pub const MaxPending: u16 = 32;
635}
636
637/// The type used to represent the kinds of proxying allowed.
638#[derive(
639	Copy,
640	Clone,
641	Eq,
642	PartialEq,
643	Ord,
644	PartialOrd,
645	Encode,
646	Decode,
647	DecodeWithMemTracking,
648	RuntimeDebug,
649	MaxEncodedLen,
650	scale_info::TypeInfo,
651)]
652pub enum ProxyType {
653	/// Fully permissioned proxy. Can execute any call on behalf of _proxied_.
654	Any,
655	/// Can execute any call that does not transfer funds or assets.
656	NonTransfer,
657	/// Proxy with the ability to reject time-delay proxy announcements.
658	CancelProxy,
659	/// Assets proxy. Can execute any call from `assets`, **including asset transfers**.
660	Assets,
661	/// Owner proxy. Can execute calls related to asset ownership.
662	AssetOwner,
663	/// Asset manager. Can execute calls related to asset management.
664	AssetManager,
665	/// Collator selection proxy. Can execute calls related to collator selection mechanism.
666	Collator,
667	// New variants introduced by the Asset Hub Migration from the Relay Chain.
668	/// Allow to do governance.
669	///
670	/// Contains pallets `Treasury`, `Bounties`, `Utility`, `ChildBounties`, `ConvictionVoting`,
671	/// `Referenda` and `Whitelist`.
672	Governance,
673	/// Allows access to staking related calls.
674	///
675	/// Contains the `Staking`, `Session`, `Utility`, `FastUnstake`, `VoterList`, `NominationPools`
676	/// pallets.
677	Staking,
678	/// Allows access to nomination pools related calls.
679	///
680	/// Contains the `NominationPools` and `Utility` pallets.
681	NominationPools,
682
683	/// Placeholder variant to track the state before the Asset Hub Migration.
684	OldSudoBalances,
685	/// Placeholder variant to track the state before the Asset Hub Migration.
686	OldIdentityJudgement,
687	/// Placeholder variant to track the state before the Asset Hub Migration.
688	OldAuction,
689	/// Placeholder variant to track the state before the Asset Hub Migration.
690	OldParaRegistration,
691}
692impl Default for ProxyType {
693	fn default() -> Self {
694		Self::Any
695	}
696}
697
698impl InstanceFilter<RuntimeCall> for ProxyType {
699	fn filter(&self, c: &RuntimeCall) -> bool {
700		match self {
701			ProxyType::Any => true,
702			ProxyType::OldSudoBalances |
703			ProxyType::OldIdentityJudgement |
704			ProxyType::OldAuction |
705			ProxyType::OldParaRegistration => false,
706			ProxyType::NonTransfer => !matches!(
707				c,
708				RuntimeCall::Balances { .. } |
709					RuntimeCall::Assets { .. } |
710					RuntimeCall::NftFractionalization { .. } |
711					RuntimeCall::Nfts { .. } |
712					RuntimeCall::Uniques { .. } |
713					RuntimeCall::Scheduler(..) |
714					RuntimeCall::Treasury(..) |
715					// We allow calling `vest` and merging vesting schedules, but obviously not
716					// vested transfers.
717					RuntimeCall::Vesting(pallet_vesting::Call::vested_transfer { .. }) |
718					RuntimeCall::ConvictionVoting(..) |
719					RuntimeCall::Referenda(..) |
720					RuntimeCall::Whitelist(..)
721			),
722			ProxyType::CancelProxy => matches!(
723				c,
724				RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. }) |
725					RuntimeCall::Utility { .. } |
726					RuntimeCall::Multisig { .. }
727			),
728			ProxyType::Assets => {
729				matches!(
730					c,
731					RuntimeCall::Assets { .. } |
732						RuntimeCall::Utility { .. } |
733						RuntimeCall::Multisig { .. } |
734						RuntimeCall::NftFractionalization { .. } |
735						RuntimeCall::Nfts { .. } |
736						RuntimeCall::Uniques { .. }
737				)
738			},
739			ProxyType::AssetOwner => matches!(
740				c,
741				RuntimeCall::Assets(TrustBackedAssetsCall::create { .. }) |
742					RuntimeCall::Assets(TrustBackedAssetsCall::start_destroy { .. }) |
743					RuntimeCall::Assets(TrustBackedAssetsCall::destroy_accounts { .. }) |
744					RuntimeCall::Assets(TrustBackedAssetsCall::destroy_approvals { .. }) |
745					RuntimeCall::Assets(TrustBackedAssetsCall::finish_destroy { .. }) |
746					RuntimeCall::Assets(TrustBackedAssetsCall::transfer_ownership { .. }) |
747					RuntimeCall::Assets(TrustBackedAssetsCall::set_team { .. }) |
748					RuntimeCall::Assets(TrustBackedAssetsCall::set_metadata { .. }) |
749					RuntimeCall::Assets(TrustBackedAssetsCall::clear_metadata { .. }) |
750					RuntimeCall::Assets(TrustBackedAssetsCall::set_min_balance { .. }) |
751					RuntimeCall::Nfts(pallet_nfts::Call::create { .. }) |
752					RuntimeCall::Nfts(pallet_nfts::Call::destroy { .. }) |
753					RuntimeCall::Nfts(pallet_nfts::Call::redeposit { .. }) |
754					RuntimeCall::Nfts(pallet_nfts::Call::transfer_ownership { .. }) |
755					RuntimeCall::Nfts(pallet_nfts::Call::set_team { .. }) |
756					RuntimeCall::Nfts(pallet_nfts::Call::set_collection_max_supply { .. }) |
757					RuntimeCall::Nfts(pallet_nfts::Call::lock_collection { .. }) |
758					RuntimeCall::Uniques(pallet_uniques::Call::create { .. }) |
759					RuntimeCall::Uniques(pallet_uniques::Call::destroy { .. }) |
760					RuntimeCall::Uniques(pallet_uniques::Call::transfer_ownership { .. }) |
761					RuntimeCall::Uniques(pallet_uniques::Call::set_team { .. }) |
762					RuntimeCall::Uniques(pallet_uniques::Call::set_metadata { .. }) |
763					RuntimeCall::Uniques(pallet_uniques::Call::set_attribute { .. }) |
764					RuntimeCall::Uniques(pallet_uniques::Call::set_collection_metadata { .. }) |
765					RuntimeCall::Uniques(pallet_uniques::Call::clear_metadata { .. }) |
766					RuntimeCall::Uniques(pallet_uniques::Call::clear_attribute { .. }) |
767					RuntimeCall::Uniques(pallet_uniques::Call::clear_collection_metadata { .. }) |
768					RuntimeCall::Uniques(pallet_uniques::Call::set_collection_max_supply { .. }) |
769					RuntimeCall::Utility { .. } |
770					RuntimeCall::Multisig { .. }
771			),
772			ProxyType::AssetManager => matches!(
773				c,
774				RuntimeCall::Assets(TrustBackedAssetsCall::mint { .. }) |
775					RuntimeCall::Assets(TrustBackedAssetsCall::burn { .. }) |
776					RuntimeCall::Assets(TrustBackedAssetsCall::freeze { .. }) |
777					RuntimeCall::Assets(TrustBackedAssetsCall::block { .. }) |
778					RuntimeCall::Assets(TrustBackedAssetsCall::thaw { .. }) |
779					RuntimeCall::Assets(TrustBackedAssetsCall::freeze_asset { .. }) |
780					RuntimeCall::Assets(TrustBackedAssetsCall::thaw_asset { .. }) |
781					RuntimeCall::Assets(TrustBackedAssetsCall::touch_other { .. }) |
782					RuntimeCall::Assets(TrustBackedAssetsCall::refund_other { .. }) |
783					RuntimeCall::Nfts(pallet_nfts::Call::force_mint { .. }) |
784					RuntimeCall::Nfts(pallet_nfts::Call::update_mint_settings { .. }) |
785					RuntimeCall::Nfts(pallet_nfts::Call::mint_pre_signed { .. }) |
786					RuntimeCall::Nfts(pallet_nfts::Call::set_attributes_pre_signed { .. }) |
787					RuntimeCall::Nfts(pallet_nfts::Call::lock_item_transfer { .. }) |
788					RuntimeCall::Nfts(pallet_nfts::Call::unlock_item_transfer { .. }) |
789					RuntimeCall::Nfts(pallet_nfts::Call::lock_item_properties { .. }) |
790					RuntimeCall::Nfts(pallet_nfts::Call::set_metadata { .. }) |
791					RuntimeCall::Nfts(pallet_nfts::Call::clear_metadata { .. }) |
792					RuntimeCall::Nfts(pallet_nfts::Call::set_collection_metadata { .. }) |
793					RuntimeCall::Nfts(pallet_nfts::Call::clear_collection_metadata { .. }) |
794					RuntimeCall::Uniques(pallet_uniques::Call::mint { .. }) |
795					RuntimeCall::Uniques(pallet_uniques::Call::burn { .. }) |
796					RuntimeCall::Uniques(pallet_uniques::Call::freeze { .. }) |
797					RuntimeCall::Uniques(pallet_uniques::Call::thaw { .. }) |
798					RuntimeCall::Uniques(pallet_uniques::Call::freeze_collection { .. }) |
799					RuntimeCall::Uniques(pallet_uniques::Call::thaw_collection { .. }) |
800					RuntimeCall::Utility { .. } |
801					RuntimeCall::Multisig { .. }
802			),
803			ProxyType::Collator => matches!(
804				c,
805				RuntimeCall::CollatorSelection { .. } |
806					RuntimeCall::Utility { .. } |
807					RuntimeCall::Multisig { .. }
808			),
809			// New variants introduced by the Asset Hub Migration from the Relay Chain.
810			ProxyType::Governance => matches!(
811				c,
812				RuntimeCall::Treasury(..) |
813					RuntimeCall::Utility(..) |
814					RuntimeCall::ConvictionVoting(..) |
815					RuntimeCall::Referenda(..) |
816					RuntimeCall::Whitelist(..)
817			),
818			ProxyType::Staking => {
819				matches!(
820					c,
821					RuntimeCall::Staking(..) |
822						RuntimeCall::Session(..) |
823						RuntimeCall::Utility(..) |
824						RuntimeCall::NominationPools(..) |
825						RuntimeCall::FastUnstake(..) |
826						RuntimeCall::VoterList(..)
827				)
828			},
829			ProxyType::NominationPools => {
830				matches!(c, RuntimeCall::NominationPools(..) | RuntimeCall::Utility(..))
831			},
832		}
833	}
834
835	fn is_superset(&self, o: &Self) -> bool {
836		match (self, o) {
837			(x, y) if x == y => true,
838			(ProxyType::Any, _) => true,
839			(_, ProxyType::Any) => false,
840			(ProxyType::Assets, ProxyType::AssetOwner) => true,
841			(ProxyType::Assets, ProxyType::AssetManager) => true,
842			(
843				ProxyType::NonTransfer,
844				ProxyType::Collator |
845				ProxyType::Governance |
846				ProxyType::Staking |
847				ProxyType::NominationPools,
848			) => true,
849			_ => false,
850		}
851	}
852}
853
854impl pallet_proxy::Config for Runtime {
855	type RuntimeEvent = RuntimeEvent;
856	type RuntimeCall = RuntimeCall;
857	type Currency = Balances;
858	type ProxyType = ProxyType;
859	type ProxyDepositBase = ProxyDepositBase;
860	type ProxyDepositFactor = ProxyDepositFactor;
861	type MaxProxies = MaxProxies;
862	type WeightInfo = weights::pallet_proxy::WeightInfo<Runtime>;
863	type MaxPending = MaxPending;
864	type CallHasher = BlakeTwo256;
865	type AnnouncementDepositBase = AnnouncementDepositBase;
866	type AnnouncementDepositFactor = AnnouncementDepositFactor;
867	type BlockNumberProvider = RelaychainDataProvider<Runtime>;
868}
869
870parameter_types! {
871	pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4);
872	pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4);
873}
874
875impl cumulus_pallet_parachain_system::Config for Runtime {
876	type WeightInfo = weights::cumulus_pallet_parachain_system::WeightInfo<Runtime>;
877	type RuntimeEvent = RuntimeEvent;
878	type OnSystemEvent = ();
879	type SelfParaId = parachain_info::Pallet<Runtime>;
880	type DmpQueue = frame_support::traits::EnqueueWithOrigin<MessageQueue, RelayOrigin>;
881	type ReservedDmpWeight = ReservedDmpWeight;
882	type OutboundXcmpMessageSource = XcmpQueue;
883	type XcmpMessageHandler = XcmpQueue;
884	type ReservedXcmpWeight = ReservedXcmpWeight;
885	type CheckAssociatedRelayNumber = RelayNumberMonotonicallyIncreases;
886	type ConsensusHook = ConsensusHook;
887	type SelectCore = cumulus_pallet_parachain_system::DefaultCoreSelector<Runtime>;
888	type RelayParentOffset = ConstU32<0>;
889}
890
891type ConsensusHook = cumulus_pallet_aura_ext::FixedVelocityConsensusHook<
892	Runtime,
893	RELAY_CHAIN_SLOT_DURATION_MILLIS,
894	BLOCK_PROCESSING_VELOCITY,
895	UNINCLUDED_SEGMENT_CAPACITY,
896>;
897
898impl parachain_info::Config for Runtime {}
899
900parameter_types! {
901	pub MessageQueueServiceWeight: Weight = Perbill::from_percent(35) * RuntimeBlockWeights::get().max_block;
902}
903
904impl pallet_message_queue::Config for Runtime {
905	type RuntimeEvent = RuntimeEvent;
906	type WeightInfo = weights::pallet_message_queue::WeightInfo<Runtime>;
907	#[cfg(feature = "runtime-benchmarks")]
908	type MessageProcessor = pallet_message_queue::mock_helpers::NoopMessageProcessor<
909		cumulus_primitives_core::AggregateMessageOrigin,
910	>;
911	#[cfg(not(feature = "runtime-benchmarks"))]
912	type MessageProcessor = xcm_builder::ProcessXcmMessage<
913		AggregateMessageOrigin,
914		xcm_executor::XcmExecutor<xcm_config::XcmConfig>,
915		RuntimeCall,
916	>;
917	type Size = u32;
918	// The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin:
919	type QueueChangeHandler = NarrowOriginToSibling<XcmpQueue>;
920	type QueuePausedQuery = NarrowOriginToSibling<XcmpQueue>;
921	type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>;
922	type MaxStale = sp_core::ConstU32<8>;
923	type ServiceWeight = MessageQueueServiceWeight;
924	type IdleMaxServiceWeight = MessageQueueServiceWeight;
925}
926
927impl cumulus_pallet_aura_ext::Config for Runtime {}
928
929parameter_types! {
930	/// The asset ID for the asset that we use to pay for message delivery fees.
931	pub FeeAssetId: AssetId = AssetId(xcm_config::WestendLocation::get());
932	/// The base fee for the message delivery fees.
933	pub const BaseDeliveryFee: u128 = CENTS.saturating_mul(3);
934}
935
936pub type PriceForSiblingParachainDelivery = polkadot_runtime_common::xcm_sender::ExponentialPrice<
937	FeeAssetId,
938	BaseDeliveryFee,
939	TransactionByteFee,
940	XcmpQueue,
941>;
942
943impl cumulus_pallet_xcmp_queue::Config for Runtime {
944	type RuntimeEvent = RuntimeEvent;
945	type ChannelInfo = ParachainSystem;
946	type VersionWrapper = PolkadotXcm;
947	// Enqueue XCMP messages from siblings for later processing.
948	type XcmpQueue = TransformOrigin<MessageQueue, AggregateMessageOrigin, ParaId, ParaIdToSibling>;
949	type MaxInboundSuspended = ConstU32<1_000>;
950	type MaxActiveOutboundChannels = ConstU32<128>;
951	// Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we
952	// need to set the page size larger than that until we reduce the channel size on-chain.
953	type MaxPageSize = ConstU32<{ 103 * 1024 }>;
954	type ControllerOrigin = EnsureRoot<AccountId>;
955	type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;
956	type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo<Runtime>;
957	type PriceForSiblingDelivery = PriceForSiblingParachainDelivery;
958}
959
960impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime {
961	// This must be the same as the `ChannelInfo` from the `Config`:
962	type ChannelList = ParachainSystem;
963}
964
965parameter_types! {
966	pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent;
967}
968
969parameter_types! {
970	pub const Period: u32 = 6 * HOURS;
971	pub const Offset: u32 = 0;
972}
973
974impl pallet_session::Config for Runtime {
975	type RuntimeEvent = RuntimeEvent;
976	type ValidatorId = <Self as frame_system::Config>::AccountId;
977	// we don't have stash and controller, thus we don't need the convert as well.
978	type ValidatorIdOf = pallet_collator_selection::IdentityCollator;
979	type ShouldEndSession = pallet_session::PeriodicSessions<Period, Offset>;
980	type NextSessionRotation = pallet_session::PeriodicSessions<Period, Offset>;
981	type SessionManager = CollatorSelection;
982	// Essentially just Aura, but let's be pedantic.
983	type SessionHandler = <SessionKeys as sp_runtime::traits::OpaqueKeys>::KeyTypeIdProviders;
984	type Keys = SessionKeys;
985	type DisablingStrategy = ();
986	type WeightInfo = weights::pallet_session::WeightInfo<Runtime>;
987	type Currency = Balances;
988	type KeyDeposit = ();
989}
990
991impl pallet_aura::Config for Runtime {
992	type AuthorityId = AuraId;
993	type DisabledValidators = ();
994	type MaxAuthorities = ConstU32<100_000>;
995	type AllowMultipleBlocksPerSlot = ConstBool<true>;
996	type SlotDuration = ConstU64<SLOT_DURATION>;
997}
998
999parameter_types! {
1000	pub const PotId: PalletId = PalletId(*b"PotStake");
1001	pub const SessionLength: BlockNumber = 6 * HOURS;
1002}
1003
1004pub type CollatorSelectionUpdateOrigin = EnsureRoot<AccountId>;
1005
1006impl pallet_collator_selection::Config for Runtime {
1007	type RuntimeEvent = RuntimeEvent;
1008	type Currency = Balances;
1009	type UpdateOrigin = CollatorSelectionUpdateOrigin;
1010	type PotId = PotId;
1011	type MaxCandidates = ConstU32<100>;
1012	type MinEligibleCollators = ConstU32<4>;
1013	type MaxInvulnerables = ConstU32<20>;
1014	// should be a multiple of session or things will get inconsistent
1015	type KickThreshold = Period;
1016	type ValidatorId = <Self as frame_system::Config>::AccountId;
1017	type ValidatorIdOf = pallet_collator_selection::IdentityCollator;
1018	type ValidatorRegistration = Session;
1019	type WeightInfo = weights::pallet_collator_selection::WeightInfo<Runtime>;
1020}
1021
1022parameter_types! {
1023	pub StakingPot: AccountId = CollatorSelection::account_id();
1024}
1025
1026impl pallet_asset_conversion_tx_payment::Config for Runtime {
1027	type RuntimeEvent = RuntimeEvent;
1028	type AssetId = xcm::v5::Location;
1029	type OnChargeAssetTransaction = SwapAssetAdapter<
1030		WestendLocation,
1031		NativeAndNonPoolAssets,
1032		AssetConversion,
1033		ResolveAssetTo<StakingPot, NativeAndNonPoolAssets>,
1034	>;
1035	type WeightInfo = weights::pallet_asset_conversion_tx_payment::WeightInfo<Runtime>;
1036	#[cfg(feature = "runtime-benchmarks")]
1037	type BenchmarkHelper = AssetConversionTxHelper;
1038}
1039
1040parameter_types! {
1041	pub const UniquesCollectionDeposit: Balance = UNITS / 10; // 1 / 10 UNIT deposit to create a collection
1042	pub const UniquesItemDeposit: Balance = UNITS / 1_000; // 1 / 1000 UNIT deposit to mint an item
1043	pub const UniquesMetadataDepositBase: Balance = deposit(1, 129);
1044	pub const UniquesAttributeDepositBase: Balance = deposit(1, 0);
1045	pub const UniquesDepositPerByte: Balance = deposit(0, 1);
1046}
1047
1048impl pallet_uniques::Config for Runtime {
1049	type RuntimeEvent = RuntimeEvent;
1050	type CollectionId = CollectionId;
1051	type ItemId = ItemId;
1052	type Currency = Balances;
1053	type ForceOrigin = AssetsForceOrigin;
1054	type CollectionDeposit = UniquesCollectionDeposit;
1055	type ItemDeposit = UniquesItemDeposit;
1056	type MetadataDepositBase = UniquesMetadataDepositBase;
1057	type AttributeDepositBase = UniquesAttributeDepositBase;
1058	type DepositPerByte = UniquesDepositPerByte;
1059	type StringLimit = ConstU32<128>;
1060	type KeyLimit = ConstU32<32>;
1061	type ValueLimit = ConstU32<64>;
1062	type WeightInfo = weights::pallet_uniques::WeightInfo<Runtime>;
1063	#[cfg(feature = "runtime-benchmarks")]
1064	type Helper = ();
1065	type CreateOrigin = AsEnsureOriginWithArg<EnsureSigned<AccountId>>;
1066	type Locker = ();
1067}
1068
1069parameter_types! {
1070	pub const NftFractionalizationPalletId: PalletId = PalletId(*b"fraction");
1071	pub NewAssetSymbol: BoundedVec<u8, AssetsStringLimit> = (*b"FRAC").to_vec().try_into().unwrap();
1072	pub NewAssetName: BoundedVec<u8, AssetsStringLimit> = (*b"Frac").to_vec().try_into().unwrap();
1073}
1074
1075impl pallet_nft_fractionalization::Config for Runtime {
1076	type RuntimeEvent = RuntimeEvent;
1077	type Deposit = AssetDeposit;
1078	type Currency = Balances;
1079	type NewAssetSymbol = NewAssetSymbol;
1080	type NewAssetName = NewAssetName;
1081	type StringLimit = AssetsStringLimit;
1082	type NftCollectionId = <Self as pallet_nfts::Config>::CollectionId;
1083	type NftId = <Self as pallet_nfts::Config>::ItemId;
1084	type AssetBalance = <Self as pallet_balances::Config>::Balance;
1085	type AssetId = <Self as pallet_assets::Config<TrustBackedAssetsInstance>>::AssetId;
1086	type Assets = Assets;
1087	type Nfts = Nfts;
1088	type PalletId = NftFractionalizationPalletId;
1089	type WeightInfo = weights::pallet_nft_fractionalization::WeightInfo<Runtime>;
1090	type RuntimeHoldReason = RuntimeHoldReason;
1091	#[cfg(feature = "runtime-benchmarks")]
1092	type BenchmarkHelper = ();
1093}
1094
1095parameter_types! {
1096	pub NftsPalletFeatures: PalletFeatures = PalletFeatures::all_enabled();
1097	pub const NftsMaxDeadlineDuration: BlockNumber = 12 * 30 * DAYS;
1098	// re-use the Uniques deposits
1099	pub const NftsCollectionDeposit: Balance = UniquesCollectionDeposit::get();
1100	pub const NftsItemDeposit: Balance = UniquesItemDeposit::get();
1101	pub const NftsMetadataDepositBase: Balance = UniquesMetadataDepositBase::get();
1102	pub const NftsAttributeDepositBase: Balance = UniquesAttributeDepositBase::get();
1103	pub const NftsDepositPerByte: Balance = UniquesDepositPerByte::get();
1104}
1105
1106impl pallet_nfts::Config for Runtime {
1107	type RuntimeEvent = RuntimeEvent;
1108	type CollectionId = CollectionId;
1109	type ItemId = ItemId;
1110	type Currency = Balances;
1111	type CreateOrigin = AsEnsureOriginWithArg<EnsureSigned<AccountId>>;
1112	type ForceOrigin = AssetsForceOrigin;
1113	type Locker = ();
1114	type CollectionDeposit = NftsCollectionDeposit;
1115	type ItemDeposit = NftsItemDeposit;
1116	type MetadataDepositBase = NftsMetadataDepositBase;
1117	type AttributeDepositBase = NftsAttributeDepositBase;
1118	type DepositPerByte = NftsDepositPerByte;
1119	type StringLimit = ConstU32<256>;
1120	type KeyLimit = ConstU32<64>;
1121	type ValueLimit = ConstU32<256>;
1122	type ApprovalsLimit = ConstU32<20>;
1123	type ItemAttributesApprovalsLimit = ConstU32<30>;
1124	type MaxTips = ConstU32<10>;
1125	type MaxDeadlineDuration = NftsMaxDeadlineDuration;
1126	type MaxAttributesPerCall = ConstU32<10>;
1127	type Features = NftsPalletFeatures;
1128	type OffchainSignature = Signature;
1129	type OffchainPublic = <Signature as Verify>::Signer;
1130	type WeightInfo = weights::pallet_nfts::WeightInfo<Runtime>;
1131	#[cfg(feature = "runtime-benchmarks")]
1132	type Helper = ();
1133	// TODO migrate for async backing.
1134	type BlockNumberProvider = System;
1135}
1136
1137/// XCM router instance to BridgeHub with bridging capabilities for `Rococo` global
1138/// consensus with dynamic fees and back-pressure.
1139pub type ToRococoXcmRouterInstance = pallet_xcm_bridge_hub_router::Instance1;
1140impl pallet_xcm_bridge_hub_router::Config<ToRococoXcmRouterInstance> for Runtime {
1141	type RuntimeEvent = RuntimeEvent;
1142	type WeightInfo = weights::pallet_xcm_bridge_hub_router::WeightInfo<Runtime>;
1143
1144	type UniversalLocation = xcm_config::UniversalLocation;
1145	type SiblingBridgeHubLocation = xcm_config::bridging::SiblingBridgeHub;
1146	type BridgedNetworkId = xcm_config::bridging::to_rococo::RococoNetwork;
1147	type Bridges = xcm_config::bridging::NetworkExportTable;
1148	type DestinationVersion = PolkadotXcm;
1149
1150	type BridgeHubOrigin = frame_support::traits::EitherOfDiverse<
1151		EnsureRoot<AccountId>,
1152		EnsureXcm<Equals<Self::SiblingBridgeHubLocation>>,
1153	>;
1154	type ToBridgeHubSender = XcmpQueue;
1155	type LocalXcmChannelManager =
1156		cumulus_pallet_xcmp_queue::bridging::InAndOutXcmpChannelStatusProvider<Runtime>;
1157
1158	type ByteFee = xcm_config::bridging::XcmBridgeHubRouterByteFee;
1159	type FeeAsset = xcm_config::bridging::XcmBridgeHubRouterFeeAssetId;
1160}
1161
1162parameter_types! {
1163	pub const DepositPerItem: Balance = deposit(1, 0);
1164	pub const DepositPerByte: Balance = deposit(0, 1);
1165	pub CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(30);
1166}
1167
1168impl pallet_revive::Config for Runtime {
1169	type Time = Timestamp;
1170	type Currency = Balances;
1171	type RuntimeEvent = RuntimeEvent;
1172	type RuntimeCall = RuntimeCall;
1173	type DepositPerItem = DepositPerItem;
1174	type DepositPerByte = DepositPerByte;
1175	type WeightPrice = pallet_transaction_payment::Pallet<Self>;
1176	type WeightInfo = pallet_revive::weights::SubstrateWeight<Self>;
1177	type Precompiles = (
1178		ERC20<Self, InlineIdConfig<0x120>, TrustBackedAssetsInstance>,
1179		ERC20<Self, InlineIdConfig<0x320>, PoolAssetsInstance>,
1180		XcmPrecompile<Self>,
1181	);
1182	type AddressMapper = pallet_revive::AccountId32Mapper<Self>;
1183	type RuntimeMemory = ConstU32<{ 128 * 1024 * 1024 }>;
1184	type PVFMemory = ConstU32<{ 512 * 1024 * 1024 }>;
1185	type UnsafeUnstableInterface = ConstBool<false>;
1186	type UploadOrigin = EnsureSigned<Self::AccountId>;
1187	type InstantiateOrigin = EnsureSigned<Self::AccountId>;
1188	type RuntimeHoldReason = RuntimeHoldReason;
1189	type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent;
1190	type ChainId = ConstU64<420_420_421>;
1191	type NativeToEthRatio = ConstU32<1_000_000>; // 10^(18 - 12) Eth is 10^18, Native is 10^12.
1192	type EthGasEncoder = ();
1193	type FindAuthor = <Runtime as pallet_authorship::Config>::FindAuthor;
1194}
1195
1196parameter_types! {
1197	pub MbmServiceWeight: Weight = Perbill::from_percent(80) * RuntimeBlockWeights::get().max_block;
1198}
1199
1200impl pallet_migrations::Config for Runtime {
1201	type RuntimeEvent = RuntimeEvent;
1202	#[cfg(not(feature = "runtime-benchmarks"))]
1203	type Migrations = pallet_revive::migrations::v1::Migration<Runtime>;
1204	// Benchmarks need mocked migrations to guarantee that they succeed.
1205	#[cfg(feature = "runtime-benchmarks")]
1206	type Migrations = pallet_migrations::mock_helpers::MockedMigrations;
1207	type CursorMaxLen = ConstU32<65_536>;
1208	type IdentifierMaxLen = ConstU32<256>;
1209	type MigrationStatusHandler = ();
1210	type FailedMigrationHandler = frame_support::migrations::FreezeChainOnFailedMigration;
1211	type MaxServiceWeight = MbmServiceWeight;
1212	type WeightInfo = weights::pallet_migrations::WeightInfo<Runtime>;
1213}
1214
1215parameter_types! {
1216	pub MaximumSchedulerWeight: frame_support::weights::Weight = Perbill::from_percent(80) *
1217		RuntimeBlockWeights::get().max_block;
1218}
1219
1220impl pallet_scheduler::Config for Runtime {
1221	type RuntimeOrigin = RuntimeOrigin;
1222	type RuntimeEvent = RuntimeEvent;
1223	type PalletsOrigin = OriginCaller;
1224	type RuntimeCall = RuntimeCall;
1225	type MaximumWeight = MaximumSchedulerWeight;
1226	type ScheduleOrigin = EnsureRoot<AccountId>;
1227	#[cfg(feature = "runtime-benchmarks")]
1228	type MaxScheduledPerBlock = ConstU32<{ 512 * 15 }>; // MaxVotes * TRACKS_DATA length
1229	#[cfg(not(feature = "runtime-benchmarks"))]
1230	type MaxScheduledPerBlock = ConstU32<50>;
1231	type WeightInfo = weights::pallet_scheduler::WeightInfo<Runtime>;
1232	type OriginPrivilegeCmp = frame_support::traits::EqualPrivilegeOnly;
1233	type Preimages = Preimage;
1234	type BlockNumberProvider = RelaychainDataProvider<Runtime>;
1235}
1236
1237parameter_types! {
1238	pub const PreimageBaseDeposit: Balance = deposit(2, 64);
1239	pub const PreimageByteDeposit: Balance = deposit(0, 1);
1240	pub const PreimageHoldReason: RuntimeHoldReason = RuntimeHoldReason::Preimage(pallet_preimage::HoldReason::Preimage);
1241}
1242
1243impl pallet_preimage::Config for Runtime {
1244	type WeightInfo = weights::pallet_preimage::WeightInfo<Runtime>;
1245	type RuntimeEvent = RuntimeEvent;
1246	type Currency = Balances;
1247	type ManagerOrigin = EnsureRoot<AccountId>;
1248	type Consideration = HoldConsideration<
1249		AccountId,
1250		Balances,
1251		PreimageHoldReason,
1252		LinearStoragePrice<PreimageBaseDeposit, PreimageByteDeposit, Balance>,
1253	>;
1254}
1255
1256parameter_types! {
1257	/// Deposit for an index in the indices pallet.
1258	///
1259	/// 32 bytes for the account ID and 16 for the deposit. We cannot use `max_encoded_len` since it
1260	/// is not const.
1261	pub const IndexDeposit: Balance = deposit(1, 32 + 16);
1262}
1263
1264impl pallet_indices::Config for Runtime {
1265	type AccountIndex = AccountIndex;
1266	type Currency = Balances;
1267	type Deposit = IndexDeposit;
1268	type RuntimeEvent = RuntimeEvent;
1269	type WeightInfo = weights::pallet_indices::WeightInfo<Runtime>;
1270}
1271
1272impl pallet_ah_ops::Config for Runtime {
1273	type Currency = Balances;
1274	type RcBlockNumberProvider = RelaychainDataProvider<Runtime>;
1275	type WeightInfo = weights::pallet_ah_ops::WeightInfo<Runtime>;
1276}
1277
1278impl pallet_sudo::Config for Runtime {
1279	type RuntimeEvent = RuntimeEvent;
1280	type RuntimeCall = RuntimeCall;
1281	type WeightInfo = weights::pallet_sudo::WeightInfo<Runtime>;
1282}
1283
1284// Create the runtime by composing the FRAME pallets that were previously configured.
1285construct_runtime!(
1286	pub enum Runtime
1287	{
1288		// System support stuff.
1289		System: frame_system = 0,
1290		ParachainSystem: cumulus_pallet_parachain_system = 1,
1291		// RandomnessCollectiveFlip = 2 removed
1292		Timestamp: pallet_timestamp = 3,
1293		ParachainInfo: parachain_info = 4,
1294		WeightReclaim: cumulus_pallet_weight_reclaim = 5,
1295		MultiBlockMigrations: pallet_migrations = 6,
1296		Preimage: pallet_preimage = 7,
1297		Scheduler: pallet_scheduler = 8,
1298		Sudo: pallet_sudo = 9,
1299
1300		// Monetary stuff.
1301		Balances: pallet_balances = 10,
1302		TransactionPayment: pallet_transaction_payment = 11,
1303		// AssetTxPayment: pallet_asset_tx_payment = 12,
1304		AssetTxPayment: pallet_asset_conversion_tx_payment = 13,
1305		Vesting: pallet_vesting = 14,
1306
1307		// Collator support. the order of these 5 are important and shall not change.
1308		Authorship: pallet_authorship = 20,
1309		CollatorSelection: pallet_collator_selection = 21,
1310		Session: pallet_session = 22,
1311		Aura: pallet_aura = 23,
1312		AuraExt: cumulus_pallet_aura_ext = 24,
1313
1314		// XCM helpers.
1315		XcmpQueue: cumulus_pallet_xcmp_queue = 30,
1316		PolkadotXcm: pallet_xcm = 31,
1317		CumulusXcm: cumulus_pallet_xcm = 32,
1318		// Bridge utilities.
1319		ToRococoXcmRouter: pallet_xcm_bridge_hub_router::<Instance1> = 34,
1320		MessageQueue: pallet_message_queue = 35,
1321		// Snowbridge
1322		SnowbridgeSystemFrontend: snowbridge_pallet_system_frontend = 36,
1323
1324		// Handy utilities.
1325		Utility: pallet_utility = 40,
1326		Multisig: pallet_multisig = 41,
1327		Proxy: pallet_proxy = 42,
1328		Indices: pallet_indices = 43,
1329
1330		// The main stage.
1331		Assets: pallet_assets::<Instance1> = 50,
1332		Uniques: pallet_uniques = 51,
1333		Nfts: pallet_nfts = 52,
1334		ForeignAssets: pallet_assets::<Instance2> = 53,
1335		NftFractionalization: pallet_nft_fractionalization = 54,
1336		PoolAssets: pallet_assets::<Instance3> = 55,
1337		AssetConversion: pallet_asset_conversion = 56,
1338
1339		AssetsFreezer: pallet_assets_freezer::<Instance1> = 57,
1340		ForeignAssetsFreezer: pallet_assets_freezer::<Instance2> = 58,
1341		PoolAssetsFreezer: pallet_assets_freezer::<Instance3> = 59,
1342		Revive: pallet_revive = 60,
1343
1344		AssetRewards: pallet_asset_rewards = 61,
1345
1346		StateTrieMigration: pallet_state_trie_migration = 70,
1347
1348		// Staking.
1349		Staking: pallet_staking_async = 80,
1350		NominationPools: pallet_nomination_pools = 81,
1351		FastUnstake: pallet_fast_unstake = 82,
1352		VoterList: pallet_bags_list::<Instance1> = 83,
1353		DelegatedStaking: pallet_delegated_staking = 84,
1354		StakingRcClient: pallet_staking_async_rc_client = 89,
1355
1356		// Staking election apparatus.
1357		MultiBlockElection: pallet_election_provider_multi_block = 85,
1358		MultiBlockElectionVerifier: pallet_election_provider_multi_block::verifier = 86,
1359		MultiBlockElectionUnsigned: pallet_election_provider_multi_block::unsigned = 87,
1360		MultiBlockElectionSigned: pallet_election_provider_multi_block::signed = 88,
1361
1362		// Governance.
1363		ConvictionVoting: pallet_conviction_voting = 90,
1364		Referenda: pallet_referenda = 91,
1365		Origins: pallet_custom_origins = 92,
1366		Whitelist: pallet_whitelist = 93,
1367		Treasury: pallet_treasury = 94,
1368		AssetRate: pallet_asset_rate = 95,
1369
1370		// TODO: the pallet instance should be removed once all pools have migrated
1371		// to the new account IDs.
1372		AssetConversionMigration: pallet_asset_conversion_ops = 200,
1373
1374		AhOps: pallet_ah_ops = 254,
1375	}
1376);
1377
1378/// The address format for describing accounts.
1379pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
1380/// Block type as expected by this runtime.
1381pub type Block = generic::Block<Header, UncheckedExtrinsic>;
1382/// A Block signed with a Justification
1383pub type SignedBlock = generic::SignedBlock<Block>;
1384/// BlockId type as expected by this runtime.
1385pub type BlockId = generic::BlockId<Block>;
1386/// The extension to the basic transaction logic.
1387pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
1388	Runtime,
1389	(
1390		frame_system::AuthorizeCall<Runtime>,
1391		frame_system::CheckNonZeroSender<Runtime>,
1392		frame_system::CheckSpecVersion<Runtime>,
1393		frame_system::CheckTxVersion<Runtime>,
1394		frame_system::CheckGenesis<Runtime>,
1395		frame_system::CheckEra<Runtime>,
1396		frame_system::CheckNonce<Runtime>,
1397		frame_system::CheckWeight<Runtime>,
1398		pallet_asset_conversion_tx_payment::ChargeAssetTxPayment<Runtime>,
1399		frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
1400	),
1401>;
1402
1403/// Default extensions applied to Ethereum transactions.
1404#[derive(Clone, PartialEq, Eq, Debug)]
1405pub struct EthExtraImpl;
1406
1407impl EthExtra for EthExtraImpl {
1408	type Config = Runtime;
1409	type Extension = TxExtension;
1410
1411	fn get_eth_extension(nonce: u32, tip: Balance) -> Self::Extension {
1412		(
1413			frame_system::AuthorizeCall::<Runtime>::new(),
1414			frame_system::CheckNonZeroSender::<Runtime>::new(),
1415			frame_system::CheckSpecVersion::<Runtime>::new(),
1416			frame_system::CheckTxVersion::<Runtime>::new(),
1417			frame_system::CheckGenesis::<Runtime>::new(),
1418			frame_system::CheckMortality::from(generic::Era::Immortal),
1419			frame_system::CheckNonce::<Runtime>::from(nonce),
1420			frame_system::CheckWeight::<Runtime>::new(),
1421			pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::<Runtime>::from(tip, None),
1422			frame_metadata_hash_extension::CheckMetadataHash::<Runtime>::new(false),
1423		)
1424			.into()
1425	}
1426}
1427
1428/// Unchecked extrinsic type as expected by this runtime.
1429pub type UncheckedExtrinsic =
1430	pallet_revive::evm::runtime::UncheckedExtrinsic<Address, Signature, EthExtraImpl>;
1431
1432/// Migrations to apply on runtime upgrade.
1433pub type Migrations = (
1434	// v9420
1435	pallet_nfts::migration::v1::MigrateToV1<Runtime>,
1436	// unreleased
1437	pallet_collator_selection::migration::v2::MigrationToV2<Runtime>,
1438	// unreleased
1439	pallet_multisig::migrations::v1::MigrateToV1<Runtime>,
1440	// unreleased
1441	InitStorageVersions,
1442	// unreleased
1443	DeleteUndecodableStorage,
1444	// unreleased
1445	cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4<Runtime>,
1446	cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5<Runtime>,
1447	// unreleased
1448	pallet_assets::migration::next_asset_id::SetNextAssetId<
1449		ConstU32<50_000_000>,
1450		Runtime,
1451		TrustBackedAssetsInstance,
1452	>,
1453	pallet_session::migrations::v1::MigrateV0ToV1<
1454		Runtime,
1455		pallet_session::migrations::v1::InitOffenceSeverity<Runtime>,
1456	>,
1457	// permanent
1458	pallet_xcm::migration::MigrateToLatestXcmVersion<Runtime>,
1459	cumulus_pallet_aura_ext::migration::MigrateV0ToV1<Runtime>,
1460);
1461
1462/// Asset Hub Westend has some undecodable storage, delete it.
1463/// See <https://github.com/paritytech/polkadot-sdk/issues/2241> for more info.
1464///
1465/// First we remove the bad Hold, then the bad NFT collection.
1466pub struct DeleteUndecodableStorage;
1467
1468impl frame_support::traits::OnRuntimeUpgrade for DeleteUndecodableStorage {
1469	fn on_runtime_upgrade() -> Weight {
1470		use sp_core::crypto::Ss58Codec;
1471
1472		let mut writes = 0;
1473
1474		// Remove Holds for account with undecodable hold
1475		// Westend doesn't have any HoldReasons implemented yet, so it's safe to just blanket remove
1476		// any for this account.
1477		match AccountId::from_ss58check("5GCCJthVSwNXRpbeg44gysJUx9vzjdGdfWhioeM7gCg6VyXf") {
1478			Ok(a) => {
1479				log::info!("Removing holds for account with bad hold");
1480				pallet_balances::Holds::<Runtime, ()>::remove(a);
1481				writes.saturating_inc();
1482			},
1483			Err(_) => {
1484				log::error!("CleanupUndecodableStorage: Somehow failed to convert valid SS58 address into an AccountId!");
1485			},
1486		};
1487
1488		// Destroy undecodable NFT item 1
1489		writes.saturating_inc();
1490		match pallet_nfts::Pallet::<Runtime, ()>::do_burn(3, 1, |_| Ok(())) {
1491			Ok(_) => {
1492				log::info!("Destroyed undecodable NFT item 1");
1493			},
1494			Err(e) => {
1495				log::error!("Failed to destroy undecodable NFT item: {:?}", e);
1496				return <Runtime as frame_system::Config>::DbWeight::get().reads_writes(0, writes);
1497			},
1498		}
1499
1500		// Destroy undecodable NFT item 2
1501		writes.saturating_inc();
1502		match pallet_nfts::Pallet::<Runtime, ()>::do_burn(3, 2, |_| Ok(())) {
1503			Ok(_) => {
1504				log::info!("Destroyed undecodable NFT item 2");
1505			},
1506			Err(e) => {
1507				log::error!("Failed to destroy undecodable NFT item: {:?}", e);
1508				return <Runtime as frame_system::Config>::DbWeight::get().reads_writes(0, writes);
1509			},
1510		}
1511
1512		// Finally, we can destroy the collection
1513		writes.saturating_inc();
1514		match pallet_nfts::Pallet::<Runtime, ()>::do_destroy_collection(
1515			3,
1516			DestroyWitness { attributes: 0, item_metadatas: 1, item_configs: 0 },
1517			None,
1518		) {
1519			Ok(_) => {
1520				log::info!("Destroyed undecodable NFT collection");
1521			},
1522			Err(e) => {
1523				log::error!("Failed to destroy undecodable NFT collection: {:?}", e);
1524			},
1525		};
1526
1527		<Runtime as frame_system::Config>::DbWeight::get().reads_writes(0, writes)
1528	}
1529}
1530
1531/// Migration to initialize storage versions for pallets added after genesis.
1532///
1533/// Ideally this would be done automatically (see
1534/// <https://github.com/paritytech/polkadot-sdk/pull/1297>), but it probably won't be ready for some
1535/// time and it's beneficial to get try-runtime-cli on-runtime-upgrade checks into the CI, so we're
1536/// doing it manually.
1537pub struct InitStorageVersions;
1538
1539impl frame_support::traits::OnRuntimeUpgrade for InitStorageVersions {
1540	fn on_runtime_upgrade() -> Weight {
1541		use frame_support::traits::{GetStorageVersion, StorageVersion};
1542
1543		let mut writes = 0;
1544
1545		if PolkadotXcm::on_chain_storage_version() == StorageVersion::new(0) {
1546			PolkadotXcm::in_code_storage_version().put::<PolkadotXcm>();
1547			writes.saturating_inc();
1548		}
1549
1550		if ForeignAssets::on_chain_storage_version() == StorageVersion::new(0) {
1551			ForeignAssets::in_code_storage_version().put::<ForeignAssets>();
1552			writes.saturating_inc();
1553		}
1554
1555		if PoolAssets::on_chain_storage_version() == StorageVersion::new(0) {
1556			PoolAssets::in_code_storage_version().put::<PoolAssets>();
1557			writes.saturating_inc();
1558		}
1559
1560		<Runtime as frame_system::Config>::DbWeight::get().reads_writes(3, writes)
1561	}
1562}
1563
1564/// Executive: handles dispatch to the various modules.
1565pub type Executive = frame_executive::Executive<
1566	Runtime,
1567	Block,
1568	frame_system::ChainContext<Runtime>,
1569	Runtime,
1570	AllPalletsWithSystem,
1571	Migrations,
1572>;
1573
1574#[cfg(feature = "runtime-benchmarks")]
1575pub struct AssetConversionTxHelper;
1576
1577#[cfg(feature = "runtime-benchmarks")]
1578impl
1579	pallet_asset_conversion_tx_payment::BenchmarkHelperTrait<
1580		AccountId,
1581		cumulus_primitives_core::Location,
1582		cumulus_primitives_core::Location,
1583	> for AssetConversionTxHelper
1584{
1585	fn create_asset_id_parameter(
1586		seed: u32,
1587	) -> (cumulus_primitives_core::Location, cumulus_primitives_core::Location) {
1588		// Use a different parachain' foreign assets pallet so that the asset is indeed foreign.
1589		let asset_id = cumulus_primitives_core::Location::new(
1590			1,
1591			[
1592				cumulus_primitives_core::Junction::Parachain(3000),
1593				cumulus_primitives_core::Junction::PalletInstance(53),
1594				cumulus_primitives_core::Junction::GeneralIndex(seed.into()),
1595			],
1596		);
1597		(asset_id.clone(), asset_id)
1598	}
1599
1600	fn setup_balances_and_pool(asset_id: cumulus_primitives_core::Location, account: AccountId) {
1601		use frame_support::{assert_ok, traits::fungibles::Mutate};
1602		assert_ok!(ForeignAssets::force_create(
1603			RuntimeOrigin::root(),
1604			asset_id.clone().into(),
1605			account.clone().into(), /* owner */
1606			true,                   /* is_sufficient */
1607			1,
1608		));
1609
1610		let lp_provider = account.clone();
1611		use frame_support::traits::Currency;
1612		let _ = Balances::deposit_creating(&lp_provider, u64::MAX.into());
1613		assert_ok!(ForeignAssets::mint_into(
1614			asset_id.clone().into(),
1615			&lp_provider,
1616			u64::MAX.into()
1617		));
1618
1619		let token_native = alloc::boxed::Box::new(cumulus_primitives_core::Location::new(
1620			1,
1621			cumulus_primitives_core::Junctions::Here,
1622		));
1623		let token_second = alloc::boxed::Box::new(asset_id);
1624
1625		assert_ok!(AssetConversion::create_pool(
1626			RuntimeOrigin::signed(lp_provider.clone()),
1627			token_native.clone(),
1628			token_second.clone()
1629		));
1630
1631		assert_ok!(AssetConversion::add_liquidity(
1632			RuntimeOrigin::signed(lp_provider.clone()),
1633			token_native,
1634			token_second,
1635			(u32::MAX / 2).into(), // 1 desired
1636			u32::MAX.into(),       // 2 desired
1637			1,                     // 1 min
1638			1,                     // 2 min
1639			lp_provider,
1640		));
1641	}
1642}
1643
1644#[cfg(feature = "runtime-benchmarks")]
1645mod benches {
1646	frame_benchmarking::define_benchmarks!(
1647		[frame_system, SystemBench::<Runtime>]
1648		[frame_system_extensions, SystemExtensionsBench::<Runtime>]
1649		[pallet_asset_conversion_ops, AssetConversionMigration]
1650		[pallet_asset_rate, AssetRate]
1651		[pallet_assets, Local]
1652		[pallet_assets, Foreign]
1653		[pallet_assets, Pool]
1654		[pallet_asset_conversion, AssetConversion]
1655		[pallet_asset_rewards, AssetRewards]
1656		[pallet_asset_conversion_tx_payment, AssetTxPayment]
1657		[pallet_bags_list, VoterList]
1658		[pallet_balances, Balances]
1659		[pallet_conviction_voting, ConvictionVoting]
1660		// Temporarily disabled due to https://github.com/paritytech/polkadot-sdk/issues/7714
1661		// [pallet_election_provider_multi_block, MultiBlockElection]
1662		// [pallet_election_provider_multi_block_verifier, MultiBlockElectionVerifier]
1663		[pallet_election_provider_multi_block_unsigned, MultiBlockElectionUnsigned]
1664		[pallet_election_provider_multi_block_signed, MultiBlockElectionSigned]
1665		[pallet_fast_unstake, FastUnstake]
1666		[pallet_message_queue, MessageQueue]
1667		[pallet_migrations, MultiBlockMigrations]
1668		[pallet_multisig, Multisig]
1669		[pallet_nft_fractionalization, NftFractionalization]
1670		[pallet_nfts, Nfts]
1671		[pallet_proxy, Proxy]
1672		[pallet_session, SessionBench::<Runtime>]
1673		[pallet_staking_async, Staking]
1674		[pallet_uniques, Uniques]
1675		[pallet_utility, Utility]
1676		[pallet_timestamp, Timestamp]
1677		[pallet_transaction_payment, TransactionPayment]
1678		[pallet_collator_selection, CollatorSelection]
1679		[cumulus_pallet_parachain_system, ParachainSystem]
1680		[cumulus_pallet_xcmp_queue, XcmpQueue]
1681		[pallet_treasury, Treasury]
1682		[pallet_vesting, Vesting]
1683		[pallet_whitelist, Whitelist]
1684		[pallet_xcm_bridge_hub_router, ToRococo]
1685		[pallet_asset_conversion_ops, AssetConversionMigration]
1686		[pallet_revive, Revive]
1687		// XCM
1688		[pallet_xcm, PalletXcmExtrinsicsBenchmark::<Runtime>]
1689		// NOTE: Make sure you point to the individual modules below.
1690		[pallet_xcm_benchmarks::fungible, XcmBalances]
1691		[pallet_xcm_benchmarks::generic, XcmGeneric]
1692		[cumulus_pallet_weight_reclaim, WeightReclaim]
1693		[snowbridge_pallet_system_frontend, SnowbridgeSystemFrontend]
1694	);
1695}
1696
1697pallet_revive::impl_runtime_apis_plus_revive!(
1698	Runtime,
1699	Executive,
1700	EthExtraImpl,
1701
1702	impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
1703		fn slot_duration() -> sp_consensus_aura::SlotDuration {
1704			sp_consensus_aura::SlotDuration::from_millis(SLOT_DURATION)
1705		}
1706
1707		fn authorities() -> Vec<AuraId> {
1708			pallet_aura::Authorities::<Runtime>::get().into_inner()
1709		}
1710	}
1711
1712	impl cumulus_primitives_core::RelayParentOffsetApi<Block> for Runtime {
1713		fn relay_parent_offset() -> u32 {
1714			0
1715		}
1716	}
1717
1718	impl cumulus_primitives_aura::AuraUnincludedSegmentApi<Block> for Runtime {
1719		fn can_build_upon(
1720			included_hash: <Block as BlockT>::Hash,
1721			slot: cumulus_primitives_aura::Slot,
1722		) -> bool {
1723			ConsensusHook::can_build_upon(included_hash, slot)
1724		}
1725	}
1726
1727	impl sp_api::Core<Block> for Runtime {
1728		fn version() -> RuntimeVersion {
1729			VERSION
1730		}
1731
1732		fn execute_block(block: Block) {
1733			Executive::execute_block(block)
1734		}
1735
1736		fn initialize_block(header: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
1737			Executive::initialize_block(header)
1738		}
1739	}
1740
1741	impl sp_api::Metadata<Block> for Runtime {
1742		fn metadata() -> OpaqueMetadata {
1743			OpaqueMetadata::new(Runtime::metadata().into())
1744		}
1745
1746		fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
1747			Runtime::metadata_at_version(version)
1748		}
1749
1750		fn metadata_versions() -> alloc::vec::Vec<u32> {
1751			Runtime::metadata_versions()
1752		}
1753	}
1754
1755	impl sp_block_builder::BlockBuilder<Block> for Runtime {
1756		fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
1757			Executive::apply_extrinsic(extrinsic)
1758		}
1759
1760		fn finalize_block() -> <Block as BlockT>::Header {
1761			Executive::finalize_block()
1762		}
1763
1764		fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
1765			data.create_extrinsics()
1766		}
1767
1768		fn check_inherents(
1769			block: Block,
1770			data: sp_inherents::InherentData,
1771		) -> sp_inherents::CheckInherentsResult {
1772			data.check_extrinsics(&block)
1773		}
1774	}
1775
1776	impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
1777		fn validate_transaction(
1778			source: TransactionSource,
1779			tx: <Block as BlockT>::Extrinsic,
1780			block_hash: <Block as BlockT>::Hash,
1781		) -> TransactionValidity {
1782			Executive::validate_transaction(source, tx, block_hash)
1783		}
1784	}
1785
1786	impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
1787		fn offchain_worker(header: &<Block as BlockT>::Header) {
1788			Executive::offchain_worker(header)
1789		}
1790	}
1791
1792	impl sp_session::SessionKeys<Block> for Runtime {
1793		fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
1794			SessionKeys::generate(seed)
1795		}
1796
1797		fn decode_session_keys(
1798			encoded: Vec<u8>,
1799		) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
1800			SessionKeys::decode_into_raw_public_keys(&encoded)
1801		}
1802	}
1803
1804	impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
1805		fn account_nonce(account: AccountId) -> Nonce {
1806			System::account_nonce(account)
1807		}
1808	}
1809
1810	impl pallet_nfts_runtime_api::NftsApi<Block, AccountId, u32, u32> for Runtime {
1811		fn owner(collection: u32, item: u32) -> Option<AccountId> {
1812			<Nfts as Inspect<AccountId>>::owner(&collection, &item)
1813		}
1814
1815		fn collection_owner(collection: u32) -> Option<AccountId> {
1816			<Nfts as Inspect<AccountId>>::collection_owner(&collection)
1817		}
1818
1819		fn attribute(
1820			collection: u32,
1821			item: u32,
1822			key: Vec<u8>,
1823		) -> Option<Vec<u8>> {
1824			<Nfts as Inspect<AccountId>>::attribute(&collection, &item, &key)
1825		}
1826
1827		fn custom_attribute(
1828			account: AccountId,
1829			collection: u32,
1830			item: u32,
1831			key: Vec<u8>,
1832		) -> Option<Vec<u8>> {
1833			<Nfts as Inspect<AccountId>>::custom_attribute(
1834				&account,
1835				&collection,
1836				&item,
1837				&key,
1838			)
1839		}
1840
1841		fn system_attribute(
1842			collection: u32,
1843			item: Option<u32>,
1844			key: Vec<u8>,
1845		) -> Option<Vec<u8>> {
1846			<Nfts as Inspect<AccountId>>::system_attribute(&collection, item.as_ref(), &key)
1847		}
1848
1849		fn collection_attribute(collection: u32, key: Vec<u8>) -> Option<Vec<u8>> {
1850			<Nfts as Inspect<AccountId>>::collection_attribute(&collection, &key)
1851		}
1852	}
1853
1854	impl pallet_asset_conversion::AssetConversionApi<
1855		Block,
1856		Balance,
1857		xcm::v5::Location,
1858	> for Runtime
1859	{
1860		fn quote_price_exact_tokens_for_tokens(asset1: xcm::v5::Location, asset2: xcm::v5::Location, amount: Balance, include_fee: bool) -> Option<Balance> {
1861			AssetConversion::quote_price_exact_tokens_for_tokens(asset1, asset2, amount, include_fee)
1862		}
1863
1864		fn quote_price_tokens_for_exact_tokens(asset1: xcm::v5::Location, asset2: xcm::v5::Location, amount: Balance, include_fee: bool) -> Option<Balance> {
1865			AssetConversion::quote_price_tokens_for_exact_tokens(asset1, asset2, amount, include_fee)
1866		}
1867
1868		fn get_reserves(asset1: xcm::v5::Location, asset2: xcm::v5::Location) -> Option<(Balance, Balance)> {
1869			AssetConversion::get_reserves(asset1, asset2).ok()
1870		}
1871	}
1872
1873	impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {
1874		fn query_info(
1875			uxt: <Block as BlockT>::Extrinsic,
1876			len: u32,
1877		) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
1878			TransactionPayment::query_info(uxt, len)
1879		}
1880		fn query_fee_details(
1881			uxt: <Block as BlockT>::Extrinsic,
1882			len: u32,
1883		) -> pallet_transaction_payment::FeeDetails<Balance> {
1884			TransactionPayment::query_fee_details(uxt, len)
1885		}
1886		fn query_weight_to_fee(weight: Weight) -> Balance {
1887			TransactionPayment::weight_to_fee(weight)
1888		}
1889		fn query_length_to_fee(length: u32) -> Balance {
1890			TransactionPayment::length_to_fee(length)
1891		}
1892	}
1893
1894	impl xcm_runtime_apis::fees::XcmPaymentApi<Block> for Runtime {
1895		fn query_acceptable_payment_assets(xcm_version: xcm::Version) -> Result<Vec<VersionedAssetId>, XcmPaymentApiError> {
1896			let native_token = xcm_config::WestendLocation::get();
1897			// We accept the native token to pay fees.
1898			let mut acceptable_assets = vec![AssetId(native_token.clone())];
1899			// We also accept all assets in a pool with the native token.
1900			acceptable_assets.extend(
1901				assets_common::PoolAdapter::<Runtime>::get_assets_in_pool_with(native_token)
1902				.map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?
1903			);
1904			PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets)
1905		}
1906
1907		fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
1908			use crate::xcm_config::XcmConfig;
1909
1910			type Trader = <XcmConfig as xcm_executor::Config>::Trader;
1911
1912			PolkadotXcm::query_weight_to_asset_fee::<Trader>(weight, asset)
1913		}
1914
1915		fn query_xcm_weight(message: VersionedXcm<()>) -> Result<Weight, XcmPaymentApiError> {
1916			PolkadotXcm::query_xcm_weight(message)
1917		}
1918
1919		fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
1920			PolkadotXcm::query_delivery_fees(destination, message)
1921		}
1922	}
1923
1924	impl xcm_runtime_apis::dry_run::DryRunApi<Block, RuntimeCall, RuntimeEvent, OriginCaller> for Runtime {
1925		fn dry_run_call(origin: OriginCaller, call: RuntimeCall, result_xcms_version: XcmVersion) -> Result<CallDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
1926			PolkadotXcm::dry_run_call::<Runtime, xcm_config::XcmRouter, OriginCaller, RuntimeCall>(origin, call, result_xcms_version)
1927		}
1928
1929		fn dry_run_xcm(origin_location: VersionedLocation, xcm: VersionedXcm<RuntimeCall>) -> Result<XcmDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
1930			PolkadotXcm::dry_run_xcm::<Runtime, xcm_config::XcmRouter, RuntimeCall, xcm_config::XcmConfig>(origin_location, xcm)
1931		}
1932	}
1933
1934	impl xcm_runtime_apis::conversions::LocationToAccountApi<Block, AccountId> for Runtime {
1935		fn convert_location(location: VersionedLocation) -> Result<
1936			AccountId,
1937			xcm_runtime_apis::conversions::Error
1938		> {
1939			xcm_runtime_apis::conversions::LocationToAccountHelper::<
1940				AccountId,
1941				xcm_config::LocationToAccountId,
1942			>::convert_location(location)
1943		}
1944	}
1945
1946	impl xcm_runtime_apis::trusted_query::TrustedQueryApi<Block> for Runtime {
1947		fn is_trusted_reserve(asset: VersionedAsset, location: VersionedLocation) -> xcm_runtime_apis::trusted_query::XcmTrustedQueryResult {
1948			PolkadotXcm::is_trusted_reserve(asset, location)
1949		}
1950		fn is_trusted_teleporter(asset: VersionedAsset, location: VersionedLocation) -> xcm_runtime_apis::trusted_query::XcmTrustedQueryResult {
1951			PolkadotXcm::is_trusted_teleporter(asset, location)
1952		}
1953	}
1954
1955	impl xcm_runtime_apis::authorized_aliases::AuthorizedAliasersApi<Block> for Runtime {
1956		fn authorized_aliasers(target: VersionedLocation) -> Result<
1957			Vec<xcm_runtime_apis::authorized_aliases::OriginAliaser>,
1958			xcm_runtime_apis::authorized_aliases::Error
1959		> {
1960			PolkadotXcm::authorized_aliasers(target)
1961		}
1962		fn is_authorized_alias(origin: VersionedLocation, target: VersionedLocation) -> Result<
1963			bool,
1964			xcm_runtime_apis::authorized_aliases::Error
1965		> {
1966			PolkadotXcm::is_authorized_alias(origin, target)
1967		}
1968	}
1969
1970	impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi<Block, Balance, RuntimeCall>
1971		for Runtime
1972	{
1973		fn query_call_info(
1974			call: RuntimeCall,
1975			len: u32,
1976		) -> pallet_transaction_payment::RuntimeDispatchInfo<Balance> {
1977			TransactionPayment::query_call_info(call, len)
1978		}
1979		fn query_call_fee_details(
1980			call: RuntimeCall,
1981			len: u32,
1982		) -> pallet_transaction_payment::FeeDetails<Balance> {
1983			TransactionPayment::query_call_fee_details(call, len)
1984		}
1985		fn query_weight_to_fee(weight: Weight) -> Balance {
1986			TransactionPayment::weight_to_fee(weight)
1987		}
1988		fn query_length_to_fee(length: u32) -> Balance {
1989			TransactionPayment::length_to_fee(length)
1990		}
1991	}
1992
1993	impl assets_common::runtime_api::FungiblesApi<
1994		Block,
1995		AccountId,
1996	> for Runtime
1997	{
1998		fn query_account_balances(account: AccountId) -> Result<xcm::VersionedAssets, assets_common::runtime_api::FungiblesAccessError> {
1999			use assets_common::fungible_conversion::{convert, convert_balance};
2000			Ok([
2001				// collect pallet_balance
2002				{
2003					let balance = Balances::free_balance(account.clone());
2004					if balance > 0 {
2005						vec![convert_balance::<WestendLocation, Balance>(balance)?]
2006					} else {
2007						vec![]
2008					}
2009				},
2010				// collect pallet_assets (TrustBackedAssets)
2011				convert::<_, _, _, _, TrustBackedAssetsConvertedConcreteId>(
2012					Assets::account_balances(account.clone())
2013						.iter()
2014						.filter(|(_, balance)| balance > &0)
2015				)?,
2016				// collect pallet_assets (ForeignAssets)
2017				convert::<_, _, _, _, ForeignAssetsConvertedConcreteId>(
2018					ForeignAssets::account_balances(account.clone())
2019						.iter()
2020						.filter(|(_, balance)| balance > &0)
2021				)?,
2022				// collect pallet_assets (PoolAssets)
2023				convert::<_, _, _, _, PoolAssetsConvertedConcreteId>(
2024					PoolAssets::account_balances(account)
2025						.iter()
2026						.filter(|(_, balance)| balance > &0)
2027				)?,
2028				// collect ... e.g. other tokens
2029			].concat().into())
2030		}
2031	}
2032
2033	impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
2034		fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {
2035			ParachainSystem::collect_collation_info(header)
2036		}
2037	}
2038
2039	impl pallet_asset_rewards::AssetRewards<Block, Balance> for Runtime {
2040		fn pool_creation_cost() -> Balance {
2041			StakePoolCreationDeposit::get()
2042		}
2043	}
2044
2045	impl cumulus_primitives_core::GetCoreSelectorApi<Block> for Runtime {
2046		fn core_selector() -> (CoreSelector, ClaimQueueOffset) {
2047			ParachainSystem::core_selector()
2048		}
2049	}
2050
2051	#[cfg(feature = "try-runtime")]
2052	impl frame_try_runtime::TryRuntime<Block> for Runtime {
2053		fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
2054			let weight = Executive::try_runtime_upgrade(checks).unwrap();
2055			(weight, RuntimeBlockWeights::get().max_block)
2056		}
2057
2058		fn execute_block(
2059			block: Block,
2060			state_root_check: bool,
2061			signature_check: bool,
2062			select: frame_try_runtime::TryStateSelect,
2063		) -> Weight {
2064			// NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to
2065			// have a backtrace here.
2066			Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap()
2067		}
2068	}
2069
2070
2071	impl pallet_nomination_pools_runtime_api::NominationPoolsApi<
2072		Block,
2073		AccountId,
2074		Balance,
2075	> for Runtime {
2076		fn pending_rewards(member: AccountId) -> Balance {
2077			NominationPools::api_pending_rewards(member).unwrap_or_default()
2078		}
2079
2080		fn points_to_balance(pool_id: PoolId, points: Balance) -> Balance {
2081			NominationPools::api_points_to_balance(pool_id, points)
2082		}
2083
2084		fn balance_to_points(pool_id: PoolId, new_funds: Balance) -> Balance {
2085			NominationPools::api_balance_to_points(pool_id, new_funds)
2086		}
2087
2088		fn pool_pending_slash(pool_id: PoolId) -> Balance {
2089			NominationPools::api_pool_pending_slash(pool_id)
2090		}
2091
2092		fn member_pending_slash(member: AccountId) -> Balance {
2093			NominationPools::api_member_pending_slash(member)
2094		}
2095
2096		fn pool_needs_delegate_migration(pool_id: PoolId) -> bool {
2097			NominationPools::api_pool_needs_delegate_migration(pool_id)
2098		}
2099
2100		fn member_needs_delegate_migration(member: AccountId) -> bool {
2101			NominationPools::api_member_needs_delegate_migration(member)
2102		}
2103
2104		fn member_total_balance(member: AccountId) -> Balance {
2105			NominationPools::api_member_total_balance(member)
2106		}
2107
2108		fn pool_balance(pool_id: PoolId) -> Balance {
2109			NominationPools::api_pool_balance(pool_id)
2110		}
2111
2112		fn pool_accounts(pool_id: PoolId) -> (AccountId, AccountId) {
2113			NominationPools::api_pool_accounts(pool_id)
2114		}
2115	}
2116
2117	impl pallet_staking_runtime_api::StakingApi<Block, Balance, AccountId> for Runtime {
2118		fn nominations_quota(balance: Balance) -> u32 {
2119			Staking::api_nominations_quota(balance)
2120		}
2121
2122		fn eras_stakers_page_count(era: sp_staking::EraIndex, account: AccountId) -> sp_staking::Page {
2123			Staking::api_eras_stakers_page_count(era, account)
2124		}
2125
2126		fn pending_rewards(era: sp_staking::EraIndex, account: AccountId) -> bool {
2127			Staking::api_pending_rewards(era, account)
2128		}
2129	}
2130
2131	#[cfg(feature = "runtime-benchmarks")]
2132	impl frame_benchmarking::Benchmark<Block> for Runtime {
2133		fn benchmark_metadata(extra: bool) -> (
2134			Vec<frame_benchmarking::BenchmarkList>,
2135			Vec<frame_support::traits::StorageInfo>,
2136		) {
2137			use frame_benchmarking::BenchmarkList;
2138			use frame_support::traits::StorageInfoTrait;
2139			use frame_system_benchmarking::Pallet as SystemBench;
2140			use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench;
2141			use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
2142			use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
2143			use pallet_xcm_bridge_hub_router::benchmarking::Pallet as XcmBridgeHubRouterBench;
2144
2145			// This is defined once again in dispatch_benchmark, because list_benchmarks!
2146			// and add_benchmarks! are macros exported by define_benchmarks! macros and those types
2147			// are referenced in that call.
2148			type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::<Runtime>;
2149			type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::<Runtime>;
2150
2151			// Benchmark files generated for `Assets/ForeignAssets` instances are by default
2152			// `pallet_assets_assets.rs / pallet_assets_foreign_assets`, which is not really nice,
2153			// so with this redefinition we can change names to nicer:
2154			// `pallet_assets_local.rs / pallet_assets_foreign.rs`.
2155			type Local = pallet_assets::Pallet::<Runtime, TrustBackedAssetsInstance>;
2156			type Foreign = pallet_assets::Pallet::<Runtime, ForeignAssetsInstance>;
2157			type Pool = pallet_assets::Pallet::<Runtime, PoolAssetsInstance>;
2158
2159			type ToRococo = XcmBridgeHubRouterBench<Runtime, ToRococoXcmRouterInstance>;
2160
2161			let mut list = Vec::<BenchmarkList>::new();
2162			list_benchmarks!(list, extra);
2163
2164			let storage_info = AllPalletsWithSystem::storage_info();
2165			(list, storage_info)
2166		}
2167
2168		#[allow(non_local_definitions)]
2169		fn dispatch_benchmark(
2170			config: frame_benchmarking::BenchmarkConfig
2171		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
2172			use frame_benchmarking::{BenchmarkBatch, BenchmarkError};
2173			use frame_support::assert_ok;
2174			use sp_storage::TrackedStorageKey;
2175
2176			use frame_system_benchmarking::Pallet as SystemBench;
2177			use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench;
2178			impl frame_system_benchmarking::Config for Runtime {
2179				fn setup_set_code_requirements(code: &alloc::vec::Vec<u8>) -> Result<(), BenchmarkError> {
2180					ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32);
2181					Ok(())
2182				}
2183
2184				fn verify_set_code() {
2185					System::assert_last_event(cumulus_pallet_parachain_system::Event::<Runtime>::ValidationFunctionStored.into());
2186				}
2187			}
2188
2189			use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
2190			impl cumulus_pallet_session_benchmarking::Config for Runtime {}
2191
2192			parameter_types! {
2193				pub ExistentialDepositAsset: Option<Asset> = Some((
2194					WestendLocation::get(),
2195					ExistentialDeposit::get()
2196				).into());
2197				pub const RandomParaId: ParaId = ParaId::new(43211234);
2198			}
2199
2200			use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
2201			impl pallet_xcm::benchmarking::Config for Runtime {
2202				type DeliveryHelper = (
2203					cumulus_primitives_utility::ToParentDeliveryHelper<
2204						xcm_config::XcmConfig,
2205						ExistentialDepositAsset,
2206						xcm_config::PriceForParentDelivery,
2207					>,
2208					polkadot_runtime_common::xcm_sender::ToParachainDeliveryHelper<
2209						xcm_config::XcmConfig,
2210						ExistentialDepositAsset,
2211						PriceForSiblingParachainDelivery,
2212						RandomParaId,
2213						ParachainSystem,
2214					>
2215				);
2216
2217				fn reachable_dest() -> Option<Location> {
2218					Some(Parent.into())
2219				}
2220
2221				fn teleportable_asset_and_dest() -> Option<(Asset, Location)> {
2222					// Relay/native token can be teleported between AH and Relay.
2223					Some((
2224						Asset {
2225							fun: Fungible(ExistentialDeposit::get()),
2226							id: AssetId(Parent.into())
2227						},
2228						Parent.into(),
2229					))
2230				}
2231
2232				fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> {
2233					// We get an account to create USDT and give it enough WND to exist.
2234					let account = frame_benchmarking::whitelisted_caller();
2235					assert_ok!(<Balances as fungible::Mutate<_>>::mint_into(
2236						&account,
2237						ExistentialDeposit::get() + (1_000 * UNITS)
2238					));
2239
2240					// We then create USDT.
2241					let usdt_id = 1984u32;
2242					let usdt_location = Location::new(0, [PalletInstance(50), GeneralIndex(usdt_id.into())]);
2243					assert_ok!(Assets::force_create(
2244						RuntimeOrigin::root(),
2245						usdt_id.into(),
2246						account.clone().into(),
2247						true,
2248						1
2249					));
2250
2251					// And return USDT as the reserve transferable asset.
2252					Some((
2253						Asset { fun: Fungible(ExistentialDeposit::get()), id: AssetId(usdt_location) },
2254						ParentThen(Parachain(RandomParaId::get().into()).into()).into(),
2255					))
2256				}
2257
2258				fn set_up_complex_asset_transfer(
2259				) -> Option<(XcmAssets, u32, Location, alloc::boxed::Box<dyn FnOnce()>)> {
2260					// Transfer to Relay some local AH asset (local-reserve-transfer) while paying
2261					// fees using teleported native token.
2262					// (We don't care that Relay doesn't accept incoming unknown AH local asset)
2263					let dest = Parent.into();
2264
2265					let fee_amount = EXISTENTIAL_DEPOSIT;
2266					let fee_asset: Asset = (Location::parent(), fee_amount).into();
2267
2268					let who = frame_benchmarking::whitelisted_caller();
2269					// Give some multiple of the existential deposit
2270					let balance = fee_amount + EXISTENTIAL_DEPOSIT * 1000;
2271					let _ = <Balances as frame_support::traits::Currency<_>>::make_free_balance_be(
2272						&who, balance,
2273					);
2274					// verify initial balance
2275					assert_eq!(Balances::free_balance(&who), balance);
2276
2277					// set up local asset
2278					let asset_amount = 10u128;
2279					let initial_asset_amount = asset_amount * 10;
2280					let (asset_id, _, _) = pallet_assets::benchmarking::create_default_minted_asset::<
2281						Runtime,
2282						pallet_assets::Instance1
2283					>(true, initial_asset_amount);
2284					let asset_location = Location::new(
2285						0,
2286						[PalletInstance(50), GeneralIndex(u32::from(asset_id).into())]
2287					);
2288					let transfer_asset: Asset = (asset_location, asset_amount).into();
2289
2290					let assets: XcmAssets = vec![fee_asset.clone(), transfer_asset].into();
2291					let fee_index = if assets.get(0).unwrap().eq(&fee_asset) { 0 } else { 1 };
2292
2293					// verify transferred successfully
2294					let verify = alloc::boxed::Box::new(move || {
2295						// verify native balance after transfer, decreased by transferred fee amount
2296						// (plus transport fees)
2297						assert!(Balances::free_balance(&who) <= balance - fee_amount);
2298						// verify asset balance decreased by exactly transferred amount
2299						assert_eq!(
2300							Assets::balance(asset_id.into(), &who),
2301							initial_asset_amount - asset_amount,
2302						);
2303					});
2304					Some((assets, fee_index as u32, dest, verify))
2305				}
2306
2307				fn get_asset() -> Asset {
2308					use frame_benchmarking::whitelisted_caller;
2309					use frame_support::traits::tokens::fungible::{Inspect, Mutate};
2310					let account = whitelisted_caller();
2311					assert_ok!(<Balances as Mutate<_>>::mint_into(
2312						&account,
2313						<Balances as Inspect<_>>::minimum_balance(),
2314					));
2315					let asset_id = 1984;
2316					assert_ok!(Assets::force_create(
2317						RuntimeOrigin::root(),
2318						asset_id.into(),
2319						account.into(),
2320						true,
2321						1u128,
2322					));
2323					let amount = 1_000_000u128;
2324					let asset_location = Location::new(0, [PalletInstance(50), GeneralIndex(u32::from(asset_id).into())]);
2325
2326					Asset {
2327						id: AssetId(asset_location),
2328						fun: Fungible(amount),
2329					}
2330				}
2331			}
2332
2333			use pallet_xcm_bridge_hub_router::benchmarking::{
2334				Pallet as XcmBridgeHubRouterBench,
2335				Config as XcmBridgeHubRouterConfig,
2336			};
2337
2338			impl XcmBridgeHubRouterConfig<ToRococoXcmRouterInstance> for Runtime {
2339				fn make_congested() {
2340					cumulus_pallet_xcmp_queue::bridging::suspend_channel_for_benchmarks::<Runtime>(
2341						xcm_config::bridging::SiblingBridgeHubParaId::get().into()
2342					);
2343				}
2344				fn ensure_bridged_target_destination() -> Result<Location, BenchmarkError> {
2345					ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
2346						xcm_config::bridging::SiblingBridgeHubParaId::get().into()
2347					);
2348					let bridged_asset_hub = xcm_config::bridging::to_rococo::AssetHubRococo::get();
2349					let _ = PolkadotXcm::force_xcm_version(
2350						RuntimeOrigin::root(),
2351						alloc::boxed::Box::new(bridged_asset_hub.clone()),
2352						XCM_VERSION,
2353					).map_err(|e| {
2354						log::error!(
2355							"Failed to dispatch `force_xcm_version({:?}, {:?}, {:?})`, error: {:?}",
2356							RuntimeOrigin::root(),
2357							bridged_asset_hub,
2358							XCM_VERSION,
2359							e
2360						);
2361						BenchmarkError::Stop("XcmVersion was not stored!")
2362					})?;
2363					Ok(bridged_asset_hub)
2364				}
2365			}
2366
2367			use xcm_config::{MaxAssetsIntoHolding, WestendLocation};
2368			use pallet_xcm_benchmarks::asset_instance_from;
2369
2370			impl pallet_xcm_benchmarks::Config for Runtime {
2371				type XcmConfig = xcm_config::XcmConfig;
2372				type AccountIdConverter = xcm_config::LocationToAccountId;
2373				type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper<
2374					xcm_config::XcmConfig,
2375					ExistentialDepositAsset,
2376					xcm_config::PriceForParentDelivery,
2377				>;
2378				fn valid_destination() -> Result<Location, BenchmarkError> {
2379					Ok(WestendLocation::get())
2380				}
2381				fn worst_case_holding(depositable_count: u32) -> XcmAssets {
2382					// A mix of fungible, non-fungible, and concrete assets.
2383					let holding_non_fungibles = MaxAssetsIntoHolding::get() / 2 - depositable_count;
2384					let holding_fungibles = holding_non_fungibles - 2; // -2 for two `iter::once` bellow
2385					let fungibles_amount: u128 = 100;
2386					(0..holding_fungibles)
2387						.map(|i| {
2388							Asset {
2389								id: AssetId(GeneralIndex(i as u128).into()),
2390								fun: Fungible(fungibles_amount * (i + 1) as u128), // non-zero amount
2391							}
2392						})
2393						.chain(core::iter::once(Asset { id: AssetId(Here.into()), fun: Fungible(u128::MAX) }))
2394						.chain(core::iter::once(Asset { id: AssetId(WestendLocation::get()), fun: Fungible(1_000_000 * UNITS) }))
2395						.chain((0..holding_non_fungibles).map(|i| Asset {
2396							id: AssetId(GeneralIndex(i as u128).into()),
2397							fun: NonFungible(asset_instance_from(i)),
2398						}))
2399						.collect::<Vec<_>>()
2400						.into()
2401				}
2402			}
2403
2404			parameter_types! {
2405				pub const TrustedTeleporter: Option<(Location, Asset)> = Some((
2406					WestendLocation::get(),
2407					Asset { fun: Fungible(UNITS), id: AssetId(WestendLocation::get()) },
2408				));
2409				pub const CheckedAccount: Option<(AccountId, xcm_builder::MintLocation)> = None;
2410				// AssetHubWestend trusts AssetHubRococo as reserve for ROCs
2411				pub TrustedReserve: Option<(Location, Asset)> = Some(
2412					(
2413						xcm_config::bridging::to_rococo::AssetHubRococo::get(),
2414						Asset::from((xcm_config::bridging::to_rococo::RocLocation::get(), 1000000000000 as u128))
2415					)
2416				);
2417			}
2418
2419			impl pallet_xcm_benchmarks::fungible::Config for Runtime {
2420				type TransactAsset = Balances;
2421
2422				type CheckedAccount = CheckedAccount;
2423				type TrustedTeleporter = TrustedTeleporter;
2424				type TrustedReserve = TrustedReserve;
2425
2426				fn get_asset() -> Asset {
2427					use frame_support::traits::tokens::fungible::{Inspect, Mutate};
2428					let (account, _) = pallet_xcm_benchmarks::account_and_location::<Runtime>(1);
2429					assert_ok!(<Balances as Mutate<_>>::mint_into(
2430						&account,
2431						<Balances as Inspect<_>>::minimum_balance(),
2432					));
2433					let asset_id = 1984;
2434					assert_ok!(Assets::force_create(
2435						RuntimeOrigin::root(),
2436						asset_id.into(),
2437						account.clone().into(),
2438						true,
2439						1u128,
2440					));
2441					let amount = 1_000_000u128;
2442					let asset_location = Location::new(0, [PalletInstance(50), GeneralIndex(u32::from(asset_id).into())]);
2443
2444					Asset {
2445						id: AssetId(asset_location),
2446						fun: Fungible(amount),
2447					}
2448				}
2449			}
2450
2451			impl pallet_xcm_benchmarks::generic::Config for Runtime {
2452				type TransactAsset = Balances;
2453				type RuntimeCall = RuntimeCall;
2454
2455				fn worst_case_response() -> (u64, Response) {
2456					(0u64, Response::Version(Default::default()))
2457				}
2458
2459				fn worst_case_asset_exchange() -> Result<(XcmAssets, XcmAssets), BenchmarkError> {
2460					let native_asset_location = WestendLocation::get();
2461					let native_asset_id = AssetId(native_asset_location.clone());
2462					let (account, _) = pallet_xcm_benchmarks::account_and_location::<Runtime>(1);
2463					let origin = RuntimeOrigin::signed(account.clone());
2464					let asset_location = Location::new(1, [Parachain(2001)]);
2465					let asset_id = AssetId(asset_location.clone());
2466
2467					assert_ok!(<Balances as fungible::Mutate<_>>::mint_into(
2468						&account,
2469						ExistentialDeposit::get() + (1_000 * UNITS)
2470					));
2471
2472					assert_ok!(ForeignAssets::force_create(
2473						RuntimeOrigin::root(),
2474						asset_location.clone().into(),
2475						account.clone().into(),
2476						true,
2477						1,
2478					));
2479
2480					assert_ok!(ForeignAssets::mint(
2481						origin.clone(),
2482						asset_location.clone().into(),
2483						account.clone().into(),
2484						3_000 * UNITS,
2485					));
2486
2487					assert_ok!(AssetConversion::create_pool(
2488						origin.clone(),
2489						native_asset_location.clone().into(),
2490						asset_location.clone().into(),
2491					));
2492
2493					assert_ok!(AssetConversion::add_liquidity(
2494						origin,
2495						native_asset_location.into(),
2496						asset_location.into(),
2497						1_000 * UNITS,
2498						2_000 * UNITS,
2499						1,
2500						1,
2501						account.into(),
2502					));
2503
2504					let give_assets: XcmAssets = (native_asset_id, 500 * UNITS).into();
2505					let receive_assets: XcmAssets = (asset_id, 660 * UNITS).into();
2506
2507					Ok((give_assets, receive_assets))
2508				}
2509
2510				fn universal_alias() -> Result<(Location, Junction), BenchmarkError> {
2511					xcm_config::bridging::BridgingBenchmarksHelper::prepare_universal_alias()
2512					.ok_or(BenchmarkError::Skip)
2513				}
2514
2515				fn transact_origin_and_runtime_call() -> Result<(Location, RuntimeCall), BenchmarkError> {
2516					Ok((WestendLocation::get(), frame_system::Call::remark_with_event { remark: vec![] }.into()))
2517				}
2518
2519				fn subscribe_origin() -> Result<Location, BenchmarkError> {
2520					Ok(WestendLocation::get())
2521				}
2522
2523				fn claimable_asset() -> Result<(Location, Location, XcmAssets), BenchmarkError> {
2524					let origin = WestendLocation::get();
2525					let assets: XcmAssets = (AssetId(WestendLocation::get()), 1_000 * UNITS).into();
2526					let ticket = Location { parents: 0, interior: Here };
2527					Ok((origin, ticket, assets))
2528				}
2529
2530				fn worst_case_for_trader() -> Result<(Asset, WeightLimit), BenchmarkError> {
2531					Ok((Asset {
2532						id: AssetId(WestendLocation::get()),
2533						fun: Fungible(1_000 * UNITS),
2534					}, WeightLimit::Limited(Weight::from_parts(5000, 5000))))
2535				}
2536
2537				fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> {
2538					Err(BenchmarkError::Skip)
2539				}
2540
2541				fn export_message_origin_and_destination(
2542				) -> Result<(Location, NetworkId, InteriorLocation), BenchmarkError> {
2543					Err(BenchmarkError::Skip)
2544				}
2545
2546				fn alias_origin() -> Result<(Location, Location), BenchmarkError> {
2547					// Any location can alias to an internal location.
2548					// Here parachain 1001 aliases to an internal account.
2549					Ok((
2550						Location::new(1, [Parachain(1001)]),
2551						Location::new(1, [Parachain(1001), AccountId32 { id: [111u8; 32], network: None }]),
2552					))
2553				}
2554			}
2555
2556			type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::<Runtime>;
2557			type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::<Runtime>;
2558
2559			type Local = pallet_assets::Pallet::<Runtime, TrustBackedAssetsInstance>;
2560			type Foreign = pallet_assets::Pallet::<Runtime, ForeignAssetsInstance>;
2561			type Pool = pallet_assets::Pallet::<Runtime, PoolAssetsInstance>;
2562
2563			type ToRococo = XcmBridgeHubRouterBench<Runtime, ToRococoXcmRouterInstance>;
2564
2565			use frame_support::traits::WhitelistedStorageKeys;
2566			let whitelist: Vec<TrackedStorageKey> = AllPalletsWithSystem::whitelisted_storage_keys();
2567
2568			let mut batches = Vec::<BenchmarkBatch>::new();
2569			let params = (&config, &whitelist);
2570			add_benchmarks!(params, batches);
2571
2572			Ok(batches)
2573		}
2574	}
2575
2576	impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
2577		fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
2578			build_state::<RuntimeGenesisConfig>(config)
2579		}
2580
2581		fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
2582			get_preset::<RuntimeGenesisConfig>(id, &genesis_config_presets::get_preset)
2583		}
2584
2585		fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
2586			genesis_config_presets::preset_names()
2587		}
2588	}
2589);
2590
2591cumulus_pallet_parachain_system::register_validate_block! {
2592	Runtime = Runtime,
2593	BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
2594}
2595
2596parameter_types! {
2597	// The deposit configuration for the singed migration. Specially if you want to allow any signed account to do the migration (see `SignedFilter`, these deposits should be high)
2598	pub const MigrationSignedDepositPerItem: Balance = CENTS;
2599	pub const MigrationSignedDepositBase: Balance = 2_000 * CENTS;
2600	pub const MigrationMaxKeyLen: u32 = 512;
2601}
2602
2603impl pallet_state_trie_migration::Config for Runtime {
2604	type RuntimeEvent = RuntimeEvent;
2605	type Currency = Balances;
2606	type RuntimeHoldReason = RuntimeHoldReason;
2607	type SignedDepositPerItem = MigrationSignedDepositPerItem;
2608	type SignedDepositBase = MigrationSignedDepositBase;
2609	// An origin that can control the whole pallet: should be Root, or a part of your council.
2610	type ControlOrigin = frame_system::EnsureSignedBy<RootMigController, AccountId>;
2611	// specific account for the migration, can trigger the signed migrations.
2612	type SignedFilter = frame_system::EnsureSignedBy<MigController, AccountId>;
2613
2614	// Replace this with weight based on your runtime.
2615	type WeightInfo = pallet_state_trie_migration::weights::SubstrateWeight<Runtime>;
2616
2617	type MaxKeyLen = MigrationMaxKeyLen;
2618}
2619
2620frame_support::ord_parameter_types! {
2621	pub const MigController: AccountId = AccountId::from(hex_literal::hex!("8458ed39dc4b6f6c7255f7bc42be50c2967db126357c999d44e12ca7ac80dc52"));
2622	pub const RootMigController: AccountId = AccountId::from(hex_literal::hex!("8458ed39dc4b6f6c7255f7bc42be50c2967db126357c999d44e12ca7ac80dc52"));
2623}
2624
2625#[test]
2626fn ensure_key_ss58() {
2627	use frame_support::traits::SortedMembers;
2628	use sp_core::crypto::Ss58Codec;
2629	let acc =
2630		AccountId::from_ss58check("5F4EbSkZz18X36xhbsjvDNs6NuZ82HyYtq5UiJ1h9SBHJXZD").unwrap();
2631	assert_eq!(acc, MigController::sorted_members()[0]);
2632	let acc =
2633		AccountId::from_ss58check("5F4EbSkZz18X36xhbsjvDNs6NuZ82HyYtq5UiJ1h9SBHJXZD").unwrap();
2634	assert_eq!(acc, RootMigController::sorted_members()[0]);
2635}