Newer
Older
// Copyright (C) Parity Technologies (UK) Ltd.
Branislav Kontur
committed
// This file is part of Cumulus.
// Cumulus is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Cumulus is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
use super::{
AccountId, AllPalletsWithSystem, Balances, BaseDeliveryFee, FeeAssetId, ParachainInfo,
Branislav Kontur
committed
ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin,
TransactionByteFee, WeightToFee, XcmpQueue,
Branislav Kontur
committed
use crate::bridge_common_config::{
Branislav Kontur
committed
BridgeGrandpaWestendInstance, DeliveryRewardInBalance, RequiredStakeForStakeAndSlash,
Branislav Kontur
committed
};
Serban Iorga
committed
use bp_messages::LaneId;
use bp_relayers::{PayRewardFromAccount, RewardsAccountOwner, RewardsAccountParams};
use bp_runtime::ChainId;
Branislav Kontur
committed
use frame_support::{
match_types, parameter_types,
traits::{ConstU32, Contains, Equals, Everything, Nothing},
Branislav Kontur
committed
};
Branislav Kontur
committed
use pallet_xcm::XcmPassthrough;
use parachains_common::{
impls::ToStakingPot,
![Svyatoslav Nikolsky Svyatoslav Nikolsky's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Svyatoslav Nikolsky
committed
xcm_config::{
AllSiblingSystemParachains, ConcreteAssetFromSystem, ParentRelayOrSiblingParachains,
RelayOrOtherSystemParachains,
![Svyatoslav Nikolsky Svyatoslav Nikolsky's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Svyatoslav Nikolsky
committed
},
use polkadot_parachain_primitives::primitives::Sibling;
use polkadot_runtime_common::xcm_sender::ExponentialPrice;
use sp_runtime::traits::AccountIdConversion;
Serban Iorga
committed
use sp_std::marker::PhantomData;
Branislav Kontur
committed
use xcm::latest::prelude::*;
#[allow(deprecated)]
use xcm_builder::CurrencyAdapter;
Branislav Kontur
committed
use xcm_builder::{
Serban Iorga
committed
deposit_or_burn_fee, AccountId32Aliases, AllowExplicitUnpaidExecutionFrom,
AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, HandleFee, IsConcrete,
ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative,
Serban Iorga
committed
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents,
XcmFeeToAccount,
Branislav Kontur
committed
traits::{FeeReason, TransactAsset, WithOriginFilter},
Branislav Kontur
committed
};
parameter_types! {
Adrian Catangiu
committed
pub const TokenLocation: MultiLocation = MultiLocation::parent();
Branislav Kontur
committed
pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
Branislav Kontur
committed
pub RelayNetwork: NetworkId = NetworkId::Rococo;
X2(GlobalConsensus(RelayNetwork::get()), Parachain(ParachainInfo::parachain_id().into()));
pub const MaxInstructions: u32 = 100;
Serban Iorga
committed
pub TreasuryAccount: AccountId = TREASURY_PALLET_ID.into_account_truncating();
pub RelayTreasuryLocation: MultiLocation = (Parent, PalletInstance(rococo_runtime_constants::TREASURY_PALLET_ID)).into();
Branislav Kontur
committed
}
/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
/// when determining ownership of accounts for asset transacting and when attempting to use XCM
/// `Transact` in order to determine the dispatch Origin.
pub type LocationToAccountId = (
// The parent (Relay-chain) origin converts to the parent `AccountId`.
ParentIsPreset<AccountId>,
// Sibling parachain origins convert to AccountId via the `ParaId::into`.
SiblingParachainConvertsVia<Sibling, AccountId>,
// Straight up local `AccountId32` origins just alias directly to `AccountId`.
AccountId32Aliases<RelayNetwork, AccountId>,
);
/// Means for transacting the native currency on this chain.
Branislav Kontur
committed
pub type CurrencyTransactor = CurrencyAdapter<
// Use this currency:
Balances,
// Use this currency when it is a fungible asset matching the given location or name:
Adrian Catangiu
committed
IsConcrete<TokenLocation>,
Branislav Kontur
committed
// Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:
LocationToAccountId,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
AccountId,
// We don't track any teleports of `Balances`.
Branislav Kontur
committed
(),
>;
/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
/// biases the kind of local `Origin` it will become.
pub type XcmOriginToTransactDispatchOrigin = (
// Sovereign account converter; this attempts to derive an `AccountId` from the origin location
// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
// foreign chains who want to have a local sovereign account on this chain which they control.
SovereignSignedViaLocation<LocationToAccountId, RuntimeOrigin>,
// Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when
Branislav Kontur
committed
// recognized.
RelayChainAsNative<RelayChainOrigin, RuntimeOrigin>,
// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
// recognized.
SiblingParachainAsNative<cumulus_pallet_xcm::Origin, RuntimeOrigin>,
// Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
// transaction from the Root origin.
ParentAsSuperuser<RuntimeOrigin>,
Branislav Kontur
committed
// Native signed account converter; this just converts an `AccountId32` origin into a normal
Branislav Kontur
committed
// `RuntimeOrigin::Signed` origin of the same 32-byte value.
Branislav Kontur
committed
SignedAccountId32AsNative<RelayNetwork, RuntimeOrigin>,
// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
XcmPassthrough<RuntimeOrigin>,
);
match_types! {
Branislav Kontur
committed
pub type ParentOrParentsPlurality: impl Contains<MultiLocation> = {
Branislav Kontur
committed
MultiLocation { parents: 1, interior: Here } |
Branislav Kontur
committed
MultiLocation { parents: 1, interior: X1(Plurality { .. }) }
Branislav Kontur
committed
};
}
/// A call filter for the XCM Transact instruction. This is a temporary measure until we properly
/// account for proof size weights.
///
/// Calls that are allowed through this filter must:
/// 1. Have a fixed weight;
/// 2. Cannot lead to another call being made;
/// 3. Have a defined proof size weight, e.g. no unbounded vecs in call parameters.
pub struct SafeCallFilter;
impl Contains<RuntimeCall> for SafeCallFilter {
fn contains(call: &RuntimeCall) -> bool {
#[cfg(feature = "runtime-benchmarks")]
{
if matches!(call, RuntimeCall::System(frame_system::Call::remark_with_event { .. })) {
return true
}
}
// Allow to change dedicated storage items (called by governance-like)
match call {
RuntimeCall::System(frame_system::Call::set_storage { items })
Adrian Catangiu
committed
if items.iter().all(|(k, _)| {
k.eq(&DeliveryRewardInBalance::key()) |
Branislav Kontur
committed
k.eq(&RequiredStakeForStakeAndSlash::key())
}) =>
return true,
_ => (),
};
RuntimeCall::PolkadotXcm(
pallet_xcm::Call::force_xcm_version { .. } |
pallet_xcm::Call::force_default_xcm_version { .. }
) | RuntimeCall::System(
frame_system::Call::set_heap_pages { .. } |
frame_system::Call::set_code { .. } |
frame_system::Call::set_code_without_checks { .. } |
frame_system::Call::kill_prefix { .. },
) | RuntimeCall::ParachainSystem(..) |
RuntimeCall::Timestamp(..) |
RuntimeCall::Balances(..) |
RuntimeCall::CollatorSelection(
pallet_collator_selection::Call::set_desired_candidates { .. } |
pallet_collator_selection::Call::set_candidacy_bond { .. } |
pallet_collator_selection::Call::register_as_candidate { .. } |
pallet_collator_selection::Call::leave_intent { .. } |
pallet_collator_selection::Call::set_invulnerables { .. } |
pallet_collator_selection::Call::add_invulnerable { .. } |
pallet_collator_selection::Call::remove_invulnerable { .. },
) | RuntimeCall::Session(pallet_session::Call::purge_keys { .. }) |
RuntimeCall::XcmpQueue(..) |
RuntimeCall::MessageQueue(..) |
Branislav Kontur
committed
RuntimeCall::BridgeWestendGrandpa(pallet_bridge_grandpa::Call::<
Runtime,
BridgeGrandpaWestendInstance,
Gavin Wood
committed
pub type Barrier = TrailingSetTopicAsId<
DenyThenTry<
DenyReserveTransferToRelayChain,
(
// Allow local users to buy weight credit.
TakeWeightCredit,
// Expected responses are OK.
AllowKnownQueryResponses<PolkadotXcm>,
WithComputedOrigin<
(
Adrian Catangiu
committed
// If the message is one that immediately attempts to pay for execution, then
// allow it.
Gavin Wood
committed
AllowTopLevelPaidExecutionFrom<Everything>,
// Parent, its pluralities (i.e. governance bodies) and relay treasury pallet
// get free execution.
AllowExplicitUnpaidExecutionFrom<(
ParentOrParentsPlurality,
Equals<RelayTreasuryLocation>,
)>,
Gavin Wood
committed
// Subscriptions for version tracking are OK.
AllowSubscriptionsFrom<ParentRelayOrSiblingParachains>,
Gavin Wood
committed
),
UniversalLocation,
ConstU32<8>,
>,
),
>,
Branislav Kontur
committed
>;
/// Locations that will not be charged fees in the executor,
/// either execution or delivery.
/// We only waive fees for system functions, which these locations represent.
![Svyatoslav Nikolsky Svyatoslav Nikolsky's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Svyatoslav Nikolsky
committed
pub type WaivedLocations = (
RelayOrOtherSystemParachains<AllSiblingSystemParachains, Runtime>,
Equals<RelayTreasuryLocation>,
);
/// Cases where a remote origin is accepted as trusted Teleporter for a given asset:
/// - NativeToken with the parent Relay Chain and sibling parachains.
Adrian Catangiu
committed
pub type TrustedTeleporters = ConcreteAssetFromSystem<TokenLocation>;
Branislav Kontur
committed
pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
type RuntimeCall = RuntimeCall;
type XcmSender = XcmRouter;
type AssetTransactor = CurrencyTransactor;
type OriginConverter = XcmOriginToTransactDispatchOrigin;
// BridgeHub does not recognize a reserve location for any asset. Users must teleport Native
// token where allowed (e.g. with the Relay Chain).
Branislav Kontur
committed
type IsReserve = ();
type IsTeleporter = TrustedTeleporters;
Branislav Kontur
committed
type Barrier = Barrier;
type Weigher = WeightInfoBounds<
crate::weights::xcm::BridgeHubRococoXcmWeight<RuntimeCall>,
RuntimeCall,
MaxInstructions,
>;
Branislav Kontur
committed
type Trader =
Adrian Catangiu
committed
UsingComponents<WeightToFee, TokenLocation, AccountId, Balances, ToStakingPot<Runtime>>;
Branislav Kontur
committed
type ResponseHandler = PolkadotXcm;
type AssetTrap = PolkadotXcm;
type AssetLocker = ();
type AssetExchanger = ();
Branislav Kontur
committed
type AssetClaims = PolkadotXcm;
type SubscriptionService = PolkadotXcm;
type PalletInstancesInfo = AllPalletsWithSystem;
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
Serban Iorga
committed
type FeeManager = XcmFeeManagerFromComponents<
WaivedLocations,
(
XcmExportFeeToRelayerRewardAccounts<
Self::AssetTransactor,
Branislav Kontur
committed
crate::bridge_to_westend_config::WestendGlobalConsensusNetwork,
crate::bridge_to_westend_config::AssetHubWestendParaId,
crate::bridge_to_westend_config::BridgeHubWestendChainId,
crate::bridge_to_westend_config::AssetHubRococoToAssetHubWestendMessagesLane,
>,
Serban Iorga
committed
XcmFeeToAccount<Self::AssetTransactor, AccountId, TreasuryAccount>,
),
>;
Branislav Kontur
committed
type MessageExporter = (crate::bridge_to_westend_config::ToBridgeHubWestendHaulBlobExporter,);
type UniversalAliases = Nothing;
type CallDispatcher = WithOriginFilter<SafeCallFilter>;
type SafeCallFilter = SafeCallFilter;
Branislav Kontur
committed
}
pub type PriceForParentDelivery =
ExponentialPrice<FeeAssetId, BaseDeliveryFee, TransactionByteFee, ParachainSystem>;
Branislav Kontur
committed
/// Converts a local signed origin into an XCM multilocation.
/// Forms the basis for local origins sending/executing XCMs.
pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>;
/// The means for routing XCM messages which are not for local execution into the right message
/// queues.
Gavin Wood
committed
pub type XcmRouter = WithUniqueTopic<(
Branislav Kontur
committed
// Two routers - use UMP to communicate with the relay chain:
cumulus_primitives_utility::ParentAsUmp<ParachainSystem, PolkadotXcm, PriceForParentDelivery>,
Branislav Kontur
committed
// ..and XCMP to communicate with the sibling chains.
XcmpQueue,
Gavin Wood
committed
)>;
Branislav Kontur
committed
impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
Branislav Kontur
committed
// We want to disallow users sending (arbitrary) XCMs from this chain.
type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, ()>;
// We support local origins dispatching XCM executions in principle...
type ExecuteXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
type XcmExecuteFilter = Nothing;
type XcmExecutor = XcmExecutor<XcmConfig>;
type XcmTeleportFilter = Everything;
type XcmReserveTransferFilter = Nothing; // This parachain is not meant as a reserve location.
type Weigher = WeightInfoBounds<
crate::weights::xcm::BridgeHubRococoXcmWeight<RuntimeCall>,
RuntimeCall,
MaxInstructions,
>;
Branislav Kontur
committed
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
type Currency = Balances;
type CurrencyMatcher = ();
type TrustedLockers = ();
type SovereignAccountOf = LocationToAccountId;
type MaxLockers = ConstU32<8>;
type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
type AdminOrigin = EnsureRoot<AccountId>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
Branislav Kontur
committed
}
impl cumulus_pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type XcmExecutor = XcmExecutor<XcmConfig>;
}
Serban Iorga
committed
/// A `HandleFee` implementation that simply deposits the fees for `ExportMessage` XCM instructions
/// into the accounts that are used for paying the relayer rewards.
/// Burns the fees in case of a failure.
pub struct XcmExportFeeToRelayerRewardAccounts<
AssetTransactor,
DestNetwork,
DestParaId,
Branislav Kontur
committed
DestBridgedChainId,
Serban Iorga
committed
BridgeLaneId,
Branislav Kontur
committed
>(PhantomData<(AssetTransactor, DestNetwork, DestParaId, DestBridgedChainId, BridgeLaneId)>);
Serban Iorga
committed
impl<
AssetTransactor: TransactAsset,
DestNetwork: Get<NetworkId>,
DestParaId: Get<cumulus_primitives_core::ParaId>,
Branislav Kontur
committed
DestBridgedChainId: Get<ChainId>,
Serban Iorga
committed
BridgeLaneId: Get<LaneId>,
> HandleFee
for XcmExportFeeToRelayerRewardAccounts<
AssetTransactor,
DestNetwork,
DestParaId,
Branislav Kontur
committed
DestBridgedChainId,
Serban Iorga
committed
BridgeLaneId,
>
{
fn handle_fee(
fee: MultiAssets,
maybe_context: Option<&XcmContext>,
reason: FeeReason,
) -> MultiAssets {
if matches!(reason, FeeReason::Export { network: bridged_network, destination }
if bridged_network == DestNetwork::get() &&
destination == X1(Parachain(DestParaId::get().into())))
{
// We have 2 relayer rewards accounts:
// - the SA of the source parachain on this BH: this pays the relayers for delivering
// Source para -> Target Para message delivery confirmations
// - the SA of the destination parachain on this BH: this pays the relayers for
// delivering Target para -> Source Para messages
// We split the `ExportMessage` fee between these 2 accounts.
let source_para_account = PayRewardFromAccount::<
pallet_balances::Pallet<Runtime>,
AccountId,
>::rewards_account(RewardsAccountParams::new(
BridgeLaneId::get(),
Branislav Kontur
committed
DestBridgedChainId::get(),
Serban Iorga
committed
RewardsAccountOwner::ThisChain,
));
let dest_para_account = PayRewardFromAccount::<
pallet_balances::Pallet<Runtime>,
AccountId,
>::rewards_account(RewardsAccountParams::new(
BridgeLaneId::get(),
Branislav Kontur
committed
DestBridgedChainId::get(),
Serban Iorga
committed
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
RewardsAccountOwner::BridgedChain,
));
for asset in fee.into_inner() {
match asset.fun {
Fungible(total_fee) => {
let source_fee = total_fee / 2;
deposit_or_burn_fee::<AssetTransactor, _>(
MultiAsset { id: asset.id, fun: Fungible(source_fee) }.into(),
maybe_context,
source_para_account.clone(),
);
let dest_fee = total_fee - source_fee;
deposit_or_burn_fee::<AssetTransactor, _>(
MultiAsset { id: asset.id, fun: Fungible(dest_fee) }.into(),
maybe_context,
dest_para_account.clone(),
);
},
NonFungible(_) => {
deposit_or_burn_fee::<AssetTransactor, _>(
asset.into(),
maybe_context,
source_para_account.clone(),
);
},
}
}
return MultiAssets::new()
}
fee
}
}