Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -512,8 +512,11 @@ macro_rules! test_can_estimate_and_pay_exact_fees {
assert_eq!(messages_to_query.len(), 1);
remote_message = messages_to_query[0].clone();
let delivery_fees =
Runtime::query_delivery_fees(destination_to_query.clone(), remote_message.clone())
.unwrap();
Runtime::query_delivery_fees(
destination_to_query.clone(),
remote_message.clone(),
VersionedAssetId::from(AssetId(Location::parent()))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to use macro overloading to parametrise this macro too, e.g. #8392

).unwrap();
local_delivery_fees = $crate::xcm_helpers::get_amount_from_versioned_assets(delivery_fees);
});

Expand Down Expand Up @@ -556,6 +559,7 @@ macro_rules! test_can_estimate_and_pay_exact_fees {
let delivery_fees = Runtime::query_delivery_fees(
destination_to_query.clone(),
intermediate_remote_message.clone(),
VersionedAssetId::from(AssetId(Location::new(1, []))),
)
.unwrap();
intermediate_delivery_fees = $crate::xcm_helpers::get_amount_from_versioned_assets(delivery_fees);
Expand Down Expand Up @@ -683,7 +687,7 @@ macro_rules! test_xcm_fee_querying_apis_work_for_asset_hub {
( $asset_hub:ty ) => {
$crate::macros::paste::paste! {
use emulated_integration_tests_common::USDT_ID;
use xcm_runtime_apis::fees::{Error as XcmPaymentApiError, runtime_decl_for_xcm_payment_api::XcmPaymentApiV1};
use xcm_runtime_apis::fees::{Error as XcmPaymentApiError, runtime_decl_for_xcm_payment_api::XcmPaymentApiV2};

$asset_hub::execute_with(|| {
// Setup a pool between USDT and WND.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use emulated_integration_tests_common::test_can_estimate_and_pay_exact_fees;
use frame_support::dispatch::RawOrigin;
use xcm_runtime_apis::{
dry_run::runtime_decl_for_dry_run_api::DryRunApiV2,
fees::runtime_decl_for_xcm_payment_api::XcmPaymentApiV1,
fees::runtime_decl_for_xcm_payment_api::XcmPaymentApiV2,
};

fn sender_assertions(test: ParaToParaThroughAHTest) {
Expand Down Expand Up @@ -157,8 +157,9 @@ fn multi_hop_works() {
.unwrap();
assert_eq!(messages_to_query.len(), 1);
remote_message = messages_to_query[0].clone();
let versioned_asset_id = VersionedAssetId::from(AssetId(Location::new(1, [])));
let delivery_fees =
Runtime::query_delivery_fees(destination_to_query.clone(), remote_message.clone())
Runtime::query_delivery_fees(destination_to_query.clone(), remote_message.clone(), versioned_asset_id)
.unwrap();
delivery_fees_amount = get_amount_from_versioned_assets(delivery_fees);
});
Expand Down Expand Up @@ -203,6 +204,7 @@ fn multi_hop_works() {
let delivery_fees = Runtime::query_delivery_fees(
destination_to_query.clone(),
intermediate_remote_message.clone(),
VersionedAssetId::from(AssetId(Location::here())),
)
.unwrap();
intermediate_delivery_fees_amount = get_amount_from_versioned_assets(delivery_fees);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use emulated_integration_tests_common::test_can_estimate_and_pay_exact_fees;
use frame_support::dispatch::RawOrigin;
use xcm_runtime_apis::{
dry_run::runtime_decl_for_dry_run_api::DryRunApiV2,
fees::runtime_decl_for_xcm_payment_api::XcmPaymentApiV1,
fees::runtime_decl_for_xcm_payment_api::XcmPaymentApiV2,
};

fn sender_assertions(test: ParaToParaThroughAHTest) {
Expand Down Expand Up @@ -160,7 +160,7 @@ fn multi_hop_works() {
assert_eq!(messages_to_query.len(), 1);
remote_message = messages_to_query[0].clone();
let delivery_fees =
Runtime::query_delivery_fees(destination_to_query.clone(), remote_message.clone())
Runtime::query_delivery_fees(destination_to_query.clone(), remote_message.clone(), VersionedAssetId::from(AssetId(Location::parent())))
.unwrap();
delivery_fees_amount = get_amount_from_versioned_assets(delivery_fees);
});
Expand Down Expand Up @@ -205,6 +205,7 @@ fn multi_hop_works() {
let delivery_fees = Runtime::query_delivery_fees(
destination_to_query.clone(),
intermediate_remote_message.clone(),
VersionedAssetId::from(AssetId(Location::new(1, [Parachain(2001)]))),
)
.unwrap();
intermediate_delivery_fees_amount = get_amount_from_versioned_assets(delivery_fees);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1588,7 +1588,7 @@ impl_runtime_apis! {
PolkadotXcm::query_xcm_weight(message)
}

fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>, _asset: VersionedAssetId) -> Result<VersionedAssets, XcmPaymentApiError> {
PolkadotXcm::query_delivery_fees(destination, message)
}
}
Expand Down
49 changes: 45 additions & 4 deletions cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ use assets_common::{
use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate};
use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight};
use xcm::{
latest::prelude::AssetId,
latest::prelude::{AssetId, Asset, Assets as XcmAssets, Fungible},
prelude::{VersionedAsset, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm},
Version as XcmVersion,
};
Expand All @@ -111,7 +111,7 @@ use frame_support::traits::PalletInfoAccess;

#[cfg(feature = "runtime-benchmarks")]
use xcm::latest::prelude::{
Asset, Assets as XcmAssets, Fungible, Here, InteriorLocation, Junction, Junction::*, Location,
Here, InteriorLocation, Junction, Junction::*, Location,
NetworkId, NonFungible, Parent, ParentThen, Response, XCM_VERSION,
};

Expand Down Expand Up @@ -1725,8 +1725,49 @@ impl_runtime_apis! {
PolkadotXcm::query_xcm_weight(message)
}

fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
PolkadotXcm::query_delivery_fees(destination, message)
fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>, asset: VersionedAssetId) -> Result<VersionedAssets, XcmPaymentApiError> {
let fee_in_native = PolkadotXcm::query_delivery_fees(destination, message)?;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather modify the helper query_delivery_fees in pallet-xcm so that other runtimes integrating this can just use that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this, I would need to add a new dependency, right? I added it into the implementation of XcmPaymentApi due to this comment.
It would have been much simpler to add it in pallet-xcm, but from what I understand, we’re going to let the runtime decide how to implement this.

For the query_weight_to_asset_fee, we also do the conversion in the runtime. This way, we can keep things more consistent by leaving all the conversions to be implemented by the runtime (I’m assuming that’s the case—I don’t know all the implementations 🤣).

Anyway, I’m going to leave this decision to you. Also, let me know if I got all wrong.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The runtime decides how to implement this, but we've seen in #8281 an example of using an existing configuration item to move more things into the helper function and make these APIs simpler to implement for teams

let asset_id: Result<AssetId, ()> = asset.clone().try_into();
let native_asset = xcm_config::WestendLocation::get();
match asset_id {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for adding this new functionality. I've noticed that the tests currently cover only the native asset branch. Would you mind adding tests for the remaining branches to ensure comprehensive coverage?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review! I didn't add test, because I'm waiting for @franciscoaguirre response about where the conversion should be implement. If you have any directions on this would be great, should I keep it where it is or should I move it to pallet-xcm

// For native asset there is no need to convert.
Ok(asset_id) if asset_id.0 == native_asset => {
Ok(fee_in_native)
},
Ok(asset_id) => {
let fee: XcmAssets = fee_in_native.clone().try_into().map_err(|()| {
log::trace!(target: "xcm::xcm_runtime_apis", "query_delivery_fees - failed to convert fee: {fee_in_native:?}!");
XcmPaymentApiError::VersionedConversionFailed
})?;

// Convert Fee to Fungible
let Fungible(balance) = fee.inner()[0].fun else {
unreachable!("fee is fungible");
};

// Try to get current price of `asset_id` in `native_asset`.
if let Ok(Some(swapped_in_native)) = assets_common::PoolAdapter::<Runtime>::quote_price_tokens_for_exact_tokens(
asset_id.0.clone(),
native_asset,
balance,
true,
) {
// convert Balance to VersionedAssets
let converted_asset = Asset {
id: asset_id,
fun: Fungible(swapped_in_native),
};
Ok(vec![converted_asset].into())
} else {
log::trace!(target: "xcm::xcm_runtime_apis", "query_delivery_fees - unhandled asset_id: {asset_id:?}!");
Err(XcmPaymentApiError::AssetNotFound)
}
},
Err(_) => {
log::trace!(target: "xcm::xcm_runtime_apis", "query_delivery_fees - failed to convert asset: {asset:?}!");
Err(XcmPaymentApiError::VersionedConversionFailed)
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ use sp_runtime::{
use xcm::{latest::prelude::*, VersionedAssets};
use xcm_executor::{traits::ConvertLocation, XcmExecutor};
use xcm_runtime_apis::fees::{
runtime_decl_for_xcm_payment_api::XcmPaymentApiV1, Error as XcmPaymentApiError,
runtime_decl_for_xcm_payment_api::XcmPaymentApiV2, Error as XcmPaymentApiError,
};

type RuntimeHelper<Runtime, AllPalletsWithoutSystem = ()> =
Expand Down Expand Up @@ -1600,7 +1600,7 @@ pub fn reserve_transfer_native_asset_to_non_teleport_para_works<

pub fn xcm_payment_api_with_pools_works<Runtime, RuntimeCall, RuntimeOrigin, Block>()
where
Runtime: XcmPaymentApiV1<Block>
Runtime: XcmPaymentApiV2<Block>
+ frame_system::Config<RuntimeOrigin = RuntimeOrigin, AccountId = AccountId>
+ pallet_balances::Config<Balance = u128>
+ pallet_session::Config
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -884,7 +884,7 @@ impl_runtime_apis! {
PolkadotXcm::query_xcm_weight(message)
}

fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>, _: VersionedAssetId) -> Result<VersionedAssets, XcmPaymentApiError> {
PolkadotXcm::query_delivery_fees(destination, message)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -835,7 +835,7 @@ impl_runtime_apis! {
PolkadotXcm::query_xcm_weight(message)
}

fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>, _: VersionedAssetId) -> Result<VersionedAssets, XcmPaymentApiError> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though bridge hub doesn't support multiple assets for fee payment, I would still throw an error if the asset is not the expected one ({ parents: 1, interior: Here })

PolkadotXcm::query_delivery_fees(destination, message)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1005,7 +1005,7 @@ impl_runtime_apis! {
PolkadotXcm::query_xcm_weight(message)
}

fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>, _: VersionedAssetId) -> Result<VersionedAssets, XcmPaymentApiError> {
PolkadotXcm::query_delivery_fees(destination, message)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -872,7 +872,7 @@ impl_runtime_apis! {
PolkadotXcm::query_xcm_weight(message)
}

fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>, _: VersionedAssetId) -> Result<VersionedAssets, XcmPaymentApiError> {
PolkadotXcm::query_delivery_fees(destination, message)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -873,7 +873,7 @@ impl_runtime_apis! {
PolkadotXcm::query_xcm_weight(message)
}

fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>, _: VersionedAssetId) -> Result<VersionedAssets, XcmPaymentApiError> {
PolkadotXcm::query_delivery_fees(destination, message)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -820,7 +820,7 @@ impl_runtime_apis! {
PolkadotXcm::query_xcm_weight(message)
}

fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>, _: VersionedAssetId) -> Result<VersionedAssets, XcmPaymentApiError> {
PolkadotXcm::query_delivery_fees(destination, message)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,7 @@ impl_runtime_apis! {
PolkadotXcm::query_xcm_weight(message)
}

fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>, _: VersionedAssetId) -> Result<VersionedAssets, XcmPaymentApiError> {
PolkadotXcm::query_delivery_fees(destination, message)
}
}
Expand Down
4 changes: 2 additions & 2 deletions cumulus/parachains/runtimes/test-utils/src/test_cases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use sp_runtime::{
};
use xcm::prelude::XcmError;
use xcm_runtime_apis::fees::{
runtime_decl_for_xcm_payment_api::XcmPaymentApiV1, Error as XcmPaymentApiError,
runtime_decl_for_xcm_payment_api::XcmPaymentApiV2, Error as XcmPaymentApiError,
};

type RuntimeHelper<Runtime, AllPalletsWithoutSystem = ()> =
Expand Down Expand Up @@ -150,7 +150,7 @@ pub fn set_storage_keys_by_governance_works<Runtime>(

pub fn xcm_payment_api_with_native_token_works<Runtime, RuntimeCall, RuntimeOrigin, Block>()
where
Runtime: XcmPaymentApiV1<Block>
Runtime: XcmPaymentApiV2<Block>
+ frame_system::Config<RuntimeOrigin = RuntimeOrigin, AccountId = AccountId>
+ pallet_balances::Config<Balance = u128>
+ pallet_session::Config
Expand Down
2 changes: 1 addition & 1 deletion cumulus/parachains/runtimes/testing/penpal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1109,7 +1109,7 @@ impl_runtime_apis! {
PolkadotXcm::query_xcm_weight(message)
}

fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>, _: VersionedAssetId) -> Result<VersionedAssets, XcmPaymentApiError> {
PolkadotXcm::query_delivery_fees(destination, message)
}
}
Expand Down
2 changes: 1 addition & 1 deletion polkadot/node/service/src/fake_runtime_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ sp_api::impl_runtime_apis! {
unimplemented!()
}

fn query_delivery_fees(_: VersionedLocation, _: VersionedXcm<()>) -> Result<VersionedAssets, xcm_runtime_apis::fees::Error> {
fn query_delivery_fees(_: VersionedLocation, _: VersionedXcm<()>, _: VersionedAssetId) -> Result<VersionedAssets, xcm_runtime_apis::fees::Error> {
unimplemented!()
}
}
Expand Down
2 changes: 1 addition & 1 deletion polkadot/runtime/rococo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1915,7 +1915,7 @@ sp_api::impl_runtime_apis! {
XcmPallet::query_xcm_weight(message)
}

fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>, _: VersionedAssetId) -> Result<VersionedAssets, XcmPaymentApiError> {
XcmPallet::query_delivery_fees(destination, message)
}
}
Expand Down
2 changes: 1 addition & 1 deletion polkadot/runtime/westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2669,7 +2669,7 @@ sp_api::impl_runtime_apis! {
XcmPallet::query_xcm_weight(message)
}

fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>, _: VersionedAssetId) -> Result<VersionedAssets, XcmPaymentApiError> {
XcmPallet::query_delivery_fees(destination, message)
}
}
Expand Down
15 changes: 14 additions & 1 deletion polkadot/xcm/xcm-runtime-apis/src/fees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ sp_api::decl_runtime_apis! {
///
/// To determine the execution weight of the calls required for
/// [`xcm::latest::Instruction::Transact`] instruction, `TransactionPaymentCallApi` can be used.
#[api_version(2)]
pub trait XcmPaymentApi {
/// Returns a list of acceptable payment assets.
///
Expand All @@ -58,14 +59,26 @@ sp_api::decl_runtime_apis! {
fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, Error>;

/// Get delivery fees for sending a specific `message` to a `destination`.
/// These always come in a specific asset, defined by the chain.
/// These always come in a specific asset, defined by the chain. Version 1
///
/// # Arguments
/// * `message`: The message that'll be sent, necessary because most delivery fees are based on the
/// size of the message.
/// * `destination`: The destination to send the message to. Different destinations may use
/// different senders that charge different fees.
#[changed_in(2)]
fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, Error>;

/// Get delivery fees for sending a specific `message` to a `destination`.
/// These always come in a specific asset, defined by the parameter `asset`.
///
/// # Arguments
/// * `asset`: The asset to charge fees in.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to end of argument list

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function signature currently is (destination: VersionedLocation, message: VersionedXcm<()>, asset: VersionedAssetId). And in the argument list it looks like the order is starting from the last.

  • asset
  • message
  • destination

This is why I left this as the first argument in the list instead of put it in at the end. What do you think?

/// * `message`: The message that'll be sent, necessary because most delivery fees are based on the
/// size of the message.
/// * `destination`: The destination to send the message to. Different destinations may use
/// different senders that charge different fees.
fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>, asset: VersionedAssetId) -> Result<VersionedAssets, Error>;
}
}

