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,
Serban Iorga
committed
use bp_messages::LaneId;
use bp_relayers::{PayRewardFromAccount, RewardsAccountOwner, RewardsAccountParams};
use bp_runtime::ChainId;
Branislav Kontur
committed
use frame_support::{
traits::{tokens::imbalance::ResolveTo, ConstU32, Contains, Equals, Everything, Nothing},
Branislav Kontur
committed
};
use pallet_collator_selection::StakingPotAccountId;
Branislav Kontur
committed
use pallet_xcm::XcmPassthrough;
![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 snowbridge_runtime_common::XcmExportFeeToSibling;
use sp_runtime::traits::AccountIdConversion;
Serban Iorga
committed
use sp_std::marker::PhantomData;
use testnet_parachains_constants::rococo::snowbridge::EthereumNetwork;
Branislav Kontur
committed
use xcm::latest::prelude::*;
use xcm_builder::{
Serban Iorga
committed
deposit_or_burn_fee, AccountId32Aliases, AllowExplicitUnpaidExecutionFrom,
Branislav Kontur
committed
AllowHrmpNotificationsFromRelayChain, AllowKnownQueryResponses, AllowSubscriptionsFrom,
AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin,
FrameTransactionalProcessor, FungibleAdapter, HandleFee, IsConcrete, ParentAsSuperuser,
ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
XcmFeeToAccount,
traits::{FeeManager, FeeReason, FeeReason::Export, TransactAsset},
Branislav Kontur
committed
};
parameter_types! {
pub const TokenLocation: Location = Location::parent();
Branislav Kontur
committed
pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
Branislav Kontur
committed
pub RelayNetwork: NetworkId = NetworkId::Rococo;
pub UniversalLocation: InteriorLocation =
[GlobalConsensus(RelayNetwork::get()), Parachain(ParachainInfo::parachain_id().into())].into();
pub const MaxInstructions: u32 = 100;
Serban Iorga
committed
pub TreasuryAccount: AccountId = TREASURY_PALLET_ID.into_account_truncating();
pub RelayTreasuryLocation: Location = (Parent, PalletInstance(rococo_runtime_constants::TREASURY_PALLET_ID)).into();
pub SiblingPeople: Location = (Parent, Parachain(rococo_runtime_constants::system_parachain::PEOPLE_ID)).into();
Branislav Kontur
committed
}
/// Type for specifying how a `Location` can be converted into an `AccountId`. This is used
Branislav Kontur
committed
/// 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 FungibleTransactor = FungibleAdapter<
Branislav Kontur
committed
// Use this currency:
Balances,
// Use this currency when it is a fungible asset matching the given location or name:
Adrian Catangiu
committed
IsConcrete<TokenLocation>,
// Do a simple punn to convert an AccountId32 Location into a native chain account ID:
Branislav Kontur
committed
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>,
);
pub struct ParentOrParentsPlurality;
impl Contains<Location> for ParentOrParentsPlurality {
fn contains(location: &Location) -> bool {
matches!(location.unpack(), (1, []) | (1, [Plurality { .. }]))
}
Branislav Kontur
committed
}
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>,
![Svyatoslav Nikolsky Svyatoslav Nikolsky's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Svyatoslav Nikolsky
committed
// Parent, its pluralities (i.e. governance bodies), relay treasury pallet
// and sibling People get free execution.
AllowExplicitUnpaidExecutionFrom<(
ParentOrParentsPlurality,
Equals<RelayTreasuryLocation>,
![Svyatoslav Nikolsky Svyatoslav Nikolsky's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Svyatoslav Nikolsky
committed
Equals<SiblingPeople>,
Gavin Wood
committed
// Subscriptions for version tracking are OK.
AllowSubscriptionsFrom<ParentRelayOrSiblingParachains>,
Branislav Kontur
committed
// HRMP notifications from the relay chain are OK.
AllowHrmpNotificationsFromRelayChain,
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;
Branislav Kontur
committed
type AssetTransactor = FungibleTransactor;
Branislav Kontur
committed
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,
>;
type Trader = UsingComponents<
WeightToFee,
TokenLocation,
AccountId,
Balances,
ResolveTo<StakingPotAccountId<Runtime>, Balances>,
>;
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;
type FeeManager = XcmFeeManagerFromComponentsBridgeHub<
Serban Iorga
committed
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,
>,
XcmExportFeeToSibling<
bp_rococo::Balance,
AccountId,
TokenLocation,
EthereumNetwork,
Self::AssetTransactor,
crate::EthereumOutboundQueue,
>,
Serban Iorga
committed
XcmFeeToAccount<Self::AssetTransactor, AccountId, TreasuryAccount>,
),
>;
![Svyatoslav Nikolsky Svyatoslav Nikolsky's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Svyatoslav Nikolsky
committed
type MessageExporter = (
crate::bridge_to_westend_config::ToBridgeHubWestendHaulBlobExporter,
crate::bridge_to_bulletin_config::ToRococoBulletinHaulBlobExporter,
crate::bridge_to_ethereum_config::SnowbridgeExporter,
![Svyatoslav Nikolsky Svyatoslav Nikolsky's avatar](/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png)
Svyatoslav Nikolsky
committed
);
type CallDispatcher = RuntimeCall;
type SafeCallFilter = Everything;
type TransactionalProcessor = FrameTransactionalProcessor;
type HrmpNewChannelOpenRequestHandler = ();
type HrmpChannelAcceptedHandler = ();
type HrmpChannelClosingHandler = ();
Branislav Kontur
committed
}
pub type PriceForParentDelivery =
ExponentialPrice<FeeAssetId, BaseDeliveryFee, TransactionByteFee, ParachainSystem>;
/// Converts a local signed origin into an XCM location.
Branislav Kontur
committed
/// 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.
Branislav Kontur
committed
type ExecuteXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
type XcmExecuteFilter = Everything;
Branislav Kontur
committed
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: Assets, maybe_context: Option<&XcmContext>, reason: FeeReason) -> Assets {
Serban Iorga
committed
if matches!(reason, FeeReason::Export { network: bridged_network, destination }
if bridged_network == DestNetwork::get() &&
Serban Iorga
committed
{
// 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
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, _>(
Asset { id: asset.id.clone(), fun: Fungible(source_fee) }.into(),
Serban Iorga
committed
maybe_context,
source_para_account.clone(),
);
let dest_fee = total_fee - source_fee;
deposit_or_burn_fee::<AssetTransactor, _>(
Asset { id: asset.id, fun: Fungible(dest_fee) }.into(),
Serban Iorga
committed
maybe_context,
dest_para_account.clone(),
);
},
NonFungible(_) => {
deposit_or_burn_fee::<AssetTransactor, _>(
asset.into(),
maybe_context,
source_para_account.clone(),
);
},
}
}
Serban Iorga
committed
}
fee
}
}
pub struct XcmFeeManagerFromComponentsBridgeHub<WaivedLocations, HandleFee>(
PhantomData<(WaivedLocations, HandleFee)>,
);
impl<WaivedLocations: Contains<Location>, FeeHandler: HandleFee> FeeManager
for XcmFeeManagerFromComponentsBridgeHub<WaivedLocations, FeeHandler>
{
fn is_waived(origin: Option<&Location>, fee_reason: FeeReason) -> bool {
let Some(loc) = origin else { return false };
if let Export { network, destination: Here } = fee_reason {
return !(network == EthereumNetwork::get())
}
WaivedLocations::contains(loc)
}
fn handle_fee(fee: Assets, context: Option<&XcmContext>, reason: FeeReason) {
FeeHandler::handle_fee(fee, context, reason);
}
}