1234567891011121314151617use frame_support::{18 traits::{19 tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Get, Everything,20 },21 weights::{Weight, WeightToFeePolynomial, WeightToFee},22 parameter_types, match_types,23};24use frame_system::EnsureRoot;25use sp_runtime::{26 traits::{Saturating, CheckedConversion, Zero},27 SaturatedConversion,28};29use pallet_xcm::XcmPassthrough;30use polkadot_parachain::primitives::Sibling;31use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};32use xcm::latest::{33 AssetId::{Concrete},34 Fungibility::Fungible as XcmFungible,35 MultiAsset, Error as XcmError,36};37use xcm_executor::traits::{MatchesFungible, WeightTrader};38use xcm_builder::{39 AccountId32Aliases, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, EnsureXcmOrigin,40 FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser, RelayChainAsNative,41 SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,42 SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, ParentIsPreset,43};44use xcm_executor::{Config, XcmExecutor, Assets};45use sp_std::marker::PhantomData;46use crate::{47 runtime_common::{constants::*, config::substrate::LinearFee},48 Runtime, Call, Event, Origin, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, XcmpQueue,49};50use common_types::{AccountId, Balance};5152parameter_types! {53 pub const RelayLocation: MultiLocation = MultiLocation::parent();54 pub const RelayNetwork: NetworkId = NetworkId::Polkadot;55 pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();56 pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();57}5859606162pub type LocationToAccountId = (63 64 ParentIsPreset<AccountId>,65 66 SiblingParachainConvertsVia<Sibling, AccountId>,67 68 AccountId32Aliases<RelayNetwork, AccountId>,69);7071pub struct OnlySelfCurrency;72impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {73 fn matches_fungible(a: &MultiAsset) -> Option<B> {74 match (&a.id, &a.fun) {75 (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),76 _ => None,77 }78 }79}808182pub type LocalAssetTransactor = CurrencyAdapter<83 84 Balances,85 86 OnlySelfCurrency,87 88 LocationToAccountId,89 90 AccountId,91 92 (),93>;949596pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);979899100pub type XcmRouter = (101 102 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,103 104 XcmpQueue,105);106107108109110pub type XcmOriginToTransactDispatchOrigin = (111 112 113 114 SovereignSignedViaLocation<LocationToAccountId, Origin>,115 116 117 RelayChainAsNative<RelayOrigin, Origin>,118 119 120 SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,121 122 123 ParentAsSuperuser<Origin>,124 125 126 SignedAccountId32AsNative<RelayNetwork, Origin>,127 128 XcmPassthrough<Origin>,129);130131parameter_types! {132 133 pub UnitWeightCost: Weight = 1_000_000;134 135 pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);136 pub const MaxInstructions: u32 = 100;137}138139match_types! {140 pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {141 MultiLocation { parents: 1, interior: Here } |142 MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }143 };144}145146pub type Barrier = (147 TakeWeightCredit,148 AllowTopLevelPaidExecutionFrom<Everything>,149 150);151152pub struct UsingOnlySelfCurrencyComponents<153 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,154 AssetId: Get<MultiLocation>,155 AccountId,156 Currency: CurrencyT<AccountId>,157 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,158>(159 Weight,160 Currency::Balance,161 PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,162);163impl<164 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,165 AssetId: Get<MultiLocation>,166 AccountId,167 Currency: CurrencyT<AccountId>,168 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,169 > WeightTrader170 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>171{172 fn new() -> Self {173 Self(0, Zero::zero(), PhantomData)174 }175176 fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {177 let amount = WeightToFee::weight_to_fee(&weight);178 let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;179180 181 let option1: xcm::v1::AssetId = Concrete(MultiLocation {182 parents: 1,183 interior: X1(Parachain(ParachainInfo::parachain_id().into())),184 });185 186 let option2: xcm::v1::AssetId = Concrete(MultiLocation {187 parents: 0,188 interior: Here,189 });190191 let required = if payment.fungible.contains_key(&option1) {192 (option1, u128_amount).into()193 } else if payment.fungible.contains_key(&option2) {194 (option2, u128_amount).into()195 } else {196 (Concrete(MultiLocation::default()), u128_amount).into()197 };198199 let unused = payment200 .checked_sub(required)201 .map_err(|_| XcmError::TooExpensive)?;202 self.0 = self.0.saturating_add(weight);203 self.1 = self.1.saturating_add(amount);204 Ok(unused)205 }206207 fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {208 let weight = weight.min(self.0);209 let amount = WeightToFee::weight_to_fee(&weight);210 self.0 -= weight;211 self.1 = self.1.saturating_sub(amount);212 let amount: u128 = amount.saturated_into();213 if amount > 0 {214 Some((AssetId::get(), amount).into())215 } else {216 None217 }218 }219}220impl<221 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,222 AssetId: Get<MultiLocation>,223 AccountId,224 Currency: CurrencyT<AccountId>,225 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,226 > Drop227 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>228{229 fn drop(&mut self) {230 OnUnbalanced::on_unbalanced(Currency::issue(self.1));231 }232}233234pub struct XcmConfig;235impl Config for XcmConfig {236 type Call = Call;237 type XcmSender = XcmRouter;238 239 type AssetTransactor = LocalAssetTransactor;240 type OriginConverter = XcmOriginToTransactDispatchOrigin;241 type IsReserve = NativeAsset;242 type IsTeleporter = (); 243 type LocationInverter = LocationInverter<Ancestry>;244 type Barrier = Barrier;245 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;246 type Trader =247 UsingOnlySelfCurrencyComponents<LinearFee<Balance>, RelayLocation, AccountId, Balances, ()>;248 type ResponseHandler = (); 249 type SubscriptionService = PolkadotXcm;250251 type AssetTrap = PolkadotXcm;252 type AssetClaims = PolkadotXcm;253}254255impl pallet_xcm::Config for Runtime {256 type Event = Event;257 type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;258 type XcmRouter = XcmRouter;259 type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;260 type XcmExecuteFilter = Everything;261 type XcmExecutor = XcmExecutor<XcmConfig>;262 type XcmTeleportFilter = Everything;263 type XcmReserveTransferFilter = Everything;264 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;265 type LocationInverter = LocationInverter<Ancestry>;266 type Origin = Origin;267 type Call = Call;268 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;269 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;270}271272impl cumulus_pallet_xcm::Config for Runtime {273 type Event = Event;274 type XcmExecutor = XcmExecutor<XcmConfig>;275}276277impl cumulus_pallet_xcmp_queue::Config for Runtime {278 type WeightInfo = ();279 type Event = Event;280 type XcmExecutor = XcmExecutor<XcmConfig>;281 type ChannelInfo = ParachainSystem;282 type VersionWrapper = ();283 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;284 type ControllerOrigin = EnsureRoot<AccountId>;285 type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;286}287288impl cumulus_pallet_dmp_queue::Config for Runtime {289 type Event = Event;290 type XcmExecutor = XcmExecutor<XcmConfig>;291 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;292}