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::config::substrate::LinearFee, Runtime, Call, Event, Origin, Balances,48 ParachainInfo, ParachainSystem, PolkadotXcm, XcmpQueue,49};50use up_common::{51 types::{AccountId, Balance},52 constants::*,53};5455parameter_types! {56 pub const RelayLocation: MultiLocation = MultiLocation::parent();57 pub const RelayNetwork: NetworkId = NetworkId::Polkadot;58 pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();59 pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();60}6162636465pub type LocationToAccountId = (66 67 ParentIsPreset<AccountId>,68 69 SiblingParachainConvertsVia<Sibling, AccountId>,70 71 AccountId32Aliases<RelayNetwork, AccountId>,72);7374pub struct OnlySelfCurrency;75impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {76 fn matches_fungible(a: &MultiAsset) -> Option<B> {77 match (&a.id, &a.fun) {78 (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),79 _ => None,80 }81 }82}838485pub type LocalAssetTransactor = CurrencyAdapter<86 87 Balances,88 89 OnlySelfCurrency,90 91 LocationToAccountId,92 93 AccountId,94 95 (),96>;979899pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);100101102103pub type XcmRouter = (104 105 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,106 107 XcmpQueue,108);109110111112113pub type XcmOriginToTransactDispatchOrigin = (114 115 116 117 SovereignSignedViaLocation<LocationToAccountId, Origin>,118 119 120 RelayChainAsNative<RelayOrigin, Origin>,121 122 123 SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,124 125 126 ParentAsSuperuser<Origin>,127 128 129 SignedAccountId32AsNative<RelayNetwork, Origin>,130 131 XcmPassthrough<Origin>,132);133134parameter_types! {135 136 pub UnitWeightCost: Weight = 1_000_000;137 138 pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);139 pub const MaxInstructions: u32 = 100;140}141142match_types! {143 pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {144 MultiLocation { parents: 1, interior: Here } |145 MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }146 };147}148149pub type Barrier = (150 TakeWeightCredit,151 AllowTopLevelPaidExecutionFrom<Everything>,152 153);154155pub struct UsingOnlySelfCurrencyComponents<156 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,157 AssetId: Get<MultiLocation>,158 AccountId,159 Currency: CurrencyT<AccountId>,160 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,161>(162 Weight,163 Currency::Balance,164 PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,165);166impl<167 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,168 AssetId: Get<MultiLocation>,169 AccountId,170 Currency: CurrencyT<AccountId>,171 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,172 > WeightTrader173 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>174{175 fn new() -> Self {176 Self(0, Zero::zero(), PhantomData)177 }178179 fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {180 let amount = WeightToFee::weight_to_fee(&weight);181 let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;182183 184 let option1: xcm::v1::AssetId = Concrete(MultiLocation {185 parents: 1,186 interior: X1(Parachain(ParachainInfo::parachain_id().into())),187 });188 189 let option2: xcm::v1::AssetId = Concrete(MultiLocation {190 parents: 0,191 interior: Here,192 });193194 let required = if payment.fungible.contains_key(&option1) {195 (option1, u128_amount).into()196 } else if payment.fungible.contains_key(&option2) {197 (option2, u128_amount).into()198 } else {199 (Concrete(MultiLocation::default()), u128_amount).into()200 };201202 let unused = payment203 .checked_sub(required)204 .map_err(|_| XcmError::TooExpensive)?;205 self.0 = self.0.saturating_add(weight);206 self.1 = self.1.saturating_add(amount);207 Ok(unused)208 }209210 fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {211 let weight = weight.min(self.0);212 let amount = WeightToFee::weight_to_fee(&weight);213 self.0 -= weight;214 self.1 = self.1.saturating_sub(amount);215 let amount: u128 = amount.saturated_into();216 if amount > 0 {217 Some((AssetId::get(), amount).into())218 } else {219 None220 }221 }222}223impl<224 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,225 AssetId: Get<MultiLocation>,226 AccountId,227 Currency: CurrencyT<AccountId>,228 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,229 > Drop230 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>231{232 fn drop(&mut self) {233 OnUnbalanced::on_unbalanced(Currency::issue(self.1));234 }235}236237pub struct XcmConfig;238impl Config for XcmConfig {239 type Call = Call;240 type XcmSender = XcmRouter;241 242 type AssetTransactor = LocalAssetTransactor;243 type OriginConverter = XcmOriginToTransactDispatchOrigin;244 type IsReserve = NativeAsset;245 type IsTeleporter = (); 246 type LocationInverter = LocationInverter<Ancestry>;247 type Barrier = Barrier;248 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;249 type Trader =250 UsingOnlySelfCurrencyComponents<LinearFee<Balance>, RelayLocation, AccountId, Balances, ()>;251 type ResponseHandler = (); 252 type SubscriptionService = PolkadotXcm;253254 type AssetTrap = PolkadotXcm;255 type AssetClaims = PolkadotXcm;256}257258impl pallet_xcm::Config for Runtime {259 type Event = Event;260 type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;261 type XcmRouter = XcmRouter;262 type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;263 type XcmExecuteFilter = Everything;264 type XcmExecutor = XcmExecutor<XcmConfig>;265 type XcmTeleportFilter = Everything;266 type XcmReserveTransferFilter = Everything;267 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;268 type LocationInverter = LocationInverter<Ancestry>;269 type Origin = Origin;270 type Call = Call;271 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;272 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;273}274275impl cumulus_pallet_xcm::Config for Runtime {276 type Event = Event;277 type XcmExecutor = XcmExecutor<XcmConfig>;278}279280impl cumulus_pallet_xcmp_queue::Config for Runtime {281 type WeightInfo = ();282 type Event = Event;283 type XcmExecutor = XcmExecutor<XcmConfig>;284 type ChannelInfo = ParachainSystem;285 type VersionWrapper = ();286 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;287 type ControllerOrigin = EnsureRoot<AccountId>;288 type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;289}290291impl cumulus_pallet_dmp_queue::Config for Runtime {292 type Event = Event;293 type XcmExecutor = XcmExecutor<XcmConfig>;294 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;295}