1234567891011121314151617use frame_support::{18 traits::{19 tokens::currency::Currency as CurrencyT,20 OnUnbalanced as OnUnbalancedT,21 Get, Everything22 },23 weights::{Weight, WeightToFeePolynomial, WeightToFee},24 parameter_types, match_types,25};26use frame_system::EnsureRoot;27use sp_runtime::{28 traits::{29 Saturating, CheckedConversion, Zero,30 },31 SaturatedConversion,32};33use pallet_xcm::XcmPassthrough;34use polkadot_parachain::primitives::Sibling;35use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};36use xcm::latest::{37 AssetId::{Concrete},38 Fungibility::Fungible as XcmFungible,39 MultiAsset,40 Error as XcmError,41};42use xcm_executor::traits::{MatchesFungible, WeightTrader};43use xcm_builder::{44 AccountId32Aliases, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, EnsureXcmOrigin,45 FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser, RelayChainAsNative,46 SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,47 SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, ParentIsPreset,48};49use xcm_executor::{Config, XcmExecutor, Assets};50use sp_std::marker::PhantomData;51use crate::{52 runtime_common::{53 constants::*,54 config::substrate::LinearFee55 },56 Runtime,57 Call,58 Event,59 Origin,60 Balances,61 ParachainInfo,62 ParachainSystem,63 PolkadotXcm,64 XcmpQueue,65};66use common_types::{AccountId, Balance};6768parameter_types! {69 pub const RelayLocation: MultiLocation = MultiLocation::parent();70 pub const RelayNetwork: NetworkId = NetworkId::Polkadot;71 pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();72 pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();73}7475767778pub type LocationToAccountId = (79 80 ParentIsPreset<AccountId>,81 82 SiblingParachainConvertsVia<Sibling, AccountId>,83 84 AccountId32Aliases<RelayNetwork, AccountId>,85);8687pub struct OnlySelfCurrency;88impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {89 fn matches_fungible(a: &MultiAsset) -> Option<B> {90 match (&a.id, &a.fun) {91 (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),92 _ => None,93 }94 }95}969798pub type LocalAssetTransactor = CurrencyAdapter<99 100 Balances,101 102 OnlySelfCurrency,103 104 LocationToAccountId,105 106 AccountId,107 108 (),109>;110111112pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);113114115116pub type XcmRouter = (117 118 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,119 120 XcmpQueue,121);122123124125126pub type XcmOriginToTransactDispatchOrigin = (127 128 129 130 SovereignSignedViaLocation<LocationToAccountId, Origin>,131 132 133 RelayChainAsNative<RelayOrigin, Origin>,134 135 136 SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,137 138 139 ParentAsSuperuser<Origin>,140 141 142 SignedAccountId32AsNative<RelayNetwork, Origin>,143 144 XcmPassthrough<Origin>,145);146147parameter_types! {148 149 pub UnitWeightCost: Weight = 1_000_000;150 151 pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);152 pub const MaxInstructions: u32 = 100;153}154155match_types! {156 pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {157 MultiLocation { parents: 1, interior: Here } |158 MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }159 };160}161162pub type Barrier = (163 TakeWeightCredit,164 AllowTopLevelPaidExecutionFrom<Everything>,165 166);167168pub struct UsingOnlySelfCurrencyComponents<169 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,170 AssetId: Get<MultiLocation>,171 AccountId,172 Currency: CurrencyT<AccountId>,173 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,174>(175 Weight,176 Currency::Balance,177 PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,178);179impl<180 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,181 AssetId: Get<MultiLocation>,182 AccountId,183 Currency: CurrencyT<AccountId>,184 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,185 > WeightTrader186 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>187{188 fn new() -> Self {189 Self(0, Zero::zero(), PhantomData)190 }191192 fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {193 let amount = WeightToFee::weight_to_fee(&weight);194 let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;195196 197 let option1: xcm::v1::AssetId = Concrete(MultiLocation {198 parents: 1,199 interior: X1(Parachain(ParachainInfo::parachain_id().into())),200 });201 202 let option2: xcm::v1::AssetId = Concrete(MultiLocation {203 parents: 0,204 interior: Here,205 });206207 let required = if payment.fungible.contains_key(&option1) {208 (option1, u128_amount).into()209 } else if payment.fungible.contains_key(&option2) {210 (option2, u128_amount).into()211 } else {212 (Concrete(MultiLocation::default()), u128_amount).into()213 };214215 let unused = payment216 .checked_sub(required)217 .map_err(|_| XcmError::TooExpensive)?;218 self.0 = self.0.saturating_add(weight);219 self.1 = self.1.saturating_add(amount);220 Ok(unused)221 }222223 fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {224 let weight = weight.min(self.0);225 let amount = WeightToFee::weight_to_fee(&weight);226 self.0 -= weight;227 self.1 = self.1.saturating_sub(amount);228 let amount: u128 = amount.saturated_into();229 if amount > 0 {230 Some((AssetId::get(), amount).into())231 } else {232 None233 }234 }235}236impl<237 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,238 AssetId: Get<MultiLocation>,239 AccountId,240 Currency: CurrencyT<AccountId>,241 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,242 > Drop243 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>244{245 fn drop(&mut self) {246 OnUnbalanced::on_unbalanced(Currency::issue(self.1));247 }248}249250pub struct XcmConfig;251impl Config for XcmConfig {252 type Call = Call;253 type XcmSender = XcmRouter;254 255 type AssetTransactor = LocalAssetTransactor;256 type OriginConverter = XcmOriginToTransactDispatchOrigin;257 type IsReserve = NativeAsset;258 type IsTeleporter = (); 259 type LocationInverter = LocationInverter<Ancestry>;260 type Barrier = Barrier;261 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;262 type Trader =263 UsingOnlySelfCurrencyComponents<LinearFee<Balance>, RelayLocation, AccountId, Balances, ()>;264 type ResponseHandler = (); 265 type SubscriptionService = PolkadotXcm;266267 type AssetTrap = PolkadotXcm;268 type AssetClaims = PolkadotXcm;269}270271impl pallet_xcm::Config for Runtime {272 type Event = Event;273 type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;274 type XcmRouter = XcmRouter;275 type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;276 type XcmExecuteFilter = Everything;277 type XcmExecutor = XcmExecutor<XcmConfig>;278 type XcmTeleportFilter = Everything;279 type XcmReserveTransferFilter = Everything;280 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;281 type LocationInverter = LocationInverter<Ancestry>;282 type Origin = Origin;283 type Call = Call;284 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;285 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;286}287288impl cumulus_pallet_xcm::Config for Runtime {289 type Event = Event;290 type XcmExecutor = XcmExecutor<XcmConfig>;291}292293impl cumulus_pallet_xcmp_queue::Config for Runtime {294 type WeightInfo = ();295 type Event = Event;296 type XcmExecutor = XcmExecutor<XcmConfig>;297 type ChannelInfo = ParachainSystem;298 type VersionWrapper = ();299 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;300 type ControllerOrigin = EnsureRoot<AccountId>;301 type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;302}303304impl cumulus_pallet_dmp_queue::Config for Runtime {305 type Event = Event;306 type XcmExecutor = XcmExecutor<XcmConfig>;307 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;308}