Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions bridges/modules/xcm-bridge-router/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ sp-runtime = { workspace = true }
sp-std = { workspace = true }

# Polkadot Dependencies
polkadot-runtime-common = { workspace = true }
xcm = { workspace = true }
xcm-builder = { workspace = true }

Expand All @@ -45,6 +46,7 @@ std = [
"frame-support/std",
"frame-system/std",
"log/std",
"polkadot-runtime-common/std",
"scale-info/std",
"sp-core/std",
"sp-runtime/std",
Expand All @@ -56,12 +58,14 @@ runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"polkadot-runtime-common/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
"xcm/runtime-benchmarks",
]
try-runtime = [
"frame-support/try-runtime",
"frame-system/try-runtime",
"polkadot-runtime-common/try-runtime",
"sp-runtime/try-runtime",
]
33 changes: 33 additions & 0 deletions bridges/modules/xcm-bridge-router/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,39 @@ impl<T: Config<I>, I: 'static> bp_xcm_bridge::LocalXcmChannelManager<BridgeIdOf<
}
}

/// Calculates the price for message delivery across bridges with base price, dynamic fees
/// and size-based pricing.
pub struct GetPriceForBridge<T, I, BasePrice>(PhantomData<(T, I, BasePrice)>);
impl<T: Config<I>, I: 'static, BasePrice: Get<Assets>>
polkadot_runtime_common::xcm_sender::PriceForMessageDelivery
for GetPriceForBridge<T, I, BasePrice>
{
type Id = BridgeIdOf<T, I>;

fn price_for_delivery(bridge_id: Self::Id, message: &Xcm<()>) -> Assets {
// Get a base price.
let mut price = BasePrice::get();

// Apply message-size-based fees (if configured).
if let Some(message_size_fees) =
Pallet::<T, I>::calculate_message_size_fee(|| message.encoded_size() as _)
{
price.push(message_size_fees);
}

// Apply dynamic congestion fees based on bridge state (if needed).
if let Some(bridge_state) = Bridges::<T, I>::get(bridge_id) {
let mut dynamic_fees = price.into_inner();
for fee in dynamic_fees.iter_mut() {
Pallet::<T, I>::apply_dynamic_fee_factor(&bridge_state, fee);
}
price = Assets::from(dynamic_fees);
}

price
}
}

/// Adapter implementation for [`ExporterFor`] that allows exporting message size fee and/or dynamic
/// fees based on the `BridgeId` resolved by the `T::BridgeIdResolver` resolver, if and only if the
/// `E` exporter supports bridging. This adapter acts as an [`ExporterFor`], for example, for the
Expand Down
4 changes: 4 additions & 0 deletions bridges/modules/xcm-bridge/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ sp-runtime = { workspace = true }
sp-std = { workspace = true }

# Polkadot Dependencies
polkadot-runtime-common = { workspace = true }
xcm = { workspace = true }
xcm-builder = { workspace = true }
xcm-executor = { workspace = true }
Expand Down Expand Up @@ -60,6 +61,7 @@ std = [
"pallet-bridge-messages/std",
"pallet-xcm-bridge-router/std",
"polkadot-parachain-primitives/std",
"polkadot-runtime-common/std",
"scale-info/std",
"sp-core/std",
"sp-io/std",
Expand All @@ -77,6 +79,7 @@ runtime-benchmarks = [
"pallet-bridge-messages/runtime-benchmarks",
"pallet-xcm-bridge-router/runtime-benchmarks",
"polkadot-parachain-primitives/runtime-benchmarks",
"polkadot-runtime-common/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
"xcm-executor/runtime-benchmarks",
Expand All @@ -88,5 +91,6 @@ try-runtime = [
"pallet-balances/try-runtime",
"pallet-bridge-messages/try-runtime",
"pallet-xcm-bridge-router/try-runtime",
"polkadot-runtime-common/try-runtime",
"sp-runtime/try-runtime",
]
25 changes: 20 additions & 5 deletions bridges/modules/xcm-bridge/src/exporter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,19 @@ use frame_support::{ensure, traits::Get};
use pallet_bridge_messages::{
Config as BridgeMessagesConfig, Error, Pallet as BridgeMessagesPallet,
};
use polkadot_runtime_common::xcm_sender::PriceForMessageDelivery;
use xcm::prelude::*;
use xcm_builder::{HaulBlob, HaulBlobError, HaulBlobExporter};
use xcm_executor::traits::ExportXcm;

/// An easy way to access `HaulBlobExporter`.
///
/// Note: Set no price for `HaulBlobExporter`, because `ExportXcm for Pallet` handles the fees.
pub type PalletAsHaulBlobExporter<T, I> = HaulBlobExporter<
DummyHaulBlob,
<T as Config<I>>::BridgedNetwork,
<T as Config<I>>::DestinationVersion,
<T as Config<I>>::MessageExportPrice,
(),
>;
/// An easy way to access associated messages pallet.
type MessagesPallet<T, I> = BridgeMessagesPallet<T, <T as Config<I>>::BridgeMessagesPalletInstance>;
Expand Down Expand Up @@ -133,17 +136,29 @@ where
SendError::NotApplicable
})?;

