// Copyright (C) Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //! # Asset Hub Westend Runtime //! //! Testnet for Asset Hub Polkadot. #![cfg_attr(not(feature = "std"), no_std)] #![recursion_limit = "256"] // Make the WASM binary available. #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); mod weights; pub mod xcm_config; use assets_common::{ local_and_foreign_assets::{LocalFromLeft, TargetFromLeft}, AssetIdForTrustBackedAssetsConvert, }; use codec::{Decode, Encode, MaxEncodedLen}; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use cumulus_primitives_core::{AggregateMessageOrigin, ParaId}; use frame_support::{ construct_runtime, derive_impl, dispatch::DispatchClass, genesis_builder_helper::{build_config, create_default_config}, ord_parameter_types, parameter_types, traits::{ fungible, fungibles, tokens::{imbalance::ResolveAssetTo, nonfungibles_v2::Inspect}, AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, Equals, InstanceFilter, TransformOrigin, }, weights::{ConstantMultiplier, Weight}, BoundedVec, PalletId, }; use frame_system::{ limits::{BlockLength, BlockWeights}, EnsureRoot, EnsureSigned, EnsureSignedBy, }; use pallet_asset_conversion_tx_payment::AssetConversionAdapter; use pallet_nfts::{DestroyWitness, PalletFeatures}; use pallet_xcm::EnsureXcm; use parachains_common::{ impls::DealWithFees, message_queue::*, AccountId, AssetIdForTrustBackedAssets, AuraId, Balance, BlockNumber, CollectionId, Hash, Header, ItemId, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdConversion, BlakeTwo256, Block as BlockT, Saturating, Verify}, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, Perbill, Permill, RuntimeDebug, }; use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; use testnet_parachains_constants::westend::{consensus::*, currency::*, fee::WeightToFee}; use xcm_config::{ ForeignAssetsConvertedConcreteId, PoolAssetsConvertedConcreteId, TrustBackedAssetsConvertedConcreteId, TrustBackedAssetsPalletLocationV3, WestendLocation, WestendLocationV3, XcmOriginToTransactDispatchOrigin, }; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; use assets_common::{foreign_creators::ForeignCreators, matching::FromSiblingParachain}; use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; // We exclude `Assets` since it's the name of a pallet use xcm::latest::prelude::AssetId; #[cfg(feature = "runtime-benchmarks")] use xcm::latest::prelude::{ Asset, Fungible, Here, InteriorLocation, Junction, Junction::*, Location, NetworkId, NonFungible, Parent, ParentThen, Response, XCM_VERSION, }; use crate::xcm_config::ForeignCreatorsSovereignAccountOf; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; impl_opaque_keys! { pub struct SessionKeys { pub aura: Aura, } } #[sp_version::runtime_version] pub const VERSION: RuntimeVersion = RuntimeVersion { // Note: "westmint" is the legacy name for this chain. It has been renamed to // "asset-hub-westend". Many wallets/tools depend on the `spec_name`, so it remains "westmint" // for the time being. Wallets/tools should update to treat "asset-hub-westend" equally. spec_name: create_runtime_str!("westmint"), impl_name: create_runtime_str!("westmint"), authoring_version: 1, spec_version: 1_006_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 14, state_version: 0, }; /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } parameter_types! { pub const Version: RuntimeVersion = VERSION; pub RuntimeBlockLength: BlockLength = BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder() .base_block(BlockExecutionWeight::get()) .for_class(DispatchClass::all(), |weights| { weights.base_extrinsic = ExtrinsicBaseWeight::get(); }) .for_class(DispatchClass::Normal, |weights| { weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); }) .for_class(DispatchClass::Operational, |weights| { weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); // Operational transactions have some extra reserved space, so that they // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. weights.reserved = Some( MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT ); }) .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) .build_or_panic(); pub const SS58Prefix: u8 = 42; } // Configure FRAME pallets to include in runtime. #[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Runtime { type BlockWeights = RuntimeBlockWeights; type BlockLength = RuntimeBlockLength; type AccountId = AccountId; type Nonce = Nonce; type Hash = Hash; type Block = Block; type BlockHashCount = BlockHashCount; type DbWeight = RocksDbWeight; type Version = Version; type AccountData = pallet_balances::AccountData; type SystemWeightInfo = weights::frame_system::WeightInfo; type SS58Prefix = SS58Prefix; type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; type WeightInfo = weights::pallet_timestamp::WeightInfo; } impl pallet_authorship::Config for Runtime { type FindAuthor = pallet_session::FindAccountFromAuthorIndex; type EventHandler = (CollatorSelection,); } parameter_types! { pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT; } impl pallet_balances::Config for Runtime { type MaxLocks = ConstU32<50>; /// The type for recording an account's balance. type Balance = Balance; /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = weights::pallet_balances::WeightInfo; type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = RuntimeFreezeReason; type FreezeIdentifier = (); // We allow each account to have holds on it from: // - `NftFractionalization`: 1 type MaxHolds = ConstU32<1>; type MaxFreezes = ConstU32<0>; } parameter_types! { /// Relay Chain `TransactionByteFee` / 10 pub const TransactionByteFee: Balance = MILLICENTS; } impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter>; type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; type OperationalFeeMultiplier = ConstU8<5>; } parameter_types! { pub const AssetDeposit: Balance = UNITS / 10; // 1 / 10 WND deposit to create asset pub const AssetAccountDeposit: Balance = deposit(1, 16); pub const ApprovalDeposit: Balance = EXISTENTIAL_DEPOSIT; pub const AssetsStringLimit: u32 = 50; /// Key = 32 bytes, Value = 36 bytes (32+1+1+1+1) // https://github.com/paritytech/substrate/blob/069917b/frame/assets/src/lib.rs#L257L271 pub const MetadataDepositBase: Balance = deposit(1, 68); pub const MetadataDepositPerByte: Balance = deposit(0, 1); } pub type AssetsForceOrigin = EnsureRoot; // Called "Trust Backed" assets because these are generally registered by some account, and users of // the asset assume it has some claimed backing. The pallet is called `Assets` in // `construct_runtime` to avoid breaking changes on storage reads. pub type TrustBackedAssetsInstance = pallet_assets::Instance1; type TrustBackedAssetsCall = pallet_assets::Call; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type AssetId = AssetIdForTrustBackedAssets; type AssetIdParameter = codec::Compact; type Currency = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = AssetsForceOrigin; type AssetDeposit = AssetDeposit; type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; type ApprovalDeposit = ApprovalDeposit; type StringLimit = AssetsStringLimit; type Freezer = (); type Extra = (); type WeightInfo = weights::pallet_assets_local::WeightInfo; type CallbackHandle = (); type AssetAccountDeposit = AssetAccountDeposit; type RemoveItemsLimit = ConstU32<1000>; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); } parameter_types! { pub const AssetConversionPalletId: PalletId = PalletId(*b"py/ascon"); pub const LiquidityWithdrawalFee: Permill = Permill::from_percent(0); } ord_parameter_types! { pub const AssetConversionOrigin: sp_runtime::AccountId32 = AccountIdConversion::::into_account_truncating(&AssetConversionPalletId::get()); } pub type PoolAssetsInstance = pallet_assets::Instance3; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type RemoveItemsLimit = ConstU32<1000>; type AssetId = u32; type AssetIdParameter = u32; type Currency = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = AssetsForceOrigin; type AssetDeposit = ConstU128<0>; type AssetAccountDeposit = ConstU128<0>; type MetadataDepositBase = ConstU128<0>; type MetadataDepositPerByte = ConstU128<0>; type ApprovalDeposit = ConstU128<0>; type StringLimit = ConstU32<50>; type Freezer = (); type Extra = (); type WeightInfo = weights::pallet_assets_pool::WeightInfo; type CallbackHandle = (); #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); } /// Union fungibles implementation for `Assets` and `ForeignAssets`. pub type LocalAndForeignAssets = fungibles::UnionOf< Assets, ForeignAssets, LocalFromLeft< AssetIdForTrustBackedAssetsConvert, AssetIdForTrustBackedAssets, xcm::v3::Location, >, xcm::v3::Location, AccountId, >; /// Union fungibles implementation for [`LocalAndForeignAssets`] and `Balances`. pub type NativeAndAssets = fungible::UnionOf< Balances, LocalAndForeignAssets, TargetFromLeft, xcm::v3::Location, AccountId, >; impl pallet_asset_conversion::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type HigherPrecisionBalance = sp_core::U256; type AssetKind = xcm::v3::Location; type Assets = NativeAndAssets; type PoolId = (Self::AssetKind, Self::AssetKind); type PoolLocator = pallet_asset_conversion::WithFirstAsset; type PoolAssetId = u32; type PoolAssets = PoolAssets; type PoolSetupFee = ConstU128<0>; // Asset class deposit fees are sufficient to prevent spam type PoolSetupFeeAsset = WestendLocationV3; type PoolSetupFeeTarget = ResolveAssetTo; type LiquidityWithdrawalFee = LiquidityWithdrawalFee; type LPFee = ConstU32<3>; type PalletId = AssetConversionPalletId; type MaxSwapPathLength = ConstU32<3>; type MintMinLiquidity = ConstU128<100>; type WeightInfo = weights::pallet_asset_conversion::WeightInfo; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = assets_common::benchmarks::AssetPairFactory< WestendLocationV3, parachain_info::Pallet, xcm_config::TrustBackedAssetsPalletIndex, xcm::v3::Location, >; } parameter_types! { // we just reuse the same deposits pub const ForeignAssetsAssetDeposit: Balance = AssetDeposit::get(); pub const ForeignAssetsAssetAccountDeposit: Balance = AssetAccountDeposit::get(); pub const ForeignAssetsApprovalDeposit: Balance = ApprovalDeposit::get(); pub const ForeignAssetsAssetsStringLimit: u32 = AssetsStringLimit::get(); pub const ForeignAssetsMetadataDepositBase: Balance = MetadataDepositBase::get(); pub const ForeignAssetsMetadataDepositPerByte: Balance = MetadataDepositPerByte::get(); } /// Assets managed by some foreign location. Note: we do not declare a `ForeignAssetsCall` type, as /// this type is used in proxy definitions. We assume that a foreign location would not want to set /// an individual, local account as a proxy for the issuance of their assets. This issuance should /// be managed by the foreign location's governance. pub type ForeignAssetsInstance = pallet_assets::Instance2; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type AssetId = xcm::v3::Location; type AssetIdParameter = xcm::v3::Location; type Currency = Balances; type CreateOrigin = ForeignCreators< FromSiblingParachain, xcm::v3::Location>, ForeignCreatorsSovereignAccountOf, AccountId, xcm::v3::Location, >; type ForceOrigin = AssetsForceOrigin; type AssetDeposit = ForeignAssetsAssetDeposit; type MetadataDepositBase = ForeignAssetsMetadataDepositBase; type MetadataDepositPerByte = ForeignAssetsMetadataDepositPerByte; type ApprovalDeposit = ForeignAssetsApprovalDeposit; type StringLimit = ForeignAssetsAssetsStringLimit; type Freezer = (); type Extra = (); type WeightInfo = weights::pallet_assets_foreign::WeightInfo; type CallbackHandle = (); type AssetAccountDeposit = ForeignAssetsAssetAccountDeposit; type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = xcm_config::XcmBenchmarkHelper; } parameter_types! { // One storage item; key size is 32; value is size 4+4+16+32 bytes = 56 bytes. pub const DepositBase: Balance = deposit(1, 88); // Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); pub const MaxSignatories: u32 = 100; } impl pallet_multisig::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; type DepositBase = DepositBase; type DepositFactor = DepositFactor; type MaxSignatories = MaxSignatories; type WeightInfo = weights::pallet_multisig::WeightInfo; } impl pallet_utility::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type PalletsOrigin = OriginCaller; type WeightInfo = weights::pallet_utility::WeightInfo; } parameter_types! { // One storage item; key size 32, value size 8; . pub const ProxyDepositBase: Balance = deposit(1, 40); // Additional storage item size of 33 bytes. pub const ProxyDepositFactor: Balance = deposit(0, 33); pub const MaxProxies: u16 = 32; // One storage item; key size 32, value size 16 pub const AnnouncementDepositBase: Balance = deposit(1, 48); pub const AnnouncementDepositFactor: Balance = deposit(0, 66); pub const MaxPending: u16 = 32; } /// The type used to represent the kinds of proxying allowed. #[derive( Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, MaxEncodedLen, scale_info::TypeInfo, )] pub enum ProxyType { /// Fully permissioned proxy. Can execute any call on behalf of _proxied_. Any, /// Can execute any call that does not transfer funds or assets. NonTransfer, /// Proxy with the ability to reject time-delay proxy announcements. CancelProxy, /// Assets proxy. Can execute any call from `assets`, **including asset transfers**. Assets, /// Owner proxy. Can execute calls related to asset ownership. AssetOwner, /// Asset manager. Can execute calls related to asset management. AssetManager, /// Collator selection proxy. Can execute calls related to collator selection mechanism. Collator, } impl Default for ProxyType { fn default() -> Self { Self::Any } } impl InstanceFilter for ProxyType { fn filter(&self, c: &RuntimeCall) -> bool { match self { ProxyType::Any => true, ProxyType::NonTransfer => !matches!( c, RuntimeCall::Balances { .. } | RuntimeCall::Assets { .. } | RuntimeCall::NftFractionalization { .. } | RuntimeCall::Nfts { .. } | RuntimeCall::Uniques { .. } ), ProxyType::CancelProxy => matches!( c, RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. }) | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), ProxyType::Assets => { matches!( c, RuntimeCall::Assets { .. } | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } | RuntimeCall::NftFractionalization { .. } | RuntimeCall::Nfts { .. } | RuntimeCall::Uniques { .. } ) }, ProxyType::AssetOwner => matches!( c, RuntimeCall::Assets(TrustBackedAssetsCall::create { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::start_destroy { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::destroy_accounts { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::destroy_approvals { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::finish_destroy { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::transfer_ownership { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::set_team { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::set_metadata { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::clear_metadata { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::set_min_balance { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::create { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::destroy { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::redeposit { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::transfer_ownership { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::set_team { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::set_collection_max_supply { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::lock_collection { .. }) | RuntimeCall::Uniques(pallet_uniques::Call::create { .. }) | RuntimeCall::Uniques(pallet_uniques::Call::destroy { .. }) | RuntimeCall::Uniques(pallet_uniques::Call::transfer_ownership { .. }) | RuntimeCall::Uniques(pallet_uniques::Call::set_team { .. }) | RuntimeCall::Uniques(pallet_uniques::Call::set_metadata { .. }) | RuntimeCall::Uniques(pallet_uniques::Call::set_attribute { .. }) | RuntimeCall::Uniques(pallet_uniques::Call::set_collection_metadata { .. }) | RuntimeCall::Uniques(pallet_uniques::Call::clear_metadata { .. }) | RuntimeCall::Uniques(pallet_uniques::Call::clear_attribute { .. }) | RuntimeCall::Uniques(pallet_uniques::Call::clear_collection_metadata { .. }) | RuntimeCall::Uniques(pallet_uniques::Call::set_collection_max_supply { .. }) | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), ProxyType::AssetManager => matches!( c, RuntimeCall::Assets(TrustBackedAssetsCall::mint { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::burn { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::freeze { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::block { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::thaw { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::freeze_asset { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::thaw_asset { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::touch_other { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::refund_other { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::force_mint { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::update_mint_settings { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::mint_pre_signed { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::set_attributes_pre_signed { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::lock_item_transfer { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::unlock_item_transfer { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::lock_item_properties { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::set_metadata { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::clear_metadata { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::set_collection_metadata { .. }) | RuntimeCall::Nfts(pallet_nfts::Call::clear_collection_metadata { .. }) | RuntimeCall::Uniques(pallet_uniques::Call::mint { .. }) | RuntimeCall::Uniques(pallet_uniques::Call::burn { .. }) | RuntimeCall::Uniques(pallet_uniques::Call::freeze { .. }) | RuntimeCall::Uniques(pallet_uniques::Call::thaw { .. }) | RuntimeCall::Uniques(pallet_uniques::Call::freeze_collection { .. }) | RuntimeCall::Uniques(pallet_uniques::Call::thaw_collection { .. }) | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), ProxyType::Collator => matches!( c, RuntimeCall::CollatorSelection { .. } | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), } } fn is_superset(&self, o: &Self) -> bool { match (self, o) { (x, y) if x == y => true, (ProxyType::Any, _) => true, (_, ProxyType::Any) => false, (ProxyType::Assets, ProxyType::AssetOwner) => true, (ProxyType::Assets, ProxyType::AssetManager) => true, (ProxyType::NonTransfer, ProxyType::Collator) => true, _ => false, } } } impl pallet_proxy::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; type ProxyType = ProxyType; type ProxyDepositBase = ProxyDepositBase; type ProxyDepositFactor = ProxyDepositFactor; type MaxProxies = MaxProxies; type WeightInfo = weights::pallet_proxy::WeightInfo; type MaxPending = MaxPending; type CallHasher = BlakeTwo256; type AnnouncementDepositBase = AnnouncementDepositBase; type AnnouncementDepositFactor = AnnouncementDepositFactor; } parameter_types! { pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); } impl cumulus_pallet_parachain_system::Config for Runtime { type WeightInfo = weights::cumulus_pallet_parachain_system::WeightInfo; type RuntimeEvent = RuntimeEvent; type OnSystemEvent = (); type SelfParaId = parachain_info::Pallet; type DmpQueue = frame_support::traits::EnqueueWithOrigin; type ReservedDmpWeight = ReservedDmpWeight; type OutboundXcmpMessageSource = XcmpQueue; type XcmpMessageHandler = XcmpQueue; type ReservedXcmpWeight = ReservedXcmpWeight; type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; type ConsensusHook = cumulus_pallet_aura_ext::FixedVelocityConsensusHook< Runtime, RELAY_CHAIN_SLOT_DURATION_MILLIS, BLOCK_PROCESSING_VELOCITY, UNINCLUDED_SEGMENT_CAPACITY, >; } impl parachain_info::Config for Runtime {} parameter_types! { pub MessageQueueServiceWeight: Weight = Perbill::from_percent(35) * RuntimeBlockWeights::get().max_block; } impl pallet_message_queue::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = weights::pallet_message_queue::WeightInfo; #[cfg(feature = "runtime-benchmarks")] type MessageProcessor = pallet_message_queue::mock_helpers::NoopMessageProcessor< cumulus_primitives_core::AggregateMessageOrigin, >; #[cfg(not(feature = "runtime-benchmarks"))] type MessageProcessor = xcm_builder::ProcessXcmMessage< AggregateMessageOrigin, xcm_executor::XcmExecutor, RuntimeCall, >; type Size = u32; // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; } impl cumulus_pallet_aura_ext::Config for Runtime {} parameter_types! { /// The asset ID for the asset that we use to pay for message delivery fees. pub FeeAssetId: AssetId = AssetId(xcm_config::WestendLocation::get()); /// The base fee for the message delivery fees. pub const BaseDeliveryFee: u128 = CENTS.saturating_mul(3); } pub type PriceForSiblingParachainDelivery = polkadot_runtime_common::xcm_sender::ExponentialPrice< FeeAssetId, BaseDeliveryFee, TransactionByteFee, XcmpQueue, >; impl cumulus_pallet_xcmp_queue::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ChannelInfo = ParachainSystem; type VersionWrapper = PolkadotXcm; // Enqueue XCMP messages from siblings for later processing. type XcmpQueue = TransformOrigin; type MaxInboundSuspended = sp_core::ConstU32<1_000>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } parameter_types! { pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent; } parameter_types! { pub const Period: u32 = 6 * HOURS; pub const Offset: u32 = 0; } impl pallet_session::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ValidatorId = ::AccountId; // we don't have stash and controller, thus we don't need the convert as well. type ValidatorIdOf = pallet_collator_selection::IdentityCollator; type ShouldEndSession = pallet_session::PeriodicSessions; type NextSessionRotation = pallet_session::PeriodicSessions; type SessionManager = CollatorSelection; // Essentially just Aura, but let's be pedantic. type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; type WeightInfo = weights::pallet_session::WeightInfo; } impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; type AllowMultipleBlocksPerSlot = ConstBool; #[cfg(feature = "experimental")] type SlotDuration = pallet_aura::MinimumPeriodTimesTwo; } parameter_types! { pub const PotId: PalletId = PalletId(*b"PotStake"); pub const SessionLength: BlockNumber = 6 * HOURS; } pub type CollatorSelectionUpdateOrigin = EnsureRoot; impl pallet_collator_selection::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; type UpdateOrigin = CollatorSelectionUpdateOrigin; type PotId = PotId; type MaxCandidates = ConstU32<100>; type MinEligibleCollators = ConstU32<4>; type MaxInvulnerables = ConstU32<20>; // should be a multiple of session or things will get inconsistent type KickThreshold = Period; type ValidatorId = ::AccountId; type ValidatorIdOf = pallet_collator_selection::IdentityCollator; type ValidatorRegistration = Session; type WeightInfo = weights::pallet_collator_selection::WeightInfo; } impl pallet_asset_conversion_tx_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Fungibles = LocalAndForeignAssets; type OnChargeAssetTransaction = AssetConversionAdapter; } parameter_types! { pub const UniquesCollectionDeposit: Balance = UNITS / 10; // 1 / 10 UNIT deposit to create a collection pub const UniquesItemDeposit: Balance = UNITS / 1_000; // 1 / 1000 UNIT deposit to mint an item pub const UniquesMetadataDepositBase: Balance = deposit(1, 129); pub const UniquesAttributeDepositBase: Balance = deposit(1, 0); pub const UniquesDepositPerByte: Balance = deposit(0, 1); } impl pallet_uniques::Config for Runtime { type RuntimeEvent = RuntimeEvent; type CollectionId = CollectionId; type ItemId = ItemId; type Currency = Balances; type ForceOrigin = AssetsForceOrigin; type CollectionDeposit = UniquesCollectionDeposit; type ItemDeposit = UniquesItemDeposit; type MetadataDepositBase = UniquesMetadataDepositBase; type AttributeDepositBase = UniquesAttributeDepositBase; type DepositPerByte = UniquesDepositPerByte; type StringLimit = ConstU32<128>; type KeyLimit = ConstU32<32>; type ValueLimit = ConstU32<64>; type WeightInfo = weights::pallet_uniques::WeightInfo; #[cfg(feature = "runtime-benchmarks")] type Helper = (); type CreateOrigin = AsEnsureOriginWithArg>; type Locker = (); } parameter_types! { pub const NftFractionalizationPalletId: PalletId = PalletId(*b"fraction"); pub NewAssetSymbol: BoundedVec = (*b"FRAC").to_vec().try_into().unwrap(); pub NewAssetName: BoundedVec = (*b"Frac").to_vec().try_into().unwrap(); } impl pallet_nft_fractionalization::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Deposit = AssetDeposit; type Currency = Balances; type NewAssetSymbol = NewAssetSymbol; type NewAssetName = NewAssetName; type StringLimit = AssetsStringLimit; type NftCollectionId = ::CollectionId; type NftId = ::ItemId; type AssetBalance = ::Balance; type AssetId = >::AssetId; type Assets = Assets; type Nfts = Nfts; type PalletId = NftFractionalizationPalletId; type WeightInfo = pallet_nft_fractionalization::weights::SubstrateWeight; type RuntimeHoldReason = RuntimeHoldReason; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); } parameter_types! { pub NftsPalletFeatures: PalletFeatures = PalletFeatures::all_enabled(); pub const NftsMaxDeadlineDuration: BlockNumber = 12 * 30 * DAYS; // re-use the Uniques deposits pub const NftsCollectionDeposit: Balance = UniquesCollectionDeposit::get(); pub const NftsItemDeposit: Balance = UniquesItemDeposit::get(); pub const NftsMetadataDepositBase: Balance = UniquesMetadataDepositBase::get(); pub const NftsAttributeDepositBase: Balance = UniquesAttributeDepositBase::get(); pub const NftsDepositPerByte: Balance = UniquesDepositPerByte::get(); } impl pallet_nfts::Config for Runtime { type RuntimeEvent = RuntimeEvent; type CollectionId = CollectionId; type ItemId = ItemId; type Currency = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = AssetsForceOrigin; type Locker = (); type CollectionDeposit = NftsCollectionDeposit; type ItemDeposit = NftsItemDeposit; type MetadataDepositBase = NftsMetadataDepositBase; type AttributeDepositBase = NftsAttributeDepositBase; type DepositPerByte = NftsDepositPerByte; type StringLimit = ConstU32<256>; type KeyLimit = ConstU32<64>; type ValueLimit = ConstU32<256>; type ApprovalsLimit = ConstU32<20>; type ItemAttributesApprovalsLimit = ConstU32<30>; type MaxTips = ConstU32<10>; type MaxDeadlineDuration = NftsMaxDeadlineDuration; type MaxAttributesPerCall = ConstU32<10>; type Features = NftsPalletFeatures; type OffchainSignature = Signature; type OffchainPublic = ::Signer; type WeightInfo = weights::pallet_nfts::WeightInfo; #[cfg(feature = "runtime-benchmarks")] type Helper = (); } /// XCM router instance to BridgeHub with bridging capabilities for `Rococo` global /// consensus with dynamic fees and back-pressure. pub type ToRococoXcmRouterInstance = pallet_xcm_bridge_hub_router::Instance1; impl pallet_xcm_bridge_hub_router::Config for Runtime { type WeightInfo = weights::pallet_xcm_bridge_hub_router::WeightInfo; type UniversalLocation = xcm_config::UniversalLocation; type BridgedNetworkId = xcm_config::bridging::to_rococo::RococoNetwork; type Bridges = xcm_config::bridging::NetworkExportTable; type DestinationVersion = PolkadotXcm; #[cfg(not(feature = "runtime-benchmarks"))] type BridgeHubOrigin = EnsureXcm>; #[cfg(feature = "runtime-benchmarks")] type BridgeHubOrigin = frame_support::traits::EitherOfDiverse< // for running benchmarks EnsureRoot, // for running tests with `--feature runtime-benchmarks` EnsureXcm>, >; type ToBridgeHubSender = XcmpQueue; type WithBridgeHubChannel = cumulus_pallet_xcmp_queue::bridging::InAndOutXcmpChannelStatusProvider< xcm_config::bridging::SiblingBridgeHubParaId, Runtime, >; type ByteFee = xcm_config::bridging::XcmBridgeHubRouterByteFee; type FeeAsset = xcm_config::bridging::XcmBridgeHubRouterFeeAssetId; } // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime { // System support stuff. System: frame_system = 0, ParachainSystem: cumulus_pallet_parachain_system = 1, // RandomnessCollectiveFlip = 2 removed Timestamp: pallet_timestamp = 3, ParachainInfo: parachain_info = 4, // Monetary stuff. Balances: pallet_balances = 10, TransactionPayment: pallet_transaction_payment = 11, // AssetTxPayment: pallet_asset_tx_payment = 12, AssetTxPayment: pallet_asset_conversion_tx_payment = 13, // Collator support. the order of these 5 are important and shall not change. Authorship: pallet_authorship = 20, CollatorSelection: pallet_collator_selection = 21, Session: pallet_session = 22, Aura: pallet_aura = 23, AuraExt: cumulus_pallet_aura_ext = 24, // XCM helpers. XcmpQueue: cumulus_pallet_xcmp_queue = 30, PolkadotXcm: pallet_xcm = 31, CumulusXcm: cumulus_pallet_xcm = 32, // Bridge utilities. ToRococoXcmRouter: pallet_xcm_bridge_hub_router:: = 34, MessageQueue: pallet_message_queue = 35, // Handy utilities. Utility: pallet_utility = 40, Multisig: pallet_multisig = 41, Proxy: pallet_proxy = 42, // The main stage. Assets: pallet_assets:: = 50, Uniques: pallet_uniques = 51, Nfts: pallet_nfts = 52, ForeignAssets: pallet_assets:: = 53, NftFractionalization: pallet_nft_fractionalization = 54, PoolAssets: pallet_assets:: = 55, AssetConversion: pallet_asset_conversion = 56, } ); /// The address format for describing accounts. pub type Address = sp_runtime::MultiAddress; /// Block type as expected by this runtime. pub type Block = generic::Block; /// A Block signed with a Justification pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, frame_system::CheckGenesis, frame_system::CheckEra, frame_system::CheckNonce, frame_system::CheckWeight, pallet_asset_conversion_tx_payment::ChargeAssetTxPayment, ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( // v9420 pallet_nfts::migration::v1::MigrateToV1, // unreleased pallet_collator_selection::migration::v1::MigrateToV1, // unreleased pallet_multisig::migrations::v1::MigrateToV1, // unreleased InitStorageVersions, // unreleased DeleteUndecodableStorage, // unreleased cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, ); /// Asset Hub Westend has some undecodable storage, delete it. /// See for more info. /// /// First we remove the bad Hold, then the bad NFT collection. pub struct DeleteUndecodableStorage; impl frame_support::traits::OnRuntimeUpgrade for DeleteUndecodableStorage { fn on_runtime_upgrade() -> Weight { use sp_core::crypto::Ss58Codec; let mut writes = 0; // Remove Holds for account with undecodable hold // Westend doesn't have any HoldReasons implemented yet, so it's safe to just blanket remove // any for this account. match AccountId::from_ss58check("5GCCJthVSwNXRpbeg44gysJUx9vzjdGdfWhioeM7gCg6VyXf") { Ok(a) => { log::info!("Removing holds for account with bad hold"); pallet_balances::Holds::::remove(a); writes.saturating_inc(); }, Err(_) => { log::error!("CleanupUndecodableStorage: Somehow failed to convert valid SS58 address into an AccountId!"); }, }; // Destroy undecodable NFT item 1 writes.saturating_inc(); match pallet_nfts::Pallet::::do_burn(3, 1, |_| Ok(())) { Ok(_) => { log::info!("Destroyed undecodable NFT item 1"); }, Err(e) => { log::error!("Failed to destroy undecodable NFT item: {:?}", e); return ::DbWeight::get().reads_writes(0, writes) }, } // Destroy undecodable NFT item 2 writes.saturating_inc(); match pallet_nfts::Pallet::::do_burn(3, 2, |_| Ok(())) { Ok(_) => { log::info!("Destroyed undecodable NFT item 2"); }, Err(e) => { log::error!("Failed to destroy undecodable NFT item: {:?}", e); return ::DbWeight::get().reads_writes(0, writes) }, } // Finally, we can destroy the collection writes.saturating_inc(); match pallet_nfts::Pallet::::do_destroy_collection( 3, DestroyWitness { attributes: 0, item_metadatas: 1, item_configs: 0 }, None, ) { Ok(_) => { log::info!("Destroyed undecodable NFT collection"); }, Err(e) => { log::error!("Failed to destroy undecodable NFT collection: {:?}", e); }, }; ::DbWeight::get().reads_writes(0, writes) } } /// Migration to initialize storage versions for pallets added after genesis. /// /// Ideally this would be done automatically (see /// ), but it probably won't be ready for some /// time and it's beneficial to get try-runtime-cli on-runtime-upgrade checks into the CI, so we're /// doing it manually. pub struct InitStorageVersions; impl frame_support::traits::OnRuntimeUpgrade for InitStorageVersions { fn on_runtime_upgrade() -> Weight { use frame_support::traits::{GetStorageVersion, StorageVersion}; let mut writes = 0; if PolkadotXcm::on_chain_storage_version() == StorageVersion::new(0) { PolkadotXcm::current_storage_version().put::(); writes.saturating_inc(); } if ForeignAssets::on_chain_storage_version() == StorageVersion::new(0) { ForeignAssets::current_storage_version().put::(); writes.saturating_inc(); } if PoolAssets::on_chain_storage_version() == StorageVersion::new(0) { PoolAssets::current_storage_version().put::(); writes.saturating_inc(); } ::DbWeight::get().reads_writes(3, writes) } } /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, Block, frame_system::ChainContext, Runtime, AllPalletsWithSystem, Migrations, >; #[cfg(feature = "runtime-benchmarks")] mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] [pallet_assets, Local] [pallet_assets, Foreign] [pallet_assets, Pool] [pallet_asset_conversion, AssetConversion] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] [pallet_multisig, Multisig] [pallet_nft_fractionalization, NftFractionalization] [pallet_nfts, Nfts] [pallet_proxy, Proxy] [pallet_session, SessionBench::] [pallet_uniques, Uniques] [pallet_utility, Utility] [pallet_timestamp, Timestamp] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_xcmp_queue, XcmpQueue] [pallet_xcm_bridge_hub_router, ToRococo] // XCM [pallet_xcm, PalletXcmExtrinsicsBenchmark::] // NOTE: Make sure you point to the individual modules below. [pallet_xcm_benchmarks::fungible, XcmBalances] [pallet_xcm_benchmarks::generic, XcmGeneric] ); } impl_runtime_apis! { impl sp_consensus_aura::AuraApi for Runtime { fn slot_duration() -> sp_consensus_aura::SlotDuration { sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) } fn authorities() -> Vec { Aura::authorities().into_inner() } } impl sp_api::Core for Runtime { fn version() -> RuntimeVersion { VERSION } fn execute_block(block: Block) { Executive::execute_block(block) } fn initialize_block(header: &::Header) { Executive::initialize_block(header) } } impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { OpaqueMetadata::new(Runtime::metadata().into()) } fn metadata_at_version(version: u32) -> Option { Runtime::metadata_at_version(version) } fn metadata_versions() -> sp_std::vec::Vec { Runtime::metadata_versions() } } impl sp_block_builder::BlockBuilder for Runtime { fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { Executive::apply_extrinsic(extrinsic) } fn finalize_block() -> ::Header { Executive::finalize_block() } fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { data.create_extrinsics() } fn check_inherents( block: Block, data: sp_inherents::InherentData, ) -> sp_inherents::CheckInherentsResult { data.check_extrinsics(&block) } } impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { fn validate_transaction( source: TransactionSource, tx: ::Extrinsic, block_hash: ::Hash, ) -> TransactionValidity { Executive::validate_transaction(source, tx, block_hash) } } impl sp_offchain::OffchainWorkerApi for Runtime { fn offchain_worker(header: &::Header) { Executive::offchain_worker(header) } } impl sp_session::SessionKeys for Runtime { fn generate_session_keys(seed: Option>) -> Vec { SessionKeys::generate(seed) } fn decode_session_keys( encoded: Vec, ) -> Option, KeyTypeId)>> { SessionKeys::decode_into_raw_public_keys(&encoded) } } impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { fn account_nonce(account: AccountId) -> Nonce { System::account_nonce(account) } } impl pallet_nfts_runtime_api::NftsApi for Runtime { fn owner(collection: u32, item: u32) -> Option { >::owner(&collection, &item) } fn collection_owner(collection: u32) -> Option { >::collection_owner(&collection) } fn attribute( collection: u32, item: u32, key: Vec, ) -> Option> { >::attribute(&collection, &item, &key) } fn custom_attribute( account: AccountId, collection: u32, item: u32, key: Vec, ) -> Option> { >::custom_attribute( &account, &collection, &item, &key, ) } fn system_attribute( collection: u32, item: Option, key: Vec, ) -> Option> { >::system_attribute(&collection, item.as_ref(), &key) } fn collection_attribute(collection: u32, key: Vec) -> Option> { >::collection_attribute(&collection, &key) } } impl pallet_asset_conversion::AssetConversionApi< Block, Balance, xcm::v3::Location, > for Runtime { fn quote_price_exact_tokens_for_tokens(asset1: xcm::v3::Location, asset2: xcm::v3::Location, amount: Balance, include_fee: bool) -> Option { AssetConversion::quote_price_exact_tokens_for_tokens(asset1, asset2, amount, include_fee) } fn quote_price_tokens_for_exact_tokens(asset1: xcm::v3::Location, asset2: xcm::v3::Location, amount: Balance, include_fee: bool) -> Option { AssetConversion::quote_price_tokens_for_exact_tokens(asset1, asset2, amount, include_fee) } fn get_reserves(asset1: xcm::v3::Location, asset2: xcm::v3::Location) -> Option<(Balance, Balance)> { AssetConversion::get_reserves(asset1, asset2).ok() } } impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { fn query_info( uxt: ::Extrinsic, len: u32, ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { TransactionPayment::query_info(uxt, len) } fn query_fee_details( uxt: ::Extrinsic, len: u32, ) -> pallet_transaction_payment::FeeDetails { TransactionPayment::query_fee_details(uxt, len) } fn query_weight_to_fee(weight: Weight) -> Balance { TransactionPayment::weight_to_fee(weight) } fn query_length_to_fee(length: u32) -> Balance { TransactionPayment::length_to_fee(length) } } impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi for Runtime { fn query_call_info( call: RuntimeCall, len: u32, ) -> pallet_transaction_payment::RuntimeDispatchInfo { TransactionPayment::query_call_info(call, len) } fn query_call_fee_details( call: RuntimeCall, len: u32, ) -> pallet_transaction_payment::FeeDetails { TransactionPayment::query_call_fee_details(call, len) } fn query_weight_to_fee(weight: Weight) -> Balance { TransactionPayment::weight_to_fee(weight) } fn query_length_to_fee(length: u32) -> Balance { TransactionPayment::length_to_fee(length) } } impl assets_common::runtime_api::FungiblesApi< Block, AccountId, > for Runtime { fn query_account_balances(account: AccountId) -> Result { use assets_common::fungible_conversion::{convert, convert_balance}; Ok([ // collect pallet_balance { let balance = Balances::free_balance(account.clone()); if balance > 0 { vec![convert_balance::(balance)?] } else { vec![] } }, // collect pallet_assets (TrustBackedAssets) convert::<_, _, _, _, TrustBackedAssetsConvertedConcreteId>( Assets::account_balances(account.clone()) .iter() .filter(|(_, balance)| balance > &0) )?, // collect pallet_assets (ForeignAssets) convert::<_, _, _, _, ForeignAssetsConvertedConcreteId>( ForeignAssets::account_balances(account.clone()) .iter() .filter(|(_, balance)| balance > &0) )?, // collect pallet_assets (PoolAssets) convert::<_, _, _, _, PoolAssetsConvertedConcreteId>( PoolAssets::account_balances(account) .iter() .filter(|(_, balance)| balance > &0) )?, // collect ... e.g. other tokens ].concat().into()) } } impl cumulus_primitives_core::CollectCollationInfo for Runtime { fn collect_collation_info(header: &::Header) -> cumulus_primitives_core::CollationInfo { ParachainSystem::collect_collation_info(header) } } #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { let weight = Executive::try_runtime_upgrade(checks).unwrap(); (weight, RuntimeBlockWeights::get().max_block) } fn execute_block( block: Block, state_root_check: bool, signature_check: bool, select: frame_try_runtime::TryStateSelect, ) -> Weight { // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to // have a backtrace here. Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap() } } #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { fn benchmark_metadata(extra: bool) -> ( Vec, Vec, ) { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; use pallet_xcm_bridge_hub_router::benchmarking::Pallet as XcmBridgeHubRouterBench; // This is defined once again in dispatch_benchmark, because list_benchmarks! // and add_benchmarks! are macros exported by define_benchmarks! macros and those types // are referenced in that call. type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::; type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::; // Benchmark files generated for `Assets/ForeignAssets` instances are by default // `pallet_assets_assets.rs / pallet_assets_foreign_assets`, which is not really nice, // so with this redefinition we can change names to nicer: // `pallet_assets_local.rs / pallet_assets_foreign.rs`. type Local = pallet_assets::Pallet::; type Foreign = pallet_assets::Pallet::; type Pool = pallet_assets::Pallet::; type ToRococo = XcmBridgeHubRouterBench; let mut list = Vec::::new(); list_benchmarks!(list, extra); let storage_info = AllPalletsWithSystem::storage_info(); (list, storage_info) } fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig ) -> Result, sp_runtime::RuntimeString> { use frame_benchmarking::{Benchmarking, BenchmarkBatch, BenchmarkError}; use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; impl frame_system_benchmarking::Config for Runtime { fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); Ok(()) } fn verify_set_code() { System::assert_last_event(cumulus_pallet_parachain_system::Event::::ValidationFunctionStored.into()); } } use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; impl pallet_xcm::benchmarking::Config for Runtime { fn reachable_dest() -> Option { Some(Parent.into()) } fn teleportable_asset_and_dest() -> Option<(Asset, Location)> { // Relay/native token can be teleported between AH and Relay. Some(( Asset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: AssetId(Parent.into()) }, Parent.into(), )) } fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> { // AH can reserve transfer native token to some random parachain. let random_para_id = 43211234; ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( random_para_id.into() ); Some(( Asset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: AssetId(Parent.into()) }, ParentThen(Parachain(random_para_id).into()).into(), )) } fn set_up_complex_asset_transfer( ) -> Option<(xcm::v4::Assets, u32, Location, Box)> { // Transfer to Relay some local AH asset (local-reserve-transfer) while paying // fees using teleported native token. // (We don't care that Relay doesn't accept incoming unknown AH local asset) let dest = Parent.into(); let fee_amount = EXISTENTIAL_DEPOSIT; let fee_asset: Asset = (Location::parent(), fee_amount).into(); let who = frame_benchmarking::whitelisted_caller(); // Give some multiple of the existential deposit let balance = fee_amount + EXISTENTIAL_DEPOSIT * 1000; let _ = >::make_free_balance_be( &who, balance, ); // verify initial balance assert_eq!(Balances::free_balance(&who), balance); // set up local asset let asset_amount = 10u128; let initial_asset_amount = asset_amount * 10; let (asset_id, _, _) = pallet_assets::benchmarking::create_default_minted_asset::< Runtime, pallet_assets::Instance1 >(true, initial_asset_amount); let asset_location = Location::new( 0, [PalletInstance(50), GeneralIndex(u32::from(asset_id).into())] ); let transfer_asset: Asset = (asset_location, asset_amount).into(); let assets: xcm::v4::Assets = vec![fee_asset.clone(), transfer_asset].into(); let fee_index = if assets.get(0).unwrap().eq(&fee_asset) { 0 } else { 1 }; // verify transferred successfully let verify = Box::new(move || { // verify native balance after transfer, decreased by transferred fee amount // (plus transport fees) assert!(Balances::free_balance(&who) <= balance - fee_amount); // verify asset balance decreased by exactly transferred amount assert_eq!( Assets::balance(asset_id.into(), &who), initial_asset_amount - asset_amount, ); }); Some((assets, fee_index as u32, dest, verify)) } } use pallet_xcm_bridge_hub_router::benchmarking::{ Pallet as XcmBridgeHubRouterBench, Config as XcmBridgeHubRouterConfig, }; impl XcmBridgeHubRouterConfig for Runtime { fn make_congested() { cumulus_pallet_xcmp_queue::bridging::suspend_channel_for_benchmarks::( xcm_config::bridging::SiblingBridgeHubParaId::get().into() ); } fn ensure_bridged_target_destination() -> Result { ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( xcm_config::bridging::SiblingBridgeHubParaId::get().into() ); let bridged_asset_hub = xcm_config::bridging::to_rococo::AssetHubRococo::get(); let _ = PolkadotXcm::force_xcm_version( RuntimeOrigin::root(), Box::new(bridged_asset_hub.clone()), XCM_VERSION, ).map_err(|e| { log::error!( "Failed to dispatch `force_xcm_version({:?}, {:?}, {:?})`, error: {:?}", RuntimeOrigin::root(), bridged_asset_hub, XCM_VERSION, e ); BenchmarkError::Stop("XcmVersion was not stored!") })?; Ok(bridged_asset_hub) } } use xcm_config::{MaxAssetsIntoHolding, WestendLocation}; use pallet_xcm_benchmarks::asset_instance_from; parameter_types! { pub ExistentialDepositAsset: Option = Some(( WestendLocation::get(), ExistentialDeposit::get() ).into()); } impl pallet_xcm_benchmarks::Config for Runtime { type XcmConfig = xcm_config::XcmConfig; type AccountIdConverter = xcm_config::LocationToAccountId; type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper< xcm_config::XcmConfig, ExistentialDepositAsset, xcm_config::PriceForParentDelivery, >; fn valid_destination() -> Result { Ok(WestendLocation::get()) } fn worst_case_holding(depositable_count: u32) -> xcm::v4::Assets { // A mix of fungible, non-fungible, and concrete assets. let holding_non_fungibles = MaxAssetsIntoHolding::get() / 2 - depositable_count; let holding_fungibles = holding_non_fungibles - 1; let fungibles_amount: u128 = 100; let mut assets = (0..holding_fungibles) .map(|i| { Asset { id: AssetId(GeneralIndex(i as u128).into()), fun: Fungible(fungibles_amount * i as u128), } }) .chain(core::iter::once(Asset { id: AssetId(Here.into()), fun: Fungible(u128::MAX) })) .chain((0..holding_non_fungibles).map(|i| Asset { id: AssetId(GeneralIndex(i as u128).into()), fun: NonFungible(asset_instance_from(i)), })) .collect::>(); assets.push(Asset { id: AssetId(WestendLocation::get()), fun: Fungible(1_000_000 * UNITS), }); assets.into() } } parameter_types! { pub const TrustedTeleporter: Option<(Location, Asset)> = Some(( WestendLocation::get(), Asset { fun: Fungible(UNITS), id: AssetId(WestendLocation::get()) }, )); pub const CheckedAccount: Option<(AccountId, xcm_builder::MintLocation)> = None; // AssetHubWestend trusts AssetHubRococo as reserve for ROCs pub TrustedReserve: Option<(Location, Asset)> = Some( ( xcm_config::bridging::to_rococo::AssetHubRococo::get(), Asset::from((xcm_config::bridging::to_rococo::RocLocation::get(), 1000000000000 as u128)) ) ); } impl pallet_xcm_benchmarks::fungible::Config for Runtime { type TransactAsset = Balances; type CheckedAccount = CheckedAccount; type TrustedTeleporter = TrustedTeleporter; type TrustedReserve = TrustedReserve; fn get_asset() -> Asset { Asset { id: AssetId(WestendLocation::get()), fun: Fungible(UNITS), } } } impl pallet_xcm_benchmarks::generic::Config for Runtime { type TransactAsset = Balances; type RuntimeCall = RuntimeCall; fn worst_case_response() -> (u64, Response) { (0u64, Response::Version(Default::default())) } fn worst_case_asset_exchange() -> Result<(xcm::v4::Assets, xcm::v4::Assets), BenchmarkError> { Err(BenchmarkError::Skip) } fn universal_alias() -> Result<(Location, Junction), BenchmarkError> { match xcm_config::bridging::BridgingBenchmarksHelper::prepare_universal_alias() { Some(alias) => Ok(alias), None => Err(BenchmarkError::Skip) } } fn transact_origin_and_runtime_call() -> Result<(Location, RuntimeCall), BenchmarkError> { Ok((WestendLocation::get(), frame_system::Call::remark_with_event { remark: vec![] }.into())) } fn subscribe_origin() -> Result { Ok(WestendLocation::get()) } fn claimable_asset() -> Result<(Location, Location, xcm::v4::Assets), BenchmarkError> { let origin = WestendLocation::get(); let assets: xcm::v4::Assets = (AssetId(WestendLocation::get()), 1_000 * UNITS).into(); let ticket = Location { parents: 0, interior: Here }; Ok((origin, ticket, assets)) } fn fee_asset() -> Result { Ok(Asset { id: AssetId(WestendLocation::get()), fun: Fungible(1_000_000 * UNITS), }) } fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> { Err(BenchmarkError::Skip) } fn export_message_origin_and_destination( ) -> Result<(Location, NetworkId, InteriorLocation), BenchmarkError> { Err(BenchmarkError::Skip) } fn alias_origin() -> Result<(Location, Location), BenchmarkError> { Err(BenchmarkError::Skip) } } type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::; type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::; type Local = pallet_assets::Pallet::; type Foreign = pallet_assets::Pallet::; type Pool = pallet_assets::Pallet::; type ToRococo = XcmBridgeHubRouterBench; let whitelist: Vec = vec![ // Block Number hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), // Total Issuance hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(), // Execution Phase hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(), // Event Count hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(), // System Events hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(), //TODO: use from relay_well_known_keys::ACTIVE_CONFIG hex_literal::hex!("06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385").to_vec().into(), ]; let mut batches = Vec::::new(); let params = (&config, &whitelist); add_benchmarks!(params, batches); Ok(batches) } } impl sp_genesis_builder::GenesisBuilder for Runtime { fn create_default_config() -> Vec { create_default_config::() } fn build_config(config: Vec) -> sp_genesis_builder::Result { build_config::(config) } } } cumulus_pallet_parachain_system::register_validate_block! { Runtime = Runtime, BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, }