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, Call, Event, Origin, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, XcmpQueue,48};49use up_common::{50 types::{AccountId, Balance},51 constants::*,52};5354parameter_types! {55 pub const RelayLocation: MultiLocation = MultiLocation::parent();56 pub const RelayNetwork: NetworkId = NetworkId::Polkadot;57 pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();58 pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();59}6061626364pub type LocationToAccountId = (65 66 ParentIsPreset<AccountId>,67 68 SiblingParachainConvertsVia<Sibling, AccountId>,69 70 AccountId32Aliases<RelayNetwork, AccountId>,71);7273pub struct OnlySelfCurrency;74impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {75 fn matches_fungible(a: &MultiAsset) -> Option<B> {76 match (&a.id, &a.fun) {77 (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),78 _ => None,79 }80 }81}828384pub type LocalAssetTransactor = CurrencyAdapter<85 86 Balances,87 88 OnlySelfCurrency,89 90 LocationToAccountId,91 92 AccountId,93 94 (),95>;969798pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);99100101102pub type XcmRouter = (103 104 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,105 106 XcmpQueue,107);108109110111112pub type XcmOriginToTransactDispatchOrigin = (113 114 115 116 SovereignSignedViaLocation<LocationToAccountId, Origin>,117 118 119 RelayChainAsNative<RelayOrigin, Origin>,120 121 122 SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,123 124 125 ParentAsSuperuser<Origin>,126 127 128 SignedAccountId32AsNative<RelayNetwork, Origin>,129 130 XcmPassthrough<Origin>,131);132133parameter_types! {134 135 pub UnitWeightCost: Weight = 1_000_000;136 137 pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);138 pub const MaxInstructions: u32 = 100;139}140141match_types! {142 pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {143 MultiLocation { parents: 1, interior: Here } |144 MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }145 };146}147148pub type Barrier = (149 TakeWeightCredit,150 AllowTopLevelPaidExecutionFrom<Everything>,151 152);153154pub struct UsingOnlySelfCurrencyComponents<155 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,156 AssetId: Get<MultiLocation>,157 AccountId,158 Currency: CurrencyT<AccountId>,159 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,160>(161 Weight,162 Currency::Balance,163 PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,164);165impl<166 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,167 AssetId: Get<MultiLocation>,168 AccountId,169 Currency: CurrencyT<AccountId>,170 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,171 > WeightTrader172 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>173{174 fn new() -> Self {175 Self(0, Zero::zero(), PhantomData)176 }177178 fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {179 let amount = WeightToFee::weight_to_fee(&weight);180 let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;181182 183 let option1: xcm::v1::AssetId = Concrete(MultiLocation {184 parents: 1,185 interior: X1(Parachain(ParachainInfo::parachain_id().into())),186 });187 188 let option2: xcm::v1::AssetId = Concrete(MultiLocation {189 parents: 0,190 interior: Here,191 });192193 let required = if payment.fungible.contains_key(&option1) {194 (option1, u128_amount).into()195 } else if payment.fungible.contains_key(&option2) {196 (option2, u128_amount).into()197 } else {198 (Concrete(MultiLocation::default()), u128_amount).into()199 };200201 let unused = payment202 .checked_sub(required)203 .map_err(|_| XcmError::TooExpensive)?;204 self.0 = self.0.saturating_add(weight);205 self.1 = self.1.saturating_add(amount);206 Ok(unused)207 }208209 fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {210 let weight = weight.min(self.0);211 let amount = WeightToFee::weight_to_fee(&weight);212 self.0 -= weight;213 self.1 = self.1.saturating_sub(amount);214 let amount: u128 = amount.saturated_into();215 if amount > 0 {216 Some((AssetId::get(), amount).into())217 } else {218 None219 }220 }221}222impl<223 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,224 AssetId: Get<MultiLocation>,225 AccountId,226 Currency: CurrencyT<AccountId>,227 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,228 > Drop229 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>230{231 fn drop(&mut self) {232 OnUnbalanced::on_unbalanced(Currency::issue(self.1));233 }234}235236pub struct XcmConfig<T>(PhantomData<T>);237impl<T> Config for XcmConfig<T>238where239 T: pallet_configuration::Config,240{241 type Call = Call;242 type XcmSender = XcmRouter;243 244 type AssetTransactor = LocalAssetTransactor;245 type OriginConverter = XcmOriginToTransactDispatchOrigin;246 type IsReserve = NativeAsset;247 type IsTeleporter = (); 248 type LocationInverter = LocationInverter<Ancestry>;249 type Barrier = Barrier;250 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;251 type Trader = UsingOnlySelfCurrencyComponents<252 pallet_configuration::WeightToFee<T, Balance>,253 RelayLocation,254 AccountId,255 Balances,256 (),257 >;258 type ResponseHandler = (); 259 type SubscriptionService = PolkadotXcm;260261 type AssetTrap = PolkadotXcm;262 type AssetClaims = PolkadotXcm;263}264265impl pallet_xcm::Config for Runtime {266 type Event = Event;267 type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;268 type XcmRouter = XcmRouter;269 type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;270 type XcmExecuteFilter = Everything;271 type XcmExecutor = XcmExecutor<XcmConfig<Self>>;272 type XcmTeleportFilter = Everything;273 type XcmReserveTransferFilter = Everything;274 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;275 type LocationInverter = LocationInverter<Ancestry>;276 type Origin = Origin;277 type Call = Call;278 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;279 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;280}281282impl cumulus_pallet_xcm::Config for Runtime {283 type Event = Event;284 type XcmExecutor = XcmExecutor<XcmConfig<Self>>;285}286287impl cumulus_pallet_xcmp_queue::Config for Runtime {288 type WeightInfo = ();289 type Event = Event;290 type XcmExecutor = XcmExecutor<XcmConfig<Self>>;291 type ChannelInfo = ParachainSystem;292 type VersionWrapper = ();293 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;294 type ControllerOrigin = EnsureRoot<AccountId>;295 type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;296}297298impl cumulus_pallet_dmp_queue::Config for Runtime {299 type Event = Event;300 type XcmExecutor = XcmExecutor<XcmConfig<Self>>;301 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;302}