From 17b080b747f2dc4690e961acf7ebd4a319cade83 Mon Sep 17 00:00:00 2001 From: Francisco Aguirre Date: Tue, 15 Oct 2024 23:34:05 +0200 Subject: [PATCH 01/16] fix: assets in pool with native can be used to query for fees --- .../assets/asset-hub-rococo/src/lib.rs | 46 +++++++++++------- .../assets/asset-hub-westend/src/lib.rs | 48 ++++++++++++------- 2 files changed, 59 insertions(+), 35 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 595e3d0711a2..919b5e075e48 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -1338,31 +1338,31 @@ impl_runtime_apis! { // We accept the native token to pay fees. let mut acceptable_assets = vec![AssetId(native_token.clone())]; // We also accept all assets in a pool with the native token. - acceptable_assets.extend( - pallet_asset_conversion::Pools::::iter_keys().filter_map( - |(asset_1, asset_2)| { - if asset_1 == native_token { - Some(asset_2.clone().into()) - } else if asset_2 == native_token { - Some(asset_1.clone().into()) - } else { - None - } - }, - ), - ); + acceptable_assets.extend(get_assets_in_pool_with(native_token.clone())); PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets) } fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result { + let native_asset = xcm_config::TokenLocation::get(); + let fee_in_native = WeightToFee::weight_to_fee(&weight); match asset.try_as::() { - Ok(asset_id) if asset_id.0 == xcm_config::TokenLocation::get() => { + Ok(asset_id) if asset_id.0 == native_asset => { // for native token - Ok(WeightToFee::weight_to_fee(&weight)) + Ok(fee_in_native) }, Ok(asset_id) => { - log::trace!(target: "xcm::xcm_runtime_apis", "query_weight_to_asset_fee - unhandled asset_id: {asset_id:?}!"); - Err(XcmPaymentApiError::AssetNotFound) + let assets_in_pool_with_native_token: Vec<_> = get_assets_in_pool_with(native_asset.clone()).collect(); + if assets_in_pool_with_native_token.contains(&asset_id) { + pallet_asset_conversion::Pallet::::quote_price_tokens_for_exact_tokens( + asset_id.clone().0, + native_asset, + fee_in_native, + true, // We include the fee. + ).ok_or(XcmPaymentApiError::AssetNotFound) + } else { + log::trace!(target: "xcm::xcm_runtime_apis", "query_weight_to_asset_fee - unhandled asset_id: {asset_id:?}!"); + Err(XcmPaymentApiError::AssetNotFound) + } }, Err(_) => { log::trace!(target: "xcm::xcm_runtime_apis", "query_weight_to_asset_fee - failed to convert asset: {asset:?}!"); @@ -1799,6 +1799,18 @@ impl_runtime_apis! { } } +fn get_assets_in_pool_with(asset: xcm::v4::Location) -> impl Iterator { + pallet_asset_conversion::Pools::::iter_keys().filter_map(move |(asset_1, asset_2)| { + if asset_1 == asset { + Some(asset_2.clone().into()) + } else if asset_2 == asset { + Some(asset_1.clone().into()) + } else { + None + } + }) +} + cumulus_pallet_parachain_system::register_validate_block! { Runtime = Runtime, BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index bd3ba10d5dfc..0e878163612e 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1371,31 +1371,31 @@ impl_runtime_apis! { // We accept the native token to pay fees. let mut acceptable_assets = vec![AssetId(native_token.clone())]; // We also accept all assets in a pool with the native token. - acceptable_assets.extend( - pallet_asset_conversion::Pools::::iter_keys().filter_map( - |(asset_1, asset_2)| { - if asset_1 == native_token { - Some(asset_2.clone().into()) - } else if asset_2 == native_token { - Some(asset_1.clone().into()) - } else { - None - } - }, - ), - ); + acceptable_assets.extend(get_assets_in_pool_with(native_token.clone())); PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets) } fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result { + let native_asset = xcm_config::WestendLocation::get(); + let fee_in_native = WeightToFee::weight_to_fee(&weight); match asset.try_as::() { - Ok(asset_id) if asset_id.0 == xcm_config::WestendLocation::get() => { - // for native token - Ok(WeightToFee::weight_to_fee(&weight)) + Ok(asset_id) if asset_id.0 == native_asset => { + // for native asset + Ok(fee_in_native) }, Ok(asset_id) => { - log::trace!(target: "xcm::xcm_runtime_apis", "query_weight_to_asset_fee - unhandled asset_id: {asset_id:?}!"); - Err(XcmPaymentApiError::AssetNotFound) + let assets_in_pool_with_native_token: Vec<_> = get_assets_in_pool_with(native_asset.clone()).collect(); + if assets_in_pool_with_native_token.contains(&asset_id) { + pallet_asset_conversion::Pallet::::quote_price_tokens_for_exact_tokens( + asset_id.clone().0, + native_asset, + fee_in_native, + true, // We include the fee. + ).ok_or(XcmPaymentApiError::AssetNotFound) + } else { + log::trace!(target: "xcm::xcm_runtime_apis", "query_weight_to_asset_fee - unhandled asset_id: {asset_id:?}!"); + Err(XcmPaymentApiError::AssetNotFound) + } }, Err(_) => { log::trace!(target: "xcm::xcm_runtime_apis", "query_weight_to_asset_fee - failed to convert asset: {asset:?}!"); @@ -1895,6 +1895,18 @@ impl_runtime_apis! { } } +fn get_assets_in_pool_with(asset: xcm::v4::Location) -> impl Iterator { + pallet_asset_conversion::Pools::::iter_keys().filter_map(move |(asset_1, asset_2)| { + if asset_1 == asset { + Some(asset_2.clone().into()) + } else if asset_2 == asset { + Some(asset_1.clone().into()) + } else { + None + } + }) +} + cumulus_pallet_parachain_system::register_validate_block! { Runtime = Runtime, BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, From 375908a7436f32d7734d52dfdacfd6065341dbcd Mon Sep 17 00:00:00 2001 From: Francisco Aguirre Date: Fri, 18 Oct 2024 08:23:58 -0300 Subject: [PATCH 02/16] chore: refactor pools helper function to assets-common --- .../assets/asset-hub-rococo/src/lib.rs | 18 +++--------------- .../assets/asset-hub-westend/src/lib.rs | 19 ++++--------------- .../runtimes/assets/common/src/lib.rs | 15 +++++++++++++++ 3 files changed, 22 insertions(+), 30 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 919b5e075e48..b7595b8c3672 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -1338,7 +1338,7 @@ impl_runtime_apis! { // We accept the native token to pay fees. let mut acceptable_assets = vec![AssetId(native_token.clone())]; // We also accept all assets in a pool with the native token. - acceptable_assets.extend(get_assets_in_pool_with(native_token.clone())); + acceptable_assets.extend(assets_common::get_assets_in_pool_with::(&native_token).map(|location| AssetId(location))); PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets) } @@ -1351,8 +1351,8 @@ impl_runtime_apis! { Ok(fee_in_native) }, Ok(asset_id) => { - let assets_in_pool_with_native_token: Vec<_> = get_assets_in_pool_with(native_asset.clone()).collect(); - if assets_in_pool_with_native_token.contains(&asset_id) { + let assets_in_pool_with_native_token: Vec<_> = assets_common::get_assets_in_pool_with::(&native_asset).collect(); + if assets_in_pool_with_native_token.contains(&asset_id.0) { pallet_asset_conversion::Pallet::::quote_price_tokens_for_exact_tokens( asset_id.clone().0, native_asset, @@ -1799,18 +1799,6 @@ impl_runtime_apis! { } } -fn get_assets_in_pool_with(asset: xcm::v4::Location) -> impl Iterator { - pallet_asset_conversion::Pools::::iter_keys().filter_map(move |(asset_1, asset_2)| { - if asset_1 == asset { - Some(asset_2.clone().into()) - } else if asset_2 == asset { - Some(asset_1.clone().into()) - } else { - None - } - }) -} - cumulus_pallet_parachain_system::register_validate_block! { Runtime = Runtime, BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 0e878163612e..cf8b2cec71b3 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1371,10 +1371,11 @@ impl_runtime_apis! { // We accept the native token to pay fees. let mut acceptable_assets = vec![AssetId(native_token.clone())]; // We also accept all assets in a pool with the native token. - acceptable_assets.extend(get_assets_in_pool_with(native_token.clone())); + acceptable_assets.extend(assets_common::get_assets_in_pool_with::(&native_token).map(|location| AssetId(location))); PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets) } + // TODO: Some rust tests. fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result { let native_asset = xcm_config::WestendLocation::get(); let fee_in_native = WeightToFee::weight_to_fee(&weight); @@ -1384,8 +1385,8 @@ impl_runtime_apis! { Ok(fee_in_native) }, Ok(asset_id) => { - let assets_in_pool_with_native_token: Vec<_> = get_assets_in_pool_with(native_asset.clone()).collect(); - if assets_in_pool_with_native_token.contains(&asset_id) { + let assets_in_pool_with_native_token: Vec<_> = assets_common::get_assets_in_pool_with::(&native_asset).collect(); + if assets_in_pool_with_native_token.contains(&asset_id.0) { pallet_asset_conversion::Pallet::::quote_price_tokens_for_exact_tokens( asset_id.clone().0, native_asset, @@ -1895,18 +1896,6 @@ impl_runtime_apis! { } } -fn get_assets_in_pool_with(asset: xcm::v4::Location) -> impl Iterator { - pallet_asset_conversion::Pools::::iter_keys().filter_map(move |(asset_1, asset_2)| { - if asset_1 == asset { - Some(asset_2.clone().into()) - } else if asset_2 == asset { - Some(asset_1.clone().into()) - } else { - None - } - }) -} - cumulus_pallet_parachain_system::register_validate_block! { Runtime = Runtime, BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, diff --git a/cumulus/parachains/runtimes/assets/common/src/lib.rs b/cumulus/parachains/runtimes/assets/common/src/lib.rs index deda5fa4ab9c..0c20d7d9fe0b 100644 --- a/cumulus/parachains/runtimes/assets/common/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/common/src/lib.rs @@ -134,6 +134,21 @@ pub type PoolAssetsConvertedConcreteId = TryConvertInto, >; +/// Returns an iterator of all assets in a pool with `asset`. +/// +/// Should only be used in runtime APIs since it iterates over the whole `pallet_asset_conversion::Pools` map. +pub fn get_assets_in_pool_with>(asset: &xcm::v4::Location) -> impl Iterator + '_ { + pallet_asset_conversion::Pools::::iter_keys().filter_map(move |(asset_1, asset_2)| { + if asset_1 == *asset { + Some(asset_2.clone().into()) + } else if asset_2 == *asset { + Some(asset_1.clone().into()) + } else { + None + } + }) +} + #[cfg(test)] mod tests { use super::*; From aec5b5b0ac4ad409fa2c857d84d529cc58050d16 Mon Sep 17 00:00:00 2001 From: Francisco Aguirre Date: Fri, 18 Oct 2024 08:24:16 -0300 Subject: [PATCH 03/16] test(asset-hub-westend-integration-tests): XcmPaymentApi --- .../asset-hub-westend/src/tests/swap.rs | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/swap.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/swap.rs index 1a2821452155..0968767af7fb 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/swap.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/swap.rs @@ -389,3 +389,67 @@ fn pay_xcm_fee_with_some_asset_swapped_for_native() { ); }); } + +#[test] +fn xcm_fee_querying_apis_work() { + use emulated_integration_tests_common::USDT_ID; + use xcm_runtime_apis::fees::{Error as XcmPaymentApiError, runtime_decl_for_xcm_payment_api::XcmPaymentApiV1}; + + AssetHubWestend::execute_with(|| { + // Setup a pool between USDT and WND. + type RuntimeOrigin = ::RuntimeOrigin; + type Assets = ::Assets; + type AssetConversion = ::AssetConversion; + let wnd = Location::new(1, []); + let usdt = Location::new(0, [PalletInstance(ASSETS_PALLET_ID), GeneralIndex(USDT_ID.into())]); + let sender = AssetHubWestendSender::get(); + assert_ok!(AssetConversion::create_pool( + RuntimeOrigin::signed(sender.clone()), + Box::new(wnd.clone()), + Box::new(usdt.clone()), + )); + + type Runtime = ::Runtime; + let acceptable_payment_assets = Runtime::query_acceptable_payment_assets(4).unwrap(); + assert_eq!(acceptable_payment_assets, vec![ + VersionedAssetId::from(AssetId(wnd.clone())), + VersionedAssetId::from(AssetId(usdt.clone())), + ]); + + let program = Xcm::<()>::builder() + .withdraw_asset((Parent, 100u128)) + .buy_execution((Parent, 10u128), Unlimited) + .deposit_asset(All, [0u8; 32]) + .build(); + let weight = Runtime::query_xcm_weight(VersionedXcm::from(program)).unwrap(); + let fee_in_wnd = Runtime::query_weight_to_asset_fee(weight, VersionedAssetId::from(AssetId(wnd.clone()))).unwrap(); + // Assets not in a pool don't work. + assert!(Runtime::query_weight_to_asset_fee(weight, VersionedAssetId::from(AssetId(Location::new(0, [PalletInstance(ASSETS_PALLET_ID), GeneralIndex(1)])))).is_err()); + let fee_in_usdt_fail = Runtime::query_weight_to_asset_fee(weight, VersionedAssetId::from(AssetId(usdt.clone()))); + // Weight to asset fee fails because there's not enough asset in the pool. + // We just created it, there's none. + assert_eq!(fee_in_usdt_fail, Err(XcmPaymentApiError::AssetNotFound)); + // We add some. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(sender.clone()), + USDT_ID.into(), + sender.clone().into(), + 5_000_000_000_000 + )); + // We make 1 WND = 4 USDT. + assert_ok!(AssetConversion::add_liquidity( + RuntimeOrigin::signed(sender.clone()), + Box::new(wnd), + Box::new(usdt.clone()), + 1_000_000_000_000, + 4_000_000_000_000, + 0, + 0, + sender.into() + )); + // Now it works. + let fee_in_usdt = Runtime::query_weight_to_asset_fee(weight, VersionedAssetId::from(AssetId(usdt))); + assert_ok!(fee_in_usdt); + assert!(fee_in_usdt.unwrap() > fee_in_wnd); + }); +} From dcbb7966cfa9fb15f3b63c3a89dc48af4df204ba Mon Sep 17 00:00:00 2001 From: Francisco Aguirre Date: Fri, 18 Oct 2024 08:39:27 -0300 Subject: [PATCH 04/16] chore: move test to macro and use in both asset hubs --- .../emulated/common/src/macros.rs | 68 +++++++++++++++++++ .../tests/assets/asset-hub-rococo/src/lib.rs | 1 + .../assets/asset-hub-rococo/src/tests/swap.rs | 5 ++ .../tests/assets/asset-hub-westend/src/lib.rs | 1 + .../asset-hub-westend/src/tests/swap.rs | 61 +---------------- 5 files changed, 76 insertions(+), 60 deletions(-) diff --git a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs index 68926b04bfe6..3ff5ed388a39 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs @@ -451,3 +451,71 @@ macro_rules! test_dry_run_transfer_across_pk_bridge { } }; } + +#[macro_export] +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}; + + $asset_hub::execute_with(|| { + // Setup a pool between USDT and WND. + type RuntimeOrigin = <$asset_hub as Chain>::RuntimeOrigin; + type Assets = <$asset_hub as [<$asset_hub Pallet>]>::Assets; + type AssetConversion = <$asset_hub as [<$asset_hub Pallet>]>::AssetConversion; + let wnd = Location::new(1, []); + let usdt = Location::new(0, [PalletInstance(ASSETS_PALLET_ID), GeneralIndex(USDT_ID.into())]); + let sender = [<$asset_hub Sender>]::get(); + assert_ok!(AssetConversion::create_pool( + RuntimeOrigin::signed(sender.clone()), + Box::new(wnd.clone()), + Box::new(usdt.clone()), + )); + + type Runtime = <$asset_hub as Chain>::Runtime; + let acceptable_payment_assets = Runtime::query_acceptable_payment_assets(4).unwrap(); + assert_eq!(acceptable_payment_assets, vec![ + VersionedAssetId::from(AssetId(wnd.clone())), + VersionedAssetId::from(AssetId(usdt.clone())), + ]); + + let program = Xcm::<()>::builder() + .withdraw_asset((Parent, 100u128)) + .buy_execution((Parent, 10u128), Unlimited) + .deposit_asset(All, [0u8; 32]) + .build(); + let weight = Runtime::query_xcm_weight(VersionedXcm::from(program)).unwrap(); + let fee_in_wnd = Runtime::query_weight_to_asset_fee(weight, VersionedAssetId::from(AssetId(wnd.clone()))).unwrap(); + // Assets not in a pool don't work. + assert!(Runtime::query_weight_to_asset_fee(weight, VersionedAssetId::from(AssetId(Location::new(0, [PalletInstance(ASSETS_PALLET_ID), GeneralIndex(1)])))).is_err()); + let fee_in_usdt_fail = Runtime::query_weight_to_asset_fee(weight, VersionedAssetId::from(AssetId(usdt.clone()))); + // Weight to asset fee fails because there's not enough asset in the pool. + // We just created it, there's none. + assert_eq!(fee_in_usdt_fail, Err(XcmPaymentApiError::AssetNotFound)); + // We add some. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(sender.clone()), + USDT_ID.into(), + sender.clone().into(), + 5_000_000_000_000 + )); + // We make 1 WND = 4 USDT. + assert_ok!(AssetConversion::add_liquidity( + RuntimeOrigin::signed(sender.clone()), + Box::new(wnd), + Box::new(usdt.clone()), + 1_000_000_000_000, + 4_000_000_000_000, + 0, + 0, + sender.into() + )); + // Now it works. + let fee_in_usdt = Runtime::query_weight_to_asset_fee(weight, VersionedAssetId::from(AssetId(usdt))); + assert_ok!(fee_in_usdt); + assert!(fee_in_usdt.unwrap() > fee_in_wnd); + }); + } + }; +} diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs index 0e43108a417b..4b907fc29de8 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs @@ -38,6 +38,7 @@ mod imports { accounts::DUMMY_EMPTY, get_account_id_from_seed, test_parachain_is_trusted_teleporter, test_parachain_is_trusted_teleporter_for_relay, test_relay_is_trusted_teleporter, + test_xcm_fee_querying_apis_work_for_asset_hub, xcm_emulator::{ assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, Test, TestArgs, TestContext, TestExt, diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/swap.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/swap.rs index ac0c90ba198d..d9b32eaa357e 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/swap.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/swap.rs @@ -386,3 +386,8 @@ fn pay_xcm_fee_with_some_asset_swapped_for_native() { ); }); } + +#[test] +fn xcm_fee_querying_apis_work() { + test_xcm_fee_querying_apis_work_for_asset_hub!(AssetHubRococo); +} diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs index d0016b5a1b15..d9cb28d84737 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs @@ -35,6 +35,7 @@ mod imports { accounts::DUMMY_EMPTY, get_account_id_from_seed, test_parachain_is_trusted_teleporter, test_parachain_is_trusted_teleporter_for_relay, test_relay_is_trusted_teleporter, + test_xcm_fee_querying_apis_work_for_asset_hub, xcm_emulator::{ assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, Test, TestArgs, TestContext, TestExt, diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/swap.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/swap.rs index 0968767af7fb..4535fd431990 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/swap.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/swap.rs @@ -392,64 +392,5 @@ fn pay_xcm_fee_with_some_asset_swapped_for_native() { #[test] fn xcm_fee_querying_apis_work() { - use emulated_integration_tests_common::USDT_ID; - use xcm_runtime_apis::fees::{Error as XcmPaymentApiError, runtime_decl_for_xcm_payment_api::XcmPaymentApiV1}; - - AssetHubWestend::execute_with(|| { - // Setup a pool between USDT and WND. - type RuntimeOrigin = ::RuntimeOrigin; - type Assets = ::Assets; - type AssetConversion = ::AssetConversion; - let wnd = Location::new(1, []); - let usdt = Location::new(0, [PalletInstance(ASSETS_PALLET_ID), GeneralIndex(USDT_ID.into())]); - let sender = AssetHubWestendSender::get(); - assert_ok!(AssetConversion::create_pool( - RuntimeOrigin::signed(sender.clone()), - Box::new(wnd.clone()), - Box::new(usdt.clone()), - )); - - type Runtime = ::Runtime; - let acceptable_payment_assets = Runtime::query_acceptable_payment_assets(4).unwrap(); - assert_eq!(acceptable_payment_assets, vec![ - VersionedAssetId::from(AssetId(wnd.clone())), - VersionedAssetId::from(AssetId(usdt.clone())), - ]); - - let program = Xcm::<()>::builder() - .withdraw_asset((Parent, 100u128)) - .buy_execution((Parent, 10u128), Unlimited) - .deposit_asset(All, [0u8; 32]) - .build(); - let weight = Runtime::query_xcm_weight(VersionedXcm::from(program)).unwrap(); - let fee_in_wnd = Runtime::query_weight_to_asset_fee(weight, VersionedAssetId::from(AssetId(wnd.clone()))).unwrap(); - // Assets not in a pool don't work. - assert!(Runtime::query_weight_to_asset_fee(weight, VersionedAssetId::from(AssetId(Location::new(0, [PalletInstance(ASSETS_PALLET_ID), GeneralIndex(1)])))).is_err()); - let fee_in_usdt_fail = Runtime::query_weight_to_asset_fee(weight, VersionedAssetId::from(AssetId(usdt.clone()))); - // Weight to asset fee fails because there's not enough asset in the pool. - // We just created it, there's none. - assert_eq!(fee_in_usdt_fail, Err(XcmPaymentApiError::AssetNotFound)); - // We add some. - assert_ok!(Assets::mint( - RuntimeOrigin::signed(sender.clone()), - USDT_ID.into(), - sender.clone().into(), - 5_000_000_000_000 - )); - // We make 1 WND = 4 USDT. - assert_ok!(AssetConversion::add_liquidity( - RuntimeOrigin::signed(sender.clone()), - Box::new(wnd), - Box::new(usdt.clone()), - 1_000_000_000_000, - 4_000_000_000_000, - 0, - 0, - sender.into() - )); - // Now it works. - let fee_in_usdt = Runtime::query_weight_to_asset_fee(weight, VersionedAssetId::from(AssetId(usdt))); - assert_ok!(fee_in_usdt); - assert!(fee_in_usdt.unwrap() > fee_in_wnd); - }); + test_xcm_fee_querying_apis_work_for_asset_hub!(AssetHubWestend); } From 30cf71123ca8a9555ce863cd2e49d933817e5c34 Mon Sep 17 00:00:00 2001 From: Francisco Aguirre Date: Fri, 18 Oct 2024 08:40:08 -0300 Subject: [PATCH 05/16] chore: remove comment --- cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index cf8b2cec71b3..1758f13369da 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1375,7 +1375,6 @@ impl_runtime_apis! { PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets) } - // TODO: Some rust tests. fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result { let native_asset = xcm_config::WestendLocation::get(); let fee_in_native = WeightToFee::weight_to_fee(&weight); From a4e80ac70ae09d97b6e01bee2b4f56464583044e Mon Sep 17 00:00:00 2001 From: Francisco Aguirre Date: Fri, 18 Oct 2024 08:46:43 -0300 Subject: [PATCH 06/16] doc: add prdoc --- prdoc/pr_6080.prdoc | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 prdoc/pr_6080.prdoc diff --git a/prdoc/pr_6080.prdoc b/prdoc/pr_6080.prdoc new file mode 100644 index 000000000000..8abc90f0f412 --- /dev/null +++ b/prdoc/pr_6080.prdoc @@ -0,0 +1,22 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: [Asset Hubs] Assets in pool with native can be used in query_weight_to_asset_fee + +doc: + - audience: Runtime User + description: | + `query_weight_to_asset_fee` now works with assets in a pool with the native asset in both + Westend and Rococo asset hubs. + This means all the information you get from `query_acceptable_payment_assets` can be used + directly in `query_weight_to_asset_fee` to get the correct fees that need to be paid. + +crates: + - name: assets-common + bump: minor + - name: asset-hub-westend-runtime + bump: minor + - name: asset-hub-rococo-runtime + bump: minor + - name: emulated-integration-tests-common + bump: minor From 912179066eebb5ec30f08ba7d3ba134229c730a8 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Fri, 18 Oct 2024 11:50:19 +0000 Subject: [PATCH 07/16] ".git/.scripts/commands/fmt/fmt.sh" --- .../emulated/tests/assets/asset-hub-westend/src/lib.rs | 3 +-- cumulus/parachains/runtimes/assets/common/src/lib.rs | 9 +++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs index b0fe1f4e4344..179a44e14aa1 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs @@ -34,8 +34,7 @@ mod imports { pub use emulated_integration_tests_common::{ accounts::DUMMY_EMPTY, test_parachain_is_trusted_teleporter, test_parachain_is_trusted_teleporter_for_relay, - test_relay_is_trusted_teleporter, - test_xcm_fee_querying_apis_work_for_asset_hub, + test_relay_is_trusted_teleporter, test_xcm_fee_querying_apis_work_for_asset_hub, xcm_emulator::{ assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, Test, TestArgs, TestContext, TestExt, diff --git a/cumulus/parachains/runtimes/assets/common/src/lib.rs b/cumulus/parachains/runtimes/assets/common/src/lib.rs index 0c20d7d9fe0b..0a04ec458bd1 100644 --- a/cumulus/parachains/runtimes/assets/common/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/common/src/lib.rs @@ -136,8 +136,13 @@ pub type PoolAssetsConvertedConcreteId = /// Returns an iterator of all assets in a pool with `asset`. /// -/// Should only be used in runtime APIs since it iterates over the whole `pallet_asset_conversion::Pools` map. -pub fn get_assets_in_pool_with>(asset: &xcm::v4::Location) -> impl Iterator + '_ { +/// Should only be used in runtime APIs since it iterates over the whole +/// `pallet_asset_conversion::Pools` map. +pub fn get_assets_in_pool_with< + Runtime: pallet_asset_conversion::Config, +>( + asset: &xcm::v4::Location, +) -> impl Iterator + '_ { pallet_asset_conversion::Pools::::iter_keys().filter_map(move |(asset_1, asset_2)| { if asset_1 == *asset { Some(asset_2.clone().into()) From 9b1f15bfa11ce782e7f1cc9b1f4cd7ff7b8fa082 Mon Sep 17 00:00:00 2001 From: Francisco Aguirre Date: Fri, 18 Oct 2024 08:52:59 -0300 Subject: [PATCH 08/16] fix: used invalid character in prdoc --- prdoc/pr_6080.prdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prdoc/pr_6080.prdoc b/prdoc/pr_6080.prdoc index 8abc90f0f412..52ecd58dddde 100644 --- a/prdoc/pr_6080.prdoc +++ b/prdoc/pr_6080.prdoc @@ -1,7 +1,7 @@ # Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 # See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json -title: [Asset Hubs] Assets in pool with native can be used in query_weight_to_asset_fee +title: Assets in pool with native can be used in query_weight_to_asset_fee in Asset Hubs doc: - audience: Runtime User From 860856b1cd254ff486b12edc6cec1a90f0f9351f Mon Sep 17 00:00:00 2001 From: Francisco Aguirre Date: Mon, 21 Oct 2024 17:19:37 -0300 Subject: [PATCH 09/16] chore(assets-common): make get_assets_in_pool_with more generic --- .../runtimes/assets/asset-hub-rococo/src/lib.rs | 4 ++-- .../runtimes/assets/asset-hub-westend/src/lib.rs | 4 ++-- cumulus/parachains/runtimes/assets/common/src/lib.rs | 9 ++++++--- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 0f1d755aa5e9..cdaa4457a7b8 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -1412,7 +1412,7 @@ impl_runtime_apis! { // We accept the native token to pay fees. let mut acceptable_assets = vec![AssetId(native_token.clone())]; // We also accept all assets in a pool with the native token. - acceptable_assets.extend(assets_common::get_assets_in_pool_with::(&native_token).map(|location| AssetId(location))); + acceptable_assets.extend(assets_common::get_assets_in_pool_with::(&native_token).map(AssetId)); PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets) } @@ -1425,7 +1425,7 @@ impl_runtime_apis! { Ok(fee_in_native) }, Ok(asset_id) => { - let assets_in_pool_with_native_token: Vec<_> = assets_common::get_assets_in_pool_with::(&native_asset).collect(); + let assets_in_pool_with_native_token: Vec<_> = assets_common::get_assets_in_pool_with::(&native_asset).collect(); if assets_in_pool_with_native_token.contains(&asset_id.0) { pallet_asset_conversion::Pallet::::quote_price_tokens_for_exact_tokens( asset_id.clone().0, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index bae66327c073..be88be9efd1d 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1450,7 +1450,7 @@ impl_runtime_apis! { // We accept the native token to pay fees. let mut acceptable_assets = vec![AssetId(native_token.clone())]; // We also accept all assets in a pool with the native token. - acceptable_assets.extend(assets_common::get_assets_in_pool_with::(&native_token).map(|location| AssetId(location))); + acceptable_assets.extend(assets_common::get_assets_in_pool_with::(&native_token).map(AssetId)); PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets) } @@ -1463,7 +1463,7 @@ impl_runtime_apis! { Ok(fee_in_native) }, Ok(asset_id) => { - let assets_in_pool_with_native_token: Vec<_> = assets_common::get_assets_in_pool_with::(&native_asset).collect(); + let assets_in_pool_with_native_token: Vec<_> = assets_common::get_assets_in_pool_with::(&native_asset).collect(); if assets_in_pool_with_native_token.contains(&asset_id.0) { pallet_asset_conversion::Pallet::::quote_price_tokens_for_exact_tokens( asset_id.clone().0, diff --git a/cumulus/parachains/runtimes/assets/common/src/lib.rs b/cumulus/parachains/runtimes/assets/common/src/lib.rs index 0a04ec458bd1..6b2d7e852783 100644 --- a/cumulus/parachains/runtimes/assets/common/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/common/src/lib.rs @@ -26,6 +26,8 @@ pub mod runtime_api; extern crate alloc; use crate::matching::{LocalLocationPattern, ParentLocation}; +use codec::{Decode, EncodeLike}; +use core::cmp::PartialEq; use frame_support::traits::{Equals, EverythingBut}; use parachains_common::{AssetIdForTrustBackedAssets, CollectionId, ItemId}; use sp_runtime::traits::TryConvertInto; @@ -139,10 +141,11 @@ pub type PoolAssetsConvertedConcreteId = /// Should only be used in runtime APIs since it iterates over the whole /// `pallet_asset_conversion::Pools` map. pub fn get_assets_in_pool_with< - Runtime: pallet_asset_conversion::Config, + Runtime: pallet_asset_conversion::Config, + L: TryInto + Clone + Decode + EncodeLike + PartialEq, >( - asset: &xcm::v4::Location, -) -> impl Iterator + '_ { + asset: &L, +) -> impl Iterator + '_ { pallet_asset_conversion::Pools::::iter_keys().filter_map(move |(asset_1, asset_2)| { if asset_1 == *asset { Some(asset_2.clone().into()) From 385137b7002804d442eb5471bb9396d854e7f21e Mon Sep 17 00:00:00 2001 From: Francisco Aguirre Date: Tue, 22 Oct 2024 11:34:17 -0300 Subject: [PATCH 10/16] chore(assets-common): make get_assets_in_pool_with more generic --- .../parachains/runtimes/assets/common/src/lib.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/common/src/lib.rs b/cumulus/parachains/runtimes/assets/common/src/lib.rs index 6b2d7e852783..834fe0589cde 100644 --- a/cumulus/parachains/runtimes/assets/common/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/common/src/lib.rs @@ -139,22 +139,25 @@ pub type PoolAssetsConvertedConcreteId = /// Returns an iterator of all assets in a pool with `asset`. /// /// Should only be used in runtime APIs since it iterates over the whole -/// `pallet_asset_conversion::Pools` map. +/// `pallet_asset_conversion::Pools` map and panics if the XCM version conversion fails. +/// +/// It takes in any version of an XCM Location but always returns the latest one. +/// This is to allow some margin of migrating the pools when updating the XCM version. pub fn get_assets_in_pool_with< Runtime: pallet_asset_conversion::Config, L: TryInto + Clone + Decode + EncodeLike + PartialEq, >( asset: &L, -) -> impl Iterator + '_ { +) -> impl Iterator + '_ { pallet_asset_conversion::Pools::::iter_keys().filter_map(move |(asset_1, asset_2)| { if asset_1 == *asset { - Some(asset_2.clone().into()) + Some(asset_2.clone()) } else if asset_2 == *asset { - Some(asset_1.clone().into()) + Some(asset_1.clone()) } else { None } - }) + }).map(|location| location.try_into().map_err(|_| ()).unwrap()) } #[cfg(test)] From db4040b00a354ff49bf12f25581a46564e198326 Mon Sep 17 00:00:00 2001 From: Francisco Aguirre Date: Tue, 22 Oct 2024 12:18:16 -0300 Subject: [PATCH 11/16] chore(assets-common): return a vec instead of an iterator in get_assets_in_pool_with --- .../runtimes/assets/asset-hub-westend/src/lib.rs | 5 +++-- cumulus/parachains/runtimes/assets/common/src/lib.rs | 11 ++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index ffd4a2657487..09722dd8f850 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1450,7 +1450,8 @@ impl_runtime_apis! { // We accept the native token to pay fees. let mut acceptable_assets = vec![AssetId(native_token.clone())]; // We also accept all assets in a pool with the native token. - acceptable_assets.extend(assets_common::get_assets_in_pool_with::(&native_token).map(AssetId)); + let assets_in_pool_with_native = assets_common::get_assets_in_pool_with::(&native_token).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?.into_iter().map(AssetId); + acceptable_assets.extend(assets_in_pool_with_native); PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets) } @@ -1463,7 +1464,7 @@ impl_runtime_apis! { Ok(fee_in_native) }, Ok(asset_id) => { - let assets_in_pool_with_native_token: Vec<_> = assets_common::get_assets_in_pool_with::(&native_asset).collect(); + let assets_in_pool_with_native_token: Vec<_> = assets_common::get_assets_in_pool_with::(&native_asset).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?; if assets_in_pool_with_native_token.contains(&asset_id.0) { pallet_asset_conversion::Pallet::::quote_price_tokens_for_exact_tokens( asset_id.clone().0, diff --git a/cumulus/parachains/runtimes/assets/common/src/lib.rs b/cumulus/parachains/runtimes/assets/common/src/lib.rs index 834fe0589cde..032a957806ab 100644 --- a/cumulus/parachains/runtimes/assets/common/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/common/src/lib.rs @@ -25,6 +25,7 @@ pub mod runtime_api; extern crate alloc; +use alloc::vec::Vec; use crate::matching::{LocalLocationPattern, ParentLocation}; use codec::{Decode, EncodeLike}; use core::cmp::PartialEq; @@ -148,16 +149,16 @@ pub fn get_assets_in_pool_with< L: TryInto + Clone + Decode + EncodeLike + PartialEq, >( asset: &L, -) -> impl Iterator + '_ { - pallet_asset_conversion::Pools::::iter_keys().filter_map(move |(asset_1, asset_2)| { +) -> Result, ()> { + pallet_asset_conversion::Pools::::iter_keys().filter_map(|(asset_1, asset_2)| { if asset_1 == *asset { - Some(asset_2.clone()) + Some(asset_2) } else if asset_2 == *asset { - Some(asset_1.clone()) + Some(asset_1) } else { None } - }).map(|location| location.try_into().map_err(|_| ()).unwrap()) + }).map(|location| location.try_into().map_err(|_| ())).collect::, _>>() } #[cfg(test)] From 88d2f2d25656ea83973a288151644acd9cf0890f Mon Sep 17 00:00:00 2001 From: Francisco Aguirre Date: Tue, 22 Oct 2024 12:24:27 -0300 Subject: [PATCH 12/16] fix(asset-hub-rococo): update get_assets_in_pool_with --- .../parachains/runtimes/assets/asset-hub-rococo/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 1e4a4e3a9ec3..7b283500904a 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -1412,7 +1412,8 @@ impl_runtime_apis! { // We accept the native token to pay fees. let mut acceptable_assets = vec![AssetId(native_token.clone())]; // We also accept all assets in a pool with the native token. - acceptable_assets.extend(assets_common::get_assets_in_pool_with::(&native_token).map(AssetId)); + let assets_in_pool_with_native = assets_common::get_assets_in_pool_with::(&native_token).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?.into_iter().map(AssetId); + acceptable_assets.extend(assets_in_pool_with_native); PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets) } @@ -1425,7 +1426,7 @@ impl_runtime_apis! { Ok(fee_in_native) }, Ok(asset_id) => { - let assets_in_pool_with_native_token: Vec<_> = assets_common::get_assets_in_pool_with::(&native_asset).collect(); + let assets_in_pool_with_native_token: Vec<_> = assets_common::get_assets_in_pool_with::(&native_asset).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?; if assets_in_pool_with_native_token.contains(&asset_id.0) { pallet_asset_conversion::Pallet::::quote_price_tokens_for_exact_tokens( asset_id.clone().0, From 14eb02726688a8d5631af8430a7b1c055a8e16d0 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Tue, 22 Oct 2024 15:28:44 +0000 Subject: [PATCH 13/16] ".git/.scripts/commands/fmt/fmt.sh" --- .../runtimes/assets/common/src/lib.rs | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/common/src/lib.rs b/cumulus/parachains/runtimes/assets/common/src/lib.rs index 032a957806ab..6901515aa0f4 100644 --- a/cumulus/parachains/runtimes/assets/common/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/common/src/lib.rs @@ -25,8 +25,8 @@ pub mod runtime_api; extern crate alloc; -use alloc::vec::Vec; use crate::matching::{LocalLocationPattern, ParentLocation}; +use alloc::vec::Vec; use codec::{Decode, EncodeLike}; use core::cmp::PartialEq; use frame_support::traits::{Equals, EverythingBut}; @@ -150,15 +150,18 @@ pub fn get_assets_in_pool_with< >( asset: &L, ) -> Result, ()> { - pallet_asset_conversion::Pools::::iter_keys().filter_map(|(asset_1, asset_2)| { - if asset_1 == *asset { - Some(asset_2) - } else if asset_2 == *asset { - Some(asset_1) - } else { - None - } - }).map(|location| location.try_into().map_err(|_| ())).collect::, _>>() + pallet_asset_conversion::Pools::::iter_keys() + .filter_map(|(asset_1, asset_2)| { + if asset_1 == *asset { + Some(asset_2) + } else if asset_2 == *asset { + Some(asset_1) + } else { + None + } + }) + .map(|location| location.try_into().map_err(|_| ())) + .collect::, _>>() } #[cfg(test)] From e650905088b0915b49af362d408f2b7f05fbcbd2 Mon Sep 17 00:00:00 2001 From: Francisco Aguirre Date: Tue, 22 Oct 2024 13:14:48 -0300 Subject: [PATCH 14/16] fix: fmt --- .../runtimes/assets/asset-hub-rococo/src/lib.rs | 10 ++++++++-- .../runtimes/assets/asset-hub-westend/src/lib.rs | 13 ++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 7b283500904a..886e5c66adb2 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -1412,7 +1412,10 @@ impl_runtime_apis! { // We accept the native token to pay fees. let mut acceptable_assets = vec![AssetId(native_token.clone())]; // We also accept all assets in a pool with the native token. - let assets_in_pool_with_native = assets_common::get_assets_in_pool_with::(&native_token).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?.into_iter().map(AssetId); + let assets_in_pool_with_native = assets_common::get_assets_in_pool_with::< + Runtime, + xcm::v4::Location + >(&native_token).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?.into_iter().map(AssetId); acceptable_assets.extend(assets_in_pool_with_native); PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets) } @@ -1426,7 +1429,10 @@ impl_runtime_apis! { Ok(fee_in_native) }, Ok(asset_id) => { - let assets_in_pool_with_native_token: Vec<_> = assets_common::get_assets_in_pool_with::(&native_asset).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?; + let assets_in_pool_with_native_token: Vec<_> = assets_common::get_assets_in_pool_with::< + Runtime, + xcm::v4::Location + >(&native_asset).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?; if assets_in_pool_with_native_token.contains(&asset_id.0) { pallet_asset_conversion::Pallet::::quote_price_tokens_for_exact_tokens( asset_id.clone().0, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 09722dd8f850..0169b7ddb70c 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1450,7 +1450,10 @@ impl_runtime_apis! { // We accept the native token to pay fees. let mut acceptable_assets = vec![AssetId(native_token.clone())]; // We also accept all assets in a pool with the native token. - let assets_in_pool_with_native = assets_common::get_assets_in_pool_with::(&native_token).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?.into_iter().map(AssetId); + let assets_in_pool_with_native = assets_common::get_assets_in_pool_with::< + Runtime, + xcm::v4::Location + >(&native_token).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?.into_iter().map(AssetId); acceptable_assets.extend(assets_in_pool_with_native); PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets) } @@ -1464,8 +1467,12 @@ impl_runtime_apis! { Ok(fee_in_native) }, Ok(asset_id) => { - let assets_in_pool_with_native_token: Vec<_> = assets_common::get_assets_in_pool_with::(&native_asset).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?; - if assets_in_pool_with_native_token.contains(&asset_id.0) { + // We recognize assets in a pool with the native one. + let assets_in_pool_with_this_asset: Vec<_> = assets_common::get_assets_in_pool_with::< + Runtime, + xcm::v4::Location + >(&asset_id.0).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?; + if assets_in_pool_with_this_asset.contains(&native_asset) { pallet_asset_conversion::Pallet::::quote_price_tokens_for_exact_tokens( asset_id.clone().0, native_asset, From 82ada8a70bfa9998db09ce095f9faf84af5f3653 Mon Sep 17 00:00:00 2001 From: Francisco Aguirre Date: Tue, 22 Oct 2024 17:17:37 -0300 Subject: [PATCH 15/16] chore: get_asset_in_pool_with returns asset id instead of location --- .../runtimes/assets/asset-hub-rococo/src/lib.rs | 12 ++++++++---- .../runtimes/assets/asset-hub-westend/src/lib.rs | 8 ++++++-- cumulus/parachains/runtimes/assets/common/src/lib.rs | 9 ++++++--- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 886e5c66adb2..40b29bb5dc5d 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -1415,7 +1415,7 @@ impl_runtime_apis! { let assets_in_pool_with_native = assets_common::get_assets_in_pool_with::< Runtime, xcm::v4::Location - >(&native_token).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?.into_iter().map(AssetId); + >(&native_token).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?.into_iter(); acceptable_assets.extend(assets_in_pool_with_native); PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets) } @@ -1429,11 +1429,15 @@ impl_runtime_apis! { Ok(fee_in_native) }, Ok(asset_id) => { - let assets_in_pool_with_native_token: Vec<_> = assets_common::get_assets_in_pool_with::< + let assets_in_pool_with_this_asset: Vec<_> = assets_common::get_assets_in_pool_with::< Runtime, xcm::v4::Location - >(&native_asset).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?; - if assets_in_pool_with_native_token.contains(&asset_id.0) { + >(&asset_id.0).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?; + if assets_in_pool_with_this_asset + .into_iter() + .map(|asset_id| asset_id.0) + .find(|location| *location == native_asset) + .is_some() { pallet_asset_conversion::Pallet::::quote_price_tokens_for_exact_tokens( asset_id.clone().0, native_asset, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 0169b7ddb70c..31483b245dee 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1453,7 +1453,7 @@ impl_runtime_apis! { let assets_in_pool_with_native = assets_common::get_assets_in_pool_with::< Runtime, xcm::v4::Location - >(&native_token).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?.into_iter().map(AssetId); + >(&native_token).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?.into_iter(); acceptable_assets.extend(assets_in_pool_with_native); PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets) } @@ -1472,7 +1472,11 @@ impl_runtime_apis! { Runtime, xcm::v4::Location >(&asset_id.0).map_err(|()| XcmPaymentApiError::VersionedConversionFailed)?; - if assets_in_pool_with_this_asset.contains(&native_asset) { + if assets_in_pool_with_this_asset + .into_iter() + .map(|asset_id| asset_id.0) + .find(|location| *location == native_asset) + .is_some() { pallet_asset_conversion::Pallet::::quote_price_tokens_for_exact_tokens( asset_id.clone().0, native_asset, diff --git a/cumulus/parachains/runtimes/assets/common/src/lib.rs b/cumulus/parachains/runtimes/assets/common/src/lib.rs index 6901515aa0f4..26046e5974b5 100644 --- a/cumulus/parachains/runtimes/assets/common/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/common/src/lib.rs @@ -140,16 +140,19 @@ pub type PoolAssetsConvertedConcreteId = /// Returns an iterator of all assets in a pool with `asset`. /// /// Should only be used in runtime APIs since it iterates over the whole -/// `pallet_asset_conversion::Pools` map and panics if the XCM version conversion fails. +/// `pallet_asset_conversion::Pools` map. /// /// It takes in any version of an XCM Location but always returns the latest one. /// This is to allow some margin of migrating the pools when updating the XCM version. +/// +/// An error of type `()` is returned if the version conversion fails for XCM locations. +/// This error should be mapped by the caller to a more descriptive one. pub fn get_assets_in_pool_with< Runtime: pallet_asset_conversion::Config, L: TryInto + Clone + Decode + EncodeLike + PartialEq, >( asset: &L, -) -> Result, ()> { +) -> Result, ()> { pallet_asset_conversion::Pools::::iter_keys() .filter_map(|(asset_1, asset_2)| { if asset_1 == *asset { @@ -160,7 +163,7 @@ pub fn get_assets_in_pool_with< None } }) - .map(|location| location.try_into().map_err(|_| ())) + .map(|location| location.try_into().map_err(|_| ()).map(AssetId)) .collect::, _>>() } From 010299d0bfb43daf219b90f15baf2efc722da484 Mon Sep 17 00:00:00 2001 From: Francisco Aguirre Date: Tue, 22 Oct 2024 17:22:42 -0300 Subject: [PATCH 16/16] chore: any() instead of find().is_some() --- cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs | 3 +-- .../parachains/runtimes/assets/asset-hub-westend/src/lib.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 40b29bb5dc5d..f768f803aeaf 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -1436,8 +1436,7 @@ impl_runtime_apis! { if assets_in_pool_with_this_asset .into_iter() .map(|asset_id| asset_id.0) - .find(|location| *location == native_asset) - .is_some() { + .any(|location| location == native_asset) { pallet_asset_conversion::Pallet::::quote_price_tokens_for_exact_tokens( asset_id.clone().0, native_asset, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 31483b245dee..63234bfb6e59 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1475,8 +1475,7 @@ impl_runtime_apis! { if assets_in_pool_with_this_asset .into_iter() .map(|asset_id| asset_id.0) - .find(|location| *location == native_asset) - .is_some() { + .any(|location| location == native_asset) { pallet_asset_conversion::Pallet::::quote_price_tokens_for_exact_tokens( asset_id.clone().0, native_asset,