// check if we are able to route the message. We use existing `HaulBlobExporter` for that.
// It will make all required changes and will encode message properly, so that the
// `DispatchBlob` at the bridged bridge hub will be able to decode it
let ((blob, id), price) = PalletAsHaulBlobExporter::<T, I>::validate(
// Get the potential price for a message over the bridge.
let price_for_delivery = message.as_ref().map(|msg| {
T::MessageExportPrice::price_for_delivery(locations.bridge_id().clone(), msg)
});

// check if we are able to route the message. We use the existing ` HaulBlobExporter ` for that.
// It will make all required changes and will encode a message properly, so that the
// `DispatchBlob` at the bridged xcm-bridge will be able to decode it.
let ((blob, id), mut price) = PalletAsHaulBlobExporter::<T, I>::validate(
network,
channel,
universal_source,
destination,
message,
)?;

// Add `price_for_delivery` to the `price`.
if let Some(delivery_prices) = price_for_delivery {
for dp in delivery_prices.into_inner() {
price.push(dp);
}
}

// Here, we know that the message is relevant to this pallet instance, so let's check for
// congestion defense.
if bridge.state == BridgeState::HardSuspended {
Expand Down
9 changes: 5 additions & 4 deletions bridges/modules/xcm-bridge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ use bp_xcm_bridge::{
use frame_support::{traits::fungible::MutateHold, DefaultNoBound};
use frame_system::Config as SystemConfig;
use pallet_bridge_messages::{Config as BridgeMessagesConfig, LanesManagerError};
use polkadot_runtime_common::xcm_sender::PriceForMessageDelivery;
use sp_std::{boxed::Box, vec::Vec};
use xcm::prelude::*;
use xcm_builder::DispatchBlob;
Expand Down Expand Up @@ -211,22 +212,22 @@ pub mod pallet {
// TODO: https://github.com/paritytech/parity-bridges-common/issues/1666 remove `ChainId` and
// replace it with the `NetworkId` - then we'll be able to use
// `T as pallet_bridge_messages::Config<T::BridgeMessagesPalletInstance>::BridgedChain::NetworkId`
/// Bridged network as relative location of bridged `GlobalConsensus`.
/// Bridged network as a relative location of bridged `GlobalConsensus`.
#[pallet::constant]
type BridgedNetwork: Get<Location>;
/// Associated messages pallet instance that bridges us with the
/// `BridgedNetworkId` consensus.
type BridgeMessagesPalletInstance: 'static;

/// Price of single message export to the bridged consensus (`Self::BridgedNetwork`).
type MessageExportPrice: Get<Assets>;
/// Price of a single message export to the bridged consensus (`Self::BridgedNetwork`).
type MessageExportPrice: PriceForMessageDelivery<Id = BridgeId>;
/// Checks the XCM version for the destination.
type DestinationVersion: GetVersion;

/// The origin that is allowed to call privileged operations on the pallet, e.g. open/close
/// bridge for locations.
type ForceOrigin: EnsureOrigin<<Self as SystemConfig>::RuntimeOrigin>;
/// A set of XCM locations within local consensus system that are allowed to open
/// A set of XCM locations within a local consensus system that are allowed to open
/// bridges with remote destinations.
type OpenBridgeOrigin: EnsureOrigin<
<Self as SystemConfig>::RuntimeOrigin,
Expand Down
3 changes: 2 additions & 1 deletion bridges/modules/xcm-bridge/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use pallet_xcm_bridge::congestion::{
UpdateBridgeStatusXcmChannelManager,
};
use polkadot_parachain_primitives::primitives::Sibling;
use polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery;
use sp_core::H256;
use sp_runtime::{
testing::Header as SubstrateHeader,
Expand Down Expand Up @@ -217,7 +218,7 @@ impl pallet_xcm_bridge::Config for TestRuntime {
type BridgedNetwork = BridgedRelayNetworkLocation;
type BridgeMessagesPalletInstance = ();

type MessageExportPrice = ();
type MessageExportPrice = NoPriceForMessageDelivery<BridgeId>;
type DestinationVersion = AlwaysLatest;

type ForceOrigin = EnsureNever<()>;
Expand Down
Loading