1234567891011121314151617use frame_support::{18 traits::{19 Contains, tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Get, Everything,20 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,37};38use xcm_builder::{39 AccountId32Aliases, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, EnsureXcmOrigin,40 FixedWeightBounds, FungiblesAdapter, LocationInverter, NativeAsset, ParentAsSuperuser, RelayChainAsNative,41 SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,42 SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, ParentIsPreset,43};44use xcm_executor::{Config, XcmExecutor, Assets};45use xcm_executor::traits::{Convert as ConvertXcm, MatchesFungible, WeightTrader, FilterAssetLocation};46use pallet_foreing_assets::{47 AssetIds, AssetIdMapping, XcmForeignAssetIdMapping, CurrencyId, NativeCurrency,48 UsingAnyCurrencyComponents, TryAsForeing, ForeignAssetId,49};50use sp_std::{borrow::Borrow, marker::PhantomData, vec, vec::Vec};51use crate::{52 Runtime, Call, Event, Origin, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, XcmpQueue,53 xcm_config::Barrier54};55#[cfg(feature = "foreign-assets")]56use crate::ForeingAssets;5758use up_common::{59 types::{AccountId, Balance},60 constants::*,61};6263parameter_types! {64 pub const RelayLocation: MultiLocation = MultiLocation::parent();65 pub const RelayNetwork: NetworkId = NetworkId::Polkadot;66 pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();67 pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();68}6970717273pub type LocationToAccountId = (74 75 ParentIsPreset<AccountId>,76 77 SiblingParachainConvertsVia<Sibling, AccountId>,78 79 AccountId32Aliases<RelayNetwork, AccountId>,80);8182pub struct OnlySelfCurrency;83impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {84 fn matches_fungible(a: &MultiAsset) -> Option<B> {85 match (&a.id, &a.fun) {86 (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),87 _ => None,88 }89 }90}919293pub type LocalAssetTransactor = CurrencyAdapter<94 95 Balances,96 97 OnlySelfCurrency,98 99 LocationToAccountId,100 101 AccountId,102 103 (),104>;105106107pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);108109110111pub type XcmRouter = (112 113 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,114 115 XcmpQueue,116);117118119120121pub type XcmOriginToTransactDispatchOrigin = (122 123 124 125 SovereignSignedViaLocation<LocationToAccountId, Origin>,126 127 128 RelayChainAsNative<RelayOrigin, Origin>,129 130 131 SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,132 133 134 ParentAsSuperuser<Origin>,135 136 137 SignedAccountId32AsNative<RelayNetwork, Origin>,138 139 XcmPassthrough<Origin>,140);141142parameter_types! {143 144 pub UnitWeightCost: Weight = 1_000_000;145 146 pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);147 pub const MaxInstructions: u32 = 100;148}149150match_types! {151 pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {152 MultiLocation { parents: 1, interior: Here } |153 MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }154 };155}156157158159160161162163164165pub struct UsingOnlySelfCurrencyComponents<166 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,167 AssetId: Get<MultiLocation>,168 AccountId,169 Currency: CurrencyT<AccountId>,170 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,171>(172 Weight,173 Currency::Balance,174 PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,175);176impl<177 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,178 AssetId: Get<MultiLocation>,179 AccountId,180 Currency: CurrencyT<AccountId>,181 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,182 > WeightTrader183 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>184{185 fn new() -> Self {186 Self(0, Zero::zero(), PhantomData)187 }188189 fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {190 let amount = WeightToFee::weight_to_fee(&weight);191 let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;192193 194 let option1: xcm::v1::AssetId = Concrete(MultiLocation {195 parents: 1,196 interior: X1(Parachain(ParachainInfo::parachain_id().into())),197 });198 199 let option2: xcm::v1::AssetId = Concrete(MultiLocation {200 parents: 0,201 interior: Here,202 });203204 let required = if payment.fungible.contains_key(&option1) {205 (option1, u128_amount).into()206 } else if payment.fungible.contains_key(&option2) {207 (option2, u128_amount).into()208 } else {209 (Concrete(MultiLocation::default()), u128_amount).into()210 };211212 let unused = payment213 .checked_sub(required)214 .map_err(|_| XcmError::TooExpensive)?;215 self.0 = self.0.saturating_add(weight);216 self.1 = self.1.saturating_add(amount);217 Ok(unused)218 }219220 fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {221 let weight = weight.min(self.0);222 let amount = WeightToFee::weight_to_fee(&weight);223 self.0 -= weight;224 self.1 = self.1.saturating_sub(amount);225 let amount: u128 = amount.saturated_into();226 if amount > 0 {227 Some((AssetId::get(), amount).into())228 } else {229 None230 }231 }232}233impl<234 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,235 AssetId: Get<MultiLocation>,236 AccountId,237 Currency: CurrencyT<AccountId>,238 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,239 > Drop240 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>241{242 fn drop(&mut self) {243 OnUnbalanced::on_unbalanced(Currency::issue(self.1));244 }245}246247parameter_types! {248 pub CheckingAccount: AccountId = PolkadotXcm::check_account();249}250251#[cfg(feature = "foreign-assets")]252pub struct NonZeroIssuance<AccountId, ForeingAssets>(PhantomData<(AccountId, ForeingAssets)>);253254#[cfg(feature = "foreign-assets")]255impl<AccountId, ForeingAssets> Contains<<ForeingAssets as fungibles::Inspect<AccountId>>::AssetId>256for NonZeroIssuance<AccountId, ForeingAssets>257 where258 ForeingAssets: fungibles::Inspect<AccountId>,259{260 fn contains(id: &<ForeingAssets as fungibles::Inspect<AccountId>>::AssetId) -> bool {261 !ForeingAssets::total_issuance(*id).is_zero()262 }263}264265#[cfg(feature = "foreign-assets")]266pub struct AsInnerId<AssetId, ConvertAssetId>(PhantomData<(AssetId, ConvertAssetId)>);267#[cfg(feature = "foreign-assets")]268impl<AssetId: Clone + PartialEq, ConvertAssetId: ConvertXcm<AssetId, AssetId>>269ConvertXcm<MultiLocation, AssetId> for AsInnerId<AssetId, ConvertAssetId>270 where271 AssetId: Borrow<AssetId>,272 AssetId: TryAsForeing<AssetId, ForeignAssetId>,273 AssetIds: Borrow<AssetId>,274{275 fn convert_ref(id: impl Borrow<MultiLocation>) -> Result<AssetId, ()> {276 let id = id.borrow();277278 log::trace!(279 target: "xcm::AsInnerId::Convert",280 "AsInnerId {:?}",281 id282 );283284 let parent = MultiLocation::parent();285 let here = MultiLocation::here();286 let self_location = MultiLocation::new(1, X1(Parachain(ParachainInfo::get().into())));287288 if *id == parent {289 return ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Parent));290 }291292 if *id == here || *id == self_location {293 return ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Here));294 }295296 match XcmForeignAssetIdMapping::<Runtime>::get_currency_id(id.clone()) {297 Some(AssetIds::ForeignAssetId(foreign_asset_id)) => {298 ConvertAssetId::convert_ref(AssetIds::ForeignAssetId(foreign_asset_id))299 }300 _ => ConvertAssetId::convert_ref(AssetIds::ForeignAssetId(0)),301 }302 }303304 fn reverse_ref(what: impl Borrow<AssetId>) -> Result<MultiLocation, ()> {305 log::trace!(306 target: "xcm::AsInnerId::Reverse",307 "AsInnerId",308 );309310 let asset_id = what.borrow();311312 let parent_id =313 ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Parent)).unwrap();314 let here_id =315 ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Here)).unwrap();316317 if asset_id.clone() == parent_id {318 return Ok(MultiLocation::parent());319 }320321 if asset_id.clone() == here_id {322 return Ok(MultiLocation::new(323 1,324 X1(Parachain(ParachainInfo::get().into())),325 ));326 }327328 match <AssetId as TryAsForeing<AssetId, ForeignAssetId>>::try_as_foreing(asset_id.clone()) {329 Some(fid) => match XcmForeignAssetIdMapping::<Runtime>::get_multi_location(fid) {330 Some(location) => Ok(location),331 None => Err(()),332 },333 None => Err(()),334 }335 }336}337338339#[cfg(feature = "foreign-assets")]340pub type FungiblesTransactor = FungiblesAdapter<341 342 ForeingAssets,343 344 ConvertedConcreteAssetId<AssetIds, Balance, AsInnerId<AssetIds, JustTry>, JustTry>,345 346 LocationToAccountId,347 348 AccountId,349 350 351 NonZeroIssuance<AccountId, ForeingAssets>,352 353 CheckingAccount,354>;355356357#[cfg(feature = "foreign-assets")]358pub type AssetTransactors = FungiblesTransactor;359#[cfg(not(feature = "foreign-assets"))]360pub type AssetTransactors = LocalAssetTransactor;361362#[cfg(feature = "foreign-assets")]363pub struct AllAsset;364#[cfg(feature = "foreign-assets")]365impl FilterAssetLocation for AllAsset {366 fn filter_asset_location(asset: &MultiAsset, origin: &MultiLocation) -> bool {367 true368 }369}370371#[cfg(feature = "foreign-assets")]372pub type IsReserve = AllAsset;373#[cfg(not(feature = "foreign-assets"))]374pub type IsReserve = NativeAsset;375376#[cfg(feature = "foreign-assets")]377type Trader<T> =378 UsingAnyCurrencyComponents<379 pallet_configuration::WeightToFee<T, Balance>,380 RelayLocation, AccountId, Balances, ()>;381#[cfg(not(feature = "foreign-assets"))]382type Trader<T> = UsingOnlySelfCurrencyComponents<383 pallet_configuration::WeightToFee<T, Balance>,384 RelayLocation,385 AccountId,386 Balances,387 (),388>;389390pub struct XcmConfig<T>(PhantomData<T>);391impl<T> Config for XcmConfig<T>392where393 T: pallet_configuration::Config,394{395 type Call = Call;396 type XcmSender = XcmRouter;397 398 type AssetTransactor = LocalAssetTransactor;399 type OriginConverter = XcmOriginToTransactDispatchOrigin;400 type IsReserve = IsReserve;401 type IsTeleporter = (); 402 type LocationInverter = LocationInverter<Ancestry>;403 type Barrier = Barrier;404 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;405 type Trader = Trader<T>;406 type ResponseHandler = (); 407 type SubscriptionService = PolkadotXcm;408409 type AssetTrap = PolkadotXcm;410 type AssetClaims = PolkadotXcm;411}412413impl pallet_xcm::Config for Runtime {414 type Event = Event;415 type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;416 type XcmRouter = XcmRouter;417 type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;418 type XcmExecuteFilter = Everything;419 type XcmExecutor = XcmExecutor<XcmConfig<Self>>;420 type XcmTeleportFilter = Everything;421 type XcmReserveTransferFilter = Everything;422 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;423 type LocationInverter = LocationInverter<Ancestry>;424 type Origin = Origin;425 type Call = Call;426 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;427 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;428}429430impl cumulus_pallet_xcm::Config for Runtime {431 type Event = Event;432 type XcmExecutor = XcmExecutor<XcmConfig<Self>>;433}434435impl cumulus_pallet_xcmp_queue::Config for Runtime {436 type WeightInfo = ();437 type Event = Event;438 type XcmExecutor = XcmExecutor<XcmConfig<Self>>;439 type ChannelInfo = ParachainSystem;440 type VersionWrapper = ();441 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;442 type ControllerOrigin = EnsureRoot<AccountId>;443 type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;444}445446impl cumulus_pallet_dmp_queue::Config for Runtime {447 type Event = Event;448 type XcmExecutor = XcmExecutor<XcmConfig<Self>>;449 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;450}451