Expand Down
5 changes: 3 additions & 2 deletions polkadot/xcm/xcm-runtime-apis/tests/fee_estimation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,13 @@ fn fee_estimation_for_teleport() {
// results.
let weight =
runtime_api.query_xcm_weight(H256::zero(), local_xcm.clone()).unwrap().unwrap();
let versioned_asset = VersionedAssetId::from(AssetId(HereLocation::get()));
assert_eq!(weight, Weight::from_parts(400, 40));
let execution_fees = runtime_api
.query_weight_to_asset_fee(
H256::zero(),
weight,
VersionedAssetId::from(AssetId(HereLocation::get())),
versioned_asset.clone(),
)
.unwrap()
.unwrap();
Expand All @@ -160,7 +161,7 @@ fn fee_estimation_for_teleport() {
let remote_message = &remote_messages[0];

let delivery_fees = runtime_api
.query_delivery_fees(H256::zero(), destination.clone(), remote_message.clone())
.query_delivery_fees(H256::zero(), destination.clone(), remote_message.clone(), versioned_asset)
.unwrap()
.unwrap();
assert_eq!(delivery_fees, VersionedAssets::from((Here, 20u128)));
Expand Down
2 changes: 1 addition & 1 deletion polkadot/xcm/xcm-runtime-apis/tests/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ sp_api::mock_impl_runtime_apis! {
}
}

fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>, _: VersionedAssetId) -> Result<VersionedAssets, XcmPaymentApiError> {
XcmPallet::query_delivery_fees(destination, message)
}
}
Expand Down
Loading