1234567891011121314151617use frame_support::{18 traits::{19 Contains, tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Get,20 Everything, fungibles,21 },22 weights::{Weight, WeightToFeePolynomial, WeightToFee},23 parameter_types, match_types,24};25use frame_system::EnsureRoot;26use sp_runtime::{27 traits::{Saturating, CheckedConversion, Zero},28 SaturatedConversion,29};30use pallet_xcm::XcmPassthrough;31use polkadot_parachain::primitives::Sibling;32use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};33use xcm::latest::{34 AssetId::{Concrete},35 Fungibility::Fungible as XcmFungible,36 MultiAsset, Error as XcmError, Instruction, Xcm,37};38use xcm_builder::{39 AccountId32Aliases, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, EnsureXcmOrigin,40 FixedWeightBounds, FungiblesAdapter, LocationInverter, NativeAsset, ParentAsSuperuser,41 RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,42 SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,43 ParentIsPreset, ConvertedConcreteAssetId,44};45use xcm_executor::{Config, XcmExecutor, Assets};46use xcm_executor::traits::{47 Convert as ConvertXcm, JustTry, MatchesFungible, WeightTrader, FilterAssetLocation,48 ShouldExecute,49};50use pallet_foreing_assets::{51 AssetIds, AssetIdMapping, XcmForeignAssetIdMapping, CurrencyId, NativeCurrency, FreeForAll,52 TryAsForeing, ForeignAssetId,53};54use sp_std::{borrow::Borrow, marker::PhantomData, vec, vec::Vec};55use crate::{56 Runtime, Call, Event, Origin, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, XcmpQueue,57 xcm_config::Barrier,58};59#[cfg(feature = "foreign-assets")]60use crate::ForeingAssets;6162use up_common::{63 types::{AccountId, Balance},64 constants::*,65};6667parameter_types! {68 pub const RelayLocation: MultiLocation = MultiLocation::parent();69 pub const RelayNetwork: NetworkId = NetworkId::Polkadot;70 pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();71 pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();72}7374757677pub type LocationToAccountId = (78 79 ParentIsPreset<AccountId>,80 81 SiblingParachainConvertsVia<Sibling, AccountId>,82 83 AccountId32Aliases<RelayNetwork, AccountId>,84);8586pub struct OnlySelfCurrency;87impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {88 fn matches_fungible(a: &MultiAsset) -> Option<B> {89 let paraid = Parachain(ParachainInfo::parachain_id().into());90 match (&a.id, &a.fun) {91 (92 Concrete(MultiLocation {93 parents: 1,94 interior: X1(loc),95 }),96 XcmFungible(ref amount),97 ) if paraid == *loc => CheckedConversion::checked_from(*amount),98 (99 Concrete(MultiLocation {100 parents: 0,101 interior: Here,102 }),103 XcmFungible(ref amount),104 ) => CheckedConversion::checked_from(*amount),105 _ => None,106 }107 }108}109110111pub type LocalAssetTransactor = CurrencyAdapter<112 113 Balances,114 115 OnlySelfCurrency,116 117 LocationToAccountId,118 119 AccountId,120 121 (),122>;123124125pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);126127128129pub type XcmRouter = (130 131 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,132 133 XcmpQueue,134);135136137138139pub type XcmOriginToTransactDispatchOrigin = (140 141 142 143 SovereignSignedViaLocation<LocationToAccountId, Origin>,144 145 146 RelayChainAsNative<RelayOrigin, Origin>,147 148 149 SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,150 151 152 ParentAsSuperuser<Origin>,153 154 155 SignedAccountId32AsNative<RelayNetwork, Origin>,156 157 XcmPassthrough<Origin>,158);159160parameter_types! {161 162 pub UnitWeightCost: Weight = 1_000_000;163 164 pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);165 pub const MaxInstructions: u32 = 100;166}167168match_types! {169 pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {170 MultiLocation { parents: 1, interior: Here } |171 MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }172 };173}174175pub struct DenyTransact;176impl ShouldExecute for DenyTransact {177 fn should_execute<Call>(178 _origin: &MultiLocation,179 message: &mut Xcm<Call>,180 _max_weight: Weight,181 _weight_credit: &mut Weight,182 ) -> Result<(), ()> {183 let transact_inst = message184 .0185 .iter()186 .find(|inst| matches![inst, Instruction::Transact { .. }]);187188 match transact_inst {189 Some(_) => {190 log::warn!(191 target: "xcm::barrier",192 "transact XCM rejected"193 );194195 Err(())196 }197 None => Ok(()),198 }199 }200}201202203204pub struct DenyThenTry<Deny, Allow>(PhantomData<Deny>, PhantomData<Allow>)205where206 Deny: ShouldExecute,207 Allow: ShouldExecute;208209impl<Deny, Allow> ShouldExecute for DenyThenTry<Deny, Allow>210where211 Deny: ShouldExecute,212 Allow: ShouldExecute,213{214 fn should_execute<Call>(215 origin: &MultiLocation,216 message: &mut Xcm<Call>,217 max_weight: Weight,218 weight_credit: &mut Weight,219 ) -> Result<(), ()> {220 Deny::should_execute(origin, message, max_weight, weight_credit)?;221 Allow::should_execute(origin, message, max_weight, weight_credit)222 }223}224225pub struct UsingOnlySelfCurrencyComponents<226 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,227 AssetId: Get<MultiLocation>,228 AccountId,229 Currency: CurrencyT<AccountId>,230 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,231>(232 Weight,233 Currency::Balance,234 PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,235);236impl<237 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,238 AssetId: Get<MultiLocation>,239 AccountId,240 Currency: CurrencyT<AccountId>,241 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,242 > WeightTrader243 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>244{245 fn new() -> Self {246 Self(0, Zero::zero(), PhantomData)247 }248249 fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {250 Ok(payment)251 }252}253impl<254 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,255 AssetId: Get<MultiLocation>,256 AccountId,257 Currency: CurrencyT<AccountId>,258 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,259 > Drop260 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>261{262 fn drop(&mut self) {263 OnUnbalanced::on_unbalanced(Currency::issue(self.1));264 }265}266267parameter_types! {268 pub CheckingAccount: AccountId = PolkadotXcm::check_account();269}270271#[cfg(feature = "foreign-assets")]272pub struct NonZeroIssuance<AccountId, ForeingAssets>(PhantomData<(AccountId, ForeingAssets)>);273274#[cfg(feature = "foreign-assets")]275impl<AccountId, ForeingAssets> Contains<<ForeingAssets as fungibles::Inspect<AccountId>>::AssetId>276 for NonZeroIssuance<AccountId, ForeingAssets>277where278 ForeingAssets: fungibles::Inspect<AccountId>,279{280 fn contains(id: &<ForeingAssets as fungibles::Inspect<AccountId>>::AssetId) -> bool {281 !ForeingAssets::total_issuance(*id).is_zero()282 }283}284285#[cfg(feature = "foreign-assets")]286pub struct AsInnerId<AssetId, ConvertAssetId>(PhantomData<(AssetId, ConvertAssetId)>);287#[cfg(feature = "foreign-assets")]288impl<AssetId: Clone + PartialEq, ConvertAssetId: ConvertXcm<AssetId, AssetId>>289 ConvertXcm<MultiLocation, AssetId> for AsInnerId<AssetId, ConvertAssetId>290where291 AssetId: Borrow<AssetId>,292 AssetId: TryAsForeing<AssetId, ForeignAssetId>,293 AssetIds: Borrow<AssetId>,294{295 fn convert_ref(id: impl Borrow<MultiLocation>) -> Result<AssetId, ()> {296 let id = id.borrow();297298 log::trace!(299 target: "xcm::AsInnerId::Convert",300 "AsInnerId {:?}",301 id302 );303304 let parent = MultiLocation::parent();305 let here = MultiLocation::here();306 let self_location = MultiLocation::new(1, X1(Parachain(ParachainInfo::get().into())));307308 if *id == parent {309 return ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Parent));310 }311312 if *id == here || *id == self_location {313 return ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Here));314 }315316 match XcmForeignAssetIdMapping::<Runtime>::get_currency_id(id.clone()) {317 Some(AssetIds::ForeignAssetId(foreign_asset_id)) => {318 ConvertAssetId::convert_ref(AssetIds::ForeignAssetId(foreign_asset_id))319 }320 _ => ConvertAssetId::convert_ref(AssetIds::ForeignAssetId(0)),321 }322 }323324 fn reverse_ref(what: impl Borrow<AssetId>) -> Result<MultiLocation, ()> {325 log::trace!(326 target: "xcm::AsInnerId::Reverse",327 "AsInnerId",328 );329330 let asset_id = what.borrow();331332 let parent_id =333 ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Parent)).unwrap();334 let here_id =335 ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Here)).unwrap();336337 if asset_id.clone() == parent_id {338 return Ok(MultiLocation::parent());339 }340341 if asset_id.clone() == here_id {342 return Ok(MultiLocation::new(343 1,344 X1(Parachain(ParachainInfo::get().into())),345 ));346 }347348 match <AssetId as TryAsForeing<AssetId, ForeignAssetId>>::try_as_foreing(asset_id.clone()) {349 Some(fid) => match XcmForeignAssetIdMapping::<Runtime>::get_multi_location(fid) {350 Some(location) => Ok(location),351 None => Err(()),352 },353 None => Err(()),354 }355 }356}357358359#[cfg(feature = "foreign-assets")]360pub type FungiblesTransactor = FungiblesAdapter<361 362 ForeingAssets,363 364 ConvertedConcreteAssetId<AssetIds, Balance, AsInnerId<AssetIds, JustTry>, JustTry>,365 366 LocationToAccountId,367 368 AccountId,369 370 371 NonZeroIssuance<AccountId, ForeingAssets>,372 373 CheckingAccount,374>;375376377#[cfg(feature = "foreign-assets")]378pub type AssetTransactors = FungiblesTransactor;379380#[cfg(not(feature = "foreign-assets"))]381pub type AssetTransactors = LocalAssetTransactor;382383#[cfg(feature = "foreign-assets")]384pub struct AllAsset;385#[cfg(feature = "foreign-assets")]386impl FilterAssetLocation for AllAsset {387 fn filter_asset_location(asset: &MultiAsset, origin: &MultiLocation) -> bool {388 true389 }390}391392#[cfg(feature = "foreign-assets")]393pub type IsReserve = AllAsset;394#[cfg(not(feature = "foreign-assets"))]395pub type IsReserve = NativeAsset;396397#[cfg(feature = "foreign-assets")]398type Trader<T> = FreeForAll<399 pallet_configuration::WeightToFee<T, Balance>,400 RelayLocation,401 AccountId,402 Balances,403 (),404>;405#[cfg(not(feature = "foreign-assets"))]406type Trader<T> = UsingOnlySelfCurrencyComponents<407 pallet_configuration::WeightToFee<T, Balance>,408 RelayLocation,409 AccountId,410 Balances,411 (),412>;413414pub struct XcmConfig<T>(PhantomData<T>);415impl<T> Config for XcmConfig<T>416where417 T: pallet_configuration::Config,418{419 type Call = Call;420 type XcmSender = XcmRouter;421 422 type AssetTransactor = AssetTransactors;423 type OriginConverter = XcmOriginToTransactDispatchOrigin;424 type IsReserve = IsReserve;425 type IsTeleporter = (); 426 type LocationInverter = LocationInverter<Ancestry>;427 type Barrier = Barrier;428 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;429 type Trader = Trader<T>;430 type ResponseHandler = (); 431 type SubscriptionService = PolkadotXcm;432433 type AssetTrap = PolkadotXcm;434 type AssetClaims = PolkadotXcm;435}436437impl pallet_xcm::Config for Runtime {438 type Event = Event;439 type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;440 type XcmRouter = XcmRouter;441 type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;442 type XcmExecuteFilter = Everything;443 type XcmExecutor = XcmExecutor<XcmConfig<Self>>;444 type XcmTeleportFilter = Everything;445 type XcmReserveTransferFilter = Everything;446 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;447 type LocationInverter = LocationInverter<Ancestry>;448 type Origin = Origin;449 type Call = Call;450 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;451 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;452}453454impl cumulus_pallet_xcm::Config for Runtime {455 type Event = Event;456 type XcmExecutor = XcmExecutor<XcmConfig<Self>>;457}458459impl cumulus_pallet_xcmp_queue::Config for Runtime {460 type WeightInfo = ();461 type Event = Event;462 type XcmExecutor = XcmExecutor<XcmConfig<Self>>;463 type ChannelInfo = ParachainSystem;464 type VersionWrapper = ();465 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;466 type ControllerOrigin = EnsureRoot<AccountId>;467 type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;468}469470impl cumulus_pallet_dmp_queue::Config for Runtime {471 type Event = Event;472 type XcmExecutor = XcmExecutor<XcmConfig<Self>>;473 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;474}