diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs index 7c5dc8570cab3..d349fb459678a 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs @@ -515,35 +515,86 @@ fn relay_to_para_reserve_transfer_assets(t: RelayToParaTest) -> DispatchResult { unimplemented!("Destination is not a parachain?") }; + type Runtime = ::Runtime; + let remote_fee_id: AssetId = t + .args + .assets + .clone() + .into_inner() + .get(t.args.fee_asset_item as usize) + .ok_or(pallet_xcm::Error::::Empty)? + .clone() + .id; + Dmp::make_parachain_reachable(para_id); - ::XcmPallet::limited_reserve_transfer_assets( + ::XcmPallet::transfer_assets_using_type_and_then( t.signed_origin, bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), bx!(t.args.assets.into()), - t.args.fee_asset_item, + bx!(TransferType::LocalReserve), + bx!(remote_fee_id.into()), + bx!(TransferType::LocalReserve), + bx!(VersionedXcm::from( + Xcm::<()>::builder_unsafe() + .deposit_asset(AllCounted(1), t.args.beneficiary) + .build() + )), t.args.weight_limit, ) } fn para_to_relay_reserve_transfer_assets(t: ParaToRelayTest) -> DispatchResult { - ::PolkadotXcm::limited_reserve_transfer_assets( + type Runtime = ::Runtime; + let remote_fee_id: AssetId = t + .args + .assets + .clone() + .into_inner() + .get(t.args.fee_asset_item as usize) + .ok_or(pallet_xcm::Error::::Empty)? + .clone() + .id; + + ::PolkadotXcm::transfer_assets_using_type_and_then( t.signed_origin, bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), bx!(t.args.assets.into()), - t.args.fee_asset_item, + bx!(TransferType::DestinationReserve), + bx!(remote_fee_id.into()), + bx!(TransferType::DestinationReserve), + bx!(VersionedXcm::from( + Xcm::<()>::builder_unsafe() + .deposit_asset(AllCounted(1), t.args.beneficiary) + .build() + )), t.args.weight_limit, ) } fn system_para_to_para_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult { - ::PolkadotXcm::limited_reserve_transfer_assets( + type Runtime = ::Runtime; + let remote_fee_id: AssetId = t + .args + .assets + .clone() + .into_inner() + .get(t.args.fee_asset_item as usize) + .ok_or(pallet_xcm::Error::::Empty)? + .clone() + .id; + + ::PolkadotXcm::transfer_assets_using_type_and_then( t.signed_origin, bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), bx!(t.args.assets.into()), - t.args.fee_asset_item, + bx!(TransferType::LocalReserve), + bx!(remote_fee_id.into()), + bx!(TransferType::LocalReserve), + bx!(VersionedXcm::from( + Xcm::<()>::builder_unsafe() + .deposit_asset(AllCounted(2), t.args.beneficiary) + .build() + )), t.args.weight_limit, ) } @@ -562,12 +613,29 @@ fn para_to_para_through_asset_hub_limited_reserve_transfer_assets( } fn para_to_system_para_reserve_transfer_assets(t: ParaToSystemParaTest) -> DispatchResult { - ::PolkadotXcm::limited_reserve_transfer_assets( + type Runtime = ::Runtime; + let remote_fee_id: AssetId = t + .args + .assets + .clone() + .into_inner() + .get(t.args.fee_asset_item as usize) + .ok_or(pallet_xcm::Error::::Empty)? + .clone() + .id; + + ::PolkadotXcm::transfer_assets_using_type_and_then( t.signed_origin, bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), bx!(t.args.assets.into()), - t.args.fee_asset_item, + bx!(TransferType::DestinationReserve), + bx!(remote_fee_id.into()), + bx!(TransferType::DestinationReserve), + bx!(VersionedXcm::from( + Xcm::<()>::builder_unsafe() + .deposit_asset(AllCounted(2), t.args.beneficiary) + .build() + )), t.args.weight_limit, ) } @@ -579,15 +647,34 @@ fn para_to_para_through_relay_limited_reserve_transfer_assets( unimplemented!("Destination is not a parachain?") }; + type Runtime = ::Runtime; + let remote_fee_id: AssetId = t + .args + .assets + .clone() + .into_inner() + .get(t.args.fee_asset_item as usize) + .ok_or(pallet_xcm::Error::::Empty)? + .clone() + .id; + + let relay_location = VersionedLocation::from(Location::parent()); + Rococo::ext_wrapper(|| { Dmp::make_parachain_reachable(para_id); }); - ::PolkadotXcm::limited_reserve_transfer_assets( + ::PolkadotXcm::transfer_assets_using_type_and_then( t.signed_origin, bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), bx!(t.args.assets.into()), - t.args.fee_asset_item, + bx!(TransferType::RemoteReserve(relay_location.clone())), + bx!(remote_fee_id.into()), + bx!(TransferType::RemoteReserve(relay_location)), + bx!(VersionedXcm::from( + Xcm::<()>::builder_unsafe() + .deposit_asset(AllCounted(1), t.args.beneficiary) + .build() + )), t.args.weight_limit, ) } diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs index 666ca83bf47a3..7738e36e5d728 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs @@ -526,46 +526,114 @@ fn relay_to_para_reserve_transfer_assets(t: RelayToParaTest) -> DispatchResult { unimplemented!("Destination is not a parachain?") }; + type Runtime = ::Runtime; + let remote_fee_id: AssetId = t + .args + .assets + .clone() + .into_inner() + .get(t.args.fee_asset_item as usize) + .ok_or(pallet_xcm::Error::::Empty)? + .clone() + .id; + Dmp::make_parachain_reachable(para_id); - ::XcmPallet::limited_reserve_transfer_assets( + ::XcmPallet::transfer_assets_using_type_and_then( t.signed_origin, bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), bx!(t.args.assets.into()), - t.args.fee_asset_item, + bx!(TransferType::LocalReserve), + bx!(remote_fee_id.into()), + bx!(TransferType::LocalReserve), + bx!(VersionedXcm::from( + Xcm::<()>::builder_unsafe() + .deposit_asset(AllCounted(1), t.args.beneficiary) + .build() + )), t.args.weight_limit, ) } fn para_to_relay_reserve_transfer_assets(t: ParaToRelayTest) -> DispatchResult { - ::PolkadotXcm::limited_reserve_transfer_assets( + type Runtime = ::Runtime; + let remote_fee_id: AssetId = t + .args + .assets + .clone() + .into_inner() + .get(t.args.fee_asset_item as usize) + .ok_or(pallet_xcm::Error::::Empty)? + .clone() + .id; + + ::PolkadotXcm::transfer_assets_using_type_and_then( t.signed_origin, bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), bx!(t.args.assets.into()), - t.args.fee_asset_item, + bx!(TransferType::DestinationReserve), + bx!(remote_fee_id.into()), + bx!(TransferType::DestinationReserve), + bx!(VersionedXcm::from( + Xcm::<()>::builder_unsafe() + .deposit_asset(AllCounted(1), t.args.beneficiary) + .build() + )), t.args.weight_limit, ) } fn system_para_to_para_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult { - ::PolkadotXcm::limited_reserve_transfer_assets( + type Runtime = ::Runtime; + let remote_fee_id: AssetId = t + .args + .assets + .clone() + .into_inner() + .get(t.args.fee_asset_item as usize) + .ok_or(pallet_xcm::Error::::Empty)? + .clone() + .id; + + ::PolkadotXcm::transfer_assets_using_type_and_then( t.signed_origin, bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), bx!(t.args.assets.into()), - t.args.fee_asset_item, + bx!(TransferType::LocalReserve), + bx!(remote_fee_id.into()), + bx!(TransferType::LocalReserve), + bx!(VersionedXcm::from( + Xcm::<()>::builder_unsafe() + .deposit_asset(AllCounted(2), t.args.beneficiary) + .build() + )), t.args.weight_limit, ) } fn para_to_system_para_reserve_transfer_assets(t: ParaToSystemParaTest) -> DispatchResult { - ::PolkadotXcm::limited_reserve_transfer_assets( + type Runtime = ::Runtime; + let remote_fee_id: AssetId = t + .args + .assets + .clone() + .into_inner() + .get(t.args.fee_asset_item as usize) + .ok_or(pallet_xcm::Error::::Empty)? + .clone() + .id; + + ::PolkadotXcm::transfer_assets_using_type_and_then( t.signed_origin, bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), bx!(t.args.assets.into()), - t.args.fee_asset_item, + bx!(TransferType::DestinationReserve), + bx!(remote_fee_id.into()), + bx!(TransferType::DestinationReserve), + bx!(VersionedXcm::from( + Xcm::<()>::builder_unsafe() + .deposit_asset(AllCounted(2), t.args.beneficiary) + .build() + )), t.args.weight_limit, ) } @@ -577,15 +645,34 @@ fn para_to_para_through_relay_limited_reserve_transfer_assets( unimplemented!("Destination is not a parachain?") }; + type Runtime = ::Runtime; + let remote_fee_id: AssetId = t + .args + .assets + .clone() + .into_inner() + .get(t.args.fee_asset_item as usize) + .ok_or(pallet_xcm::Error::::Empty)? + .clone() + .id; + + let relay_location = VersionedLocation::from(Location::parent()); + Westend::ext_wrapper(|| { Dmp::make_parachain_reachable(para_id); }); - ::PolkadotXcm::limited_reserve_transfer_assets( + ::PolkadotXcm::transfer_assets_using_type_and_then( t.signed_origin, bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), bx!(t.args.assets.into()), - t.args.fee_asset_item, + bx!(TransferType::RemoteReserve(relay_location.clone())), + bx!(remote_fee_id.into()), + bx!(TransferType::RemoteReserve(relay_location)), + bx!(VersionedXcm::from( + Xcm::<()>::builder_unsafe() + .deposit_asset(AllCounted(1), t.args.beneficiary) + .build() + )), t.args.weight_limit, ) } diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs index 20ba9e4801379..b07492d6a89dc 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs @@ -131,7 +131,8 @@ fn send_roc_from_asset_hub_rococo_to_asset_hub_westend() { let destination = asset_hub_westend_location(); let assets: Assets = (roc_at_asset_hub_rococo.clone(), amount).into(); let fee_idx = 0; - assert_ok!(send_assets_from_asset_hub_rococo(destination, assets, fee_idx)); + let transfer_type = TransferType::LocalReserve; + assert_ok!(send_assets_from_asset_hub_rococo(destination, assets, fee_idx, transfer_type)); }); // verify expected events on final destination @@ -210,7 +211,8 @@ fn send_back_wnds_usdt_and_weth_from_asset_hub_rococo_to_asset_hub_westend() { let destination = asset_hub_westend_location(); let assets: Assets = (wnd_at_asset_hub_rococo.clone(), amount_to_send).into(); let fee_idx = 0; - assert_ok!(send_assets_from_asset_hub_rococo(destination, assets, fee_idx)); + let transfer_type = TransferType::DestinationReserve; + assert_ok!(send_assets_from_asset_hub_rococo(destination, assets, fee_idx, transfer_type)); }); AssetHubWestend::execute_with(|| { diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/mod.rs index 890a0d4b0b97c..6e67372fb9f35 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/mod.rs @@ -173,19 +173,36 @@ pub(crate) fn send_assets_from_asset_hub_rococo( destination: Location, assets: Assets, fee_idx: u32, + // For knowing what reserve to pick. + // We only allow using the same transfer type for assets and fees right now. + // And only `LocalReserve` or `DestinationReserve`. + transfer_type: TransferType, ) -> DispatchResult { let signed_origin = ::RuntimeOrigin::signed(AssetHubRococoSender::get()); let beneficiary: Location = AccountId32Junction { network: None, id: AssetHubWestendReceiver::get().into() }.into(); + type Runtime = ::Runtime; + let remote_fee_id: AssetId = assets + .clone() + .into_inner() + .get(fee_idx as usize) + .ok_or(pallet_xcm::Error::::Empty)? + .clone() + .id; + AssetHubRococo::execute_with(|| { - ::PolkadotXcm::limited_reserve_transfer_assets( + ::PolkadotXcm::transfer_assets_using_type_and_then( signed_origin, bx!(destination.into()), - bx!(beneficiary.into()), bx!(assets.into()), - fee_idx, + bx!(transfer_type.clone()), + bx!(remote_fee_id.into()), + bx!(transfer_type), + bx!(VersionedXcm::from( + Xcm::<()>::builder_unsafe().deposit_asset(AllCounted(1), beneficiary).build() + )), WeightLimit::Unlimited, ) }) diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs index 799af03786975..64f02ef4baead 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs @@ -87,7 +87,8 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { send_assets_from_asset_hub_rococo( destination.clone(), (native_token.clone(), amount).into(), - 0 + 0, + TransferType::LocalReserve ), DispatchError::Module(sp_runtime::ModuleError { index: 31, @@ -109,6 +110,7 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { destination.clone(), (native_token.clone(), amount).into(), 0, + TransferType::LocalReserve )); // `ExportMessage` on local BridgeHub - fails - remote BridgeHub version not known @@ -127,6 +129,7 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { destination.clone(), (native_token.clone(), amount).into(), 0, + TransferType::LocalReserve )); assert_bridge_hub_rococo_message_accepted(true); assert_bridge_hub_westend_message_received(); diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/asset_transfers.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/asset_transfers.rs index fa641e13c09fa..bfc986e3981c2 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/asset_transfers.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/asset_transfers.rs @@ -157,7 +157,8 @@ fn send_wnds_usdt_and_weth_from_asset_hub_westend_to_asset_hub_rococo() { let destination = asset_hub_rococo_location(); let assets: Assets = (wnd_at_asset_hub_westend, amount).into(); let fee_idx = 0; - assert_ok!(send_assets_from_asset_hub_westend(destination, assets, fee_idx)); + let transfer_type = TransferType::LocalReserve; + assert_ok!(send_assets_from_asset_hub_westend(destination, assets, fee_idx, transfer_type)); }); // verify expected events on final destination @@ -302,7 +303,8 @@ fn send_back_rocs_from_asset_hub_westend_to_asset_hub_rococo() { let destination = asset_hub_rococo_location(); let assets: Assets = (bridged_roc_at_asset_hub_westend.clone(), amount_to_send).into(); let fee_idx = 0; - assert_ok!(send_assets_from_asset_hub_westend(destination, assets, fee_idx)); + let transfer_type = TransferType::DestinationReserve; + assert_ok!(send_assets_from_asset_hub_westend(destination, assets, fee_idx, transfer_type)); }); AssetHubRococo::execute_with(|| { diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/mod.rs index 8545984038182..332bfc0f0feb6 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/mod.rs @@ -136,19 +136,36 @@ pub(crate) fn send_assets_from_asset_hub_westend( destination: Location, assets: Assets, fee_idx: u32, + // For knowing what reserve to pick. + // We only allow using the same transfer type for assets and fees right now. + // And only `LocalReserve` or `DestinationReserve`. + transfer_type: TransferType, ) -> DispatchResult { let signed_origin = ::RuntimeOrigin::signed(AssetHubWestendSender::get().into()); let beneficiary: Location = AccountId32Junction { network: None, id: AssetHubRococoReceiver::get().into() }.into(); + type Runtime = ::Runtime; + let remote_fee_id: AssetId = assets + .clone() + .into_inner() + .get(fee_idx as usize) + .ok_or(pallet_xcm::Error::::Empty)? + .clone() + .id; + AssetHubWestend::execute_with(|| { - ::PolkadotXcm::limited_reserve_transfer_assets( + ::PolkadotXcm::transfer_assets_using_type_and_then( signed_origin, bx!(destination.into()), - bx!(beneficiary.into()), bx!(assets.into()), - fee_idx, + bx!(transfer_type.clone()), + bx!(remote_fee_id.into()), + bx!(transfer_type), + bx!(VersionedXcm::from( + Xcm::<()>::builder_unsafe().deposit_asset(AllCounted(1), beneficiary).build() + )), WeightLimit::Unlimited, ) }) diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs index 512ab4e1c6d76..7c5bb0d4adb0a 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs @@ -91,7 +91,8 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { send_assets_from_asset_hub_westend( destination.clone(), (native_token.clone(), amount).into(), - 0 + 0, + TransferType::LocalReserve ), DispatchError::Module(sp_runtime::ModuleError { index: 31, @@ -112,7 +113,8 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { assert_ok!(send_assets_from_asset_hub_westend( destination.clone(), (native_token.clone(), amount).into(), - 0 + 0, + TransferType::LocalReserve )); // `ExportMessage` on local BridgeHub - fails - remote BridgeHub version not known @@ -130,7 +132,8 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { assert_ok!(send_assets_from_asset_hub_westend( destination.clone(), (native_token.clone(), amount).into(), - 0 + 0, + TransferType::LocalReserve )); assert_bridge_hub_westend_message_accepted(true); assert_bridge_hub_rococo_message_received(); diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs index 09920ed00f2cd..994b4566569ac 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs @@ -873,17 +873,23 @@ fn transfer_relay_token() { [GlobalConsensus(Ethereum { chain_id: SEPOLIA_ID })], )); - let beneficiary = VersionedLocation::from(Location::new( + let beneficiary = Location::new( 0, [AccountKey20 { network: None, key: ETHEREUM_DESTINATION_ADDRESS.into() }], - )); + ); - assert_ok!(::PolkadotXcm::limited_reserve_transfer_assets( + assert_ok!(::PolkadotXcm::transfer_assets_using_type_and_then( RuntimeOrigin::signed(AssetHubWestendSender::get()), Box::new(destination), - Box::new(beneficiary), Box::new(versioned_assets), - 0, + Box::new(TransferType::LocalReserve), + Box::new(VersionedAssetId::from(AssetId(Location::parent()))), + Box::new(TransferType::LocalReserve), + Box::new(VersionedXcm::from( + Xcm::<()>::builder_unsafe() + .deposit_asset(AllCounted(1), beneficiary) + .build() + )), Unlimited, )); @@ -2229,17 +2235,23 @@ fn register_pna_in_v5_while_transfer_in_v4_should_work() { [GlobalConsensus(Ethereum { chain_id: SEPOLIA_ID })], )); - let beneficiary = VersionedLocation::V4(Location::new( + let beneficiary = Location::new( 0, [AccountKey20 { network: None, key: ETHEREUM_DESTINATION_ADDRESS.into() }], - )); + ); - assert_ok!(::PolkadotXcm::limited_reserve_transfer_assets( + assert_ok!(::PolkadotXcm::transfer_assets_using_type_and_then( RuntimeOrigin::signed(AssetHubWestendSender::get()), Box::new(destination), - Box::new(beneficiary), Box::new(versioned_assets), - 0, + Box::new(TransferType::LocalReserve), + Box::new(VersionedAssetId::V4(AssetId(Location::parent()))), + Box::new(TransferType::LocalReserve), + Box::new(VersionedXcm::V4( + Xcm::<()>::builder_unsafe() + .deposit_asset(WildAsset::AllCounted(1), beneficiary) + .build() + )), Unlimited, )); 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 abb842085d437..209f11d8173a5 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -101,7 +101,7 @@ use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; #[cfg(feature = "runtime-benchmarks")] use xcm::latest::prelude::{ Asset, Assets as XcmAssets, Fungible, Here, InteriorLocation, Junction, Junction::*, Location, - NetworkId, NonFungible, Parent, ParentThen, Response, WeightLimit, XCM_VERSION, + NetworkId, NonFungible, ParentThen, Response, WeightLimit, XCM_VERSION, }; use xcm::{ latest::prelude::{AssetId, BodyId}, @@ -1750,12 +1750,27 @@ impl_runtime_apis! { } fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> { + // We get an account to create USDT and give it enough WND to exist. + let account = frame_benchmarking::whitelisted_caller(); + assert_ok!(>::mint_into( + &account, + ExistentialDeposit::get() + (1_000 * UNITS) + )); + + // We then create USDT. + let usdt_id = 1984u32; + let usdt_location = Location::new(0, [PalletInstance(50), GeneralIndex(usdt_id.into())]); + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + usdt_id.into(), + account.clone().into(), + true, + 1 + )); + + // And return USDT as the reserve transferable asset. Some(( - Asset { - fun: Fungible(ExistentialDeposit::get()), - id: AssetId(Parent.into()) - }, - // AH can reserve transfer native token to some random parachain. + Asset { fun: Fungible(ExistentialDeposit::get()), id: AssetId(usdt_location) }, ParentThen(Parachain(RandomParaId::get().into()).into()).into(), )) } 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 f0ef5432aeda7..13fb11e8cf61d 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -123,7 +123,7 @@ use frame_support::traits::PalletInfoAccess; #[cfg(feature = "runtime-benchmarks")] use xcm::latest::prelude::{ Asset, Assets as XcmAssets, Fungible, Here, InteriorLocation, Junction, Junction::*, Location, - NetworkId, NonFungible, Parent, ParentThen, Response, WeightLimit, XCM_VERSION, + NetworkId, NonFungible, ParentThen, Response, WeightLimit, XCM_VERSION, }; use xcm_runtime_apis::{ @@ -2238,8 +2238,27 @@ pallet_revive::impl_runtime_apis_plus_revive!( } fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> { + // We get an account to create USDT and give it enough WND to exist. + let account = frame_benchmarking::whitelisted_caller(); + assert_ok!(>::mint_into( + &account, + ExistentialDeposit::get() + (1_000 * UNITS) + )); + + // We then create USDT. + let usdt_id = 1984u32; + let usdt_location = Location::new(0, [PalletInstance(50), GeneralIndex(usdt_id.into())]); + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + usdt_id.into(), + account.clone().into(), + true, + 1 + )); + + // And return USDT as the reserve transferable asset. Some(( - Asset { fun: Fungible(ExistentialDeposit::get()), id: AssetId(Parent.into()) }, + Asset { fun: Fungible(ExistentialDeposit::get()), id: AssetId(usdt_location) }, ParentThen(Parachain(RandomParaId::get().into()).into()).into(), )) } diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index d0b073b7118fc..e6a0aea3605e3 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -38,8 +38,11 @@ use sp_runtime::{ traits::{Block as BlockT, MaybeEquivalence, StaticLookup, Zero}, DispatchError, SaturatedConversion, Saturating, }; -use xcm::{latest::prelude::*, VersionedAssets}; -use xcm_executor::{traits::ConvertLocation, XcmExecutor}; +use xcm::{latest::prelude::*, VersionedAssetId, VersionedAssets, VersionedXcm}; +use xcm_executor::{ + traits::{ConvertLocation, TransferType}, + XcmExecutor, +}; use xcm_runtime_apis::fees::{ runtime_decl_for_xcm_payment_api::XcmPaymentApiV1, Error as XcmPaymentApiError, }; @@ -1551,12 +1554,18 @@ pub fn reserve_transfer_native_asset_to_non_teleport_para_works< Asset { fun: Fungible(balance_to_transfer.into()), id: AssetId(native_asset) }; // pallet_xcm call reserve transfer - assert_ok!(>::limited_reserve_transfer_assets( + assert_ok!(>::transfer_assets_using_type_and_then( RuntimeHelper::::origin_of(alice_account.clone()), Box::new(dest.clone().into_versioned()), - Box::new(dest_beneficiary.clone().into_versioned()), Box::new(VersionedAssets::from(Assets::from(asset_to_transfer))), - 0, + Box::new(TransferType::LocalReserve), + Box::new(VersionedAssetId::from(AssetId(Location::parent()))), + Box::new(TransferType::LocalReserve), + Box::new(VersionedXcm::from( + Xcm::<()>::builder_unsafe() + .deposit_asset(AllCounted(1), dest_beneficiary.clone()) + .build() + )), weight_limit, )); diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs index 9b05f2d46dfb5..6c6549390a293 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs @@ -30,9 +30,12 @@ use parachains_runtimes_test_utils::{ SlotDurations, ValidatorIdOf, XcmReceivedFrom, }; use sp_runtime::{traits::StaticLookup, Saturating}; -use xcm::{latest::prelude::*, VersionedAssets}; +use xcm::{latest::prelude::*, VersionedAssetId, VersionedAssets, VersionedXcm}; use xcm_builder::{CreateMatcher, MatchXcm}; -use xcm_executor::{traits::ConvertLocation, XcmExecutor}; +use xcm_executor::{ + traits::{ConvertLocation, TransferType}, + XcmExecutor, +}; pub struct TestBridgingConfig { pub bridged_network: NetworkId, @@ -186,13 +189,19 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< let expected_beneficiary = target_destination_account.clone(); - // do pallet_xcm call reserve transfer - assert_ok!(>::limited_reserve_transfer_assets( + // do cross-chain transfer + assert_ok!(>::transfer_assets_using_type_and_then( RuntimeHelper::::origin_of(alice_account.clone()), Box::new(target_location_from_different_consensus.clone().into_versioned()), - Box::new(target_destination_account.into_versioned()), Box::new(VersionedAssets::from(assets_to_transfer)), - 0, + Box::new(TransferType::LocalReserve), + Box::new(VersionedAssetId::from(AssetId(Location::parent()))), + Box::new(TransferType::LocalReserve), + Box::new(VersionedXcm::from( + Xcm::<()>::builder_unsafe() + .deposit_asset(AllCounted(1), target_destination_account) + .build() + )), weight_limit, )); diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 78e943f0c179a..7f5a615444763 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -2562,14 +2562,7 @@ sp_api::impl_runtime_apis! { } fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> { - // Relay can reserve transfer native token to some random parachain. - Some(( - Asset { - fun: Fungible(ExistentialDeposit::get()), - id: AssetId(Here.into()) - }, - Parachain(RandomParaId::get().into()).into(), - )) + None } fn set_up_complex_asset_transfer( diff --git a/polkadot/runtime/rococo/src/weights/pallet_xcm.rs b/polkadot/runtime/rococo/src/weights/pallet_xcm.rs index bccc5e5a38a24..aa1c33611b91c 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_xcm.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_xcm.rs @@ -95,29 +95,15 @@ impl pallet_xcm::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `XcmPallet::ShouldRecordXcm` (r:1 w:0) - /// Proof: `XcmPallet::ShouldRecordXcm` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) - /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) - /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::Heads` (r:1 w:0) - /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) fn reserve_transfer_assets() -> Weight { // Proof Size summary in bytes: - // Measured: `297` - // Estimated: `3762` - // Minimum execution time: 137_851_000 picoseconds. - Weight::from_parts(141_308_000, 0) - .saturating_add(Weight::from_parts(0, 3762)) - .saturating_add(T::DbWeight::get().reads(7)) - .saturating_add(T::DbWeight::get().writes(3)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 2724d102da2e2..7b1b9031762b4 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -2916,14 +2916,7 @@ sp_api::impl_runtime_apis! { } fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> { - // Relay can reserve transfer native token to some random parachain. - Some(( - Asset { - fun: Fungible(ExistentialDeposit::get()), - id: AssetId(Here.into()) - }, - crate::Junction::Parachain(RandomParaId::get().into()).into(), - )) + None } fn set_up_complex_asset_transfer( diff --git a/polkadot/runtime/westend/src/weights/pallet_xcm.rs b/polkadot/runtime/westend/src/weights/pallet_xcm.rs index 0a6fcf8da9630..5e2b2eb4885a9 100644 --- a/polkadot/runtime/westend/src/weights/pallet_xcm.rs +++ b/polkadot/runtime/westend/src/weights/pallet_xcm.rs @@ -95,29 +95,15 @@ impl pallet_xcm::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: `XcmPallet::ShouldRecordXcm` (r:1 w:0) - /// Proof: `XcmPallet::ShouldRecordXcm` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) - /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) - /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::Heads` (r:1 w:0) - /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) fn reserve_transfer_assets() -> Weight { // Proof Size summary in bytes: - // Measured: `367` - // Estimated: `6196` - // Minimum execution time: 145_601_000 picoseconds. - Weight::from_parts(153_228_000, 0) - .saturating_add(Weight::from_parts(0, 6196)) - .saturating_add(T::DbWeight::get().reads(8)) - .saturating_add(T::DbWeight::get().writes(4)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `System::Account` (r:2 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) diff --git a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/tests.rs b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/tests.rs index 93a112689c42a..0010e982cb7dc 100644 --- a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/tests.rs +++ b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/tests.rs @@ -18,7 +18,7 @@ use frame::testing_prelude::*; use test_log::test; use xcm::prelude::*; -use xcm_executor::traits::ConvertLocation; +use xcm_executor::traits::{ConvertLocation, TransferType}; use xcm_simulator::TestExt; use super::{ @@ -64,12 +64,16 @@ fn reserve_asset_transfers_work() { // If we don't specify anything, it will be a `u64`, which the conversion // will turn into a non-fungible token instead of a fungible one. let assets: Assets = (Here, 50u128 * CENTS as u128).into(); - assert_ok!(relay_chain::XcmPallet::limited_reserve_transfer_assets( + assert_ok!(relay_chain::XcmPallet::transfer_assets_using_type_and_then( relay_chain::RuntimeOrigin::signed(ALICE), Box::new(VersionedLocation::from(destination.clone())), - Box::new(VersionedLocation::from(beneficiary)), Box::new(VersionedAssets::from(assets)), - 0, + Box::new(TransferType::LocalReserve), + Box::new(VersionedAssetId::from(AssetId(Location::here()))), + Box::new(TransferType::LocalReserve), + Box::new(VersionedXcm::from( + Xcm::<()>::builder_unsafe().deposit_asset(AllCounted(1), beneficiary).build() + )), WeightLimit::Unlimited, )); @@ -100,12 +104,16 @@ fn reserve_asset_transfers_work() { // This chain doesn't have a token of its own, so we always refer to this token, // and we do so by the Location of the Relay Chain. let assets: Assets = (Parent, 25u128 * CENTS as u128).into(); - assert_ok!(parachain::XcmPallet::limited_reserve_transfer_assets( + assert_ok!(parachain::XcmPallet::transfer_assets_using_type_and_then( parachain::RuntimeOrigin::signed(BOB), Box::new(VersionedLocation::from(destination)), - Box::new(VersionedLocation::from(beneficiary)), Box::new(VersionedAssets::from(assets)), - 0, + Box::new(TransferType::DestinationReserve), + Box::new(VersionedAssetId::from(AssetId(Location::parent()))), + Box::new(TransferType::DestinationReserve), + Box::new(VersionedXcm::from( + Xcm::<()>::builder_unsafe().deposit_asset(AllCounted(1), beneficiary).build() + )), WeightLimit::Unlimited, )); diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 1ed4953151dd5..3881356ae40f0 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -2091,6 +2091,16 @@ impl Pallet { // Ensure all assets (including fees) have same reserve location. ensure!(assets_transfer_type == fees_transfer_type, Error::::TooManyReserves); + // We check for network native asset reserve transfers in preparation for the Asset Hub + // Migration. This check will be removed after the migration and the determined + // reserve location adjusted accordingly. For more information, see https://github.com/paritytech/polkadot-sdk/issues/9054. + Self::ensure_network_asset_reserve_transfer_allowed( + &assets, + fee_asset_item, + &assets_transfer_type, + &fees_transfer_type, + )?; + let (local_xcm, remote_xcm) = Self::build_xcm_transfer_type( origin.clone(), dest.clone(), diff --git a/polkadot/xcm/pallet-xcm/src/transfer_assets_validation.rs b/polkadot/xcm/pallet-xcm/src/transfer_assets_validation.rs index 75aa91508a539..2be7fffc5965d 100644 --- a/polkadot/xcm/pallet-xcm/src/transfer_assets_validation.rs +++ b/polkadot/xcm/pallet-xcm/src/transfer_assets_validation.rs @@ -94,7 +94,7 @@ impl Pallet { tracing::debug!( target: "xcm::pallet_xcm::transfer_assets", asset_id = ?asset.id, ?transfer_type, - "Network native asset reserve transfer blocked during Asset Hub Migration. Use `limited_reserve_transfer_assets` instead." + "Network native asset reserve transfer blocked in preparation for the Asset Hub Migration. Use `transfer_assets_using_type_and_then` instead and explicitly mention the reserve." ); // It's error-prone to try to determine the reserve in this circumstances. return Err(Error::::InvalidAssetUnknownReserve); diff --git a/prdoc/pr_9544.prdoc b/prdoc/pr_9544.prdoc new file mode 100644 index 0000000000000..8aeda780d3c74 --- /dev/null +++ b/prdoc/pr_9544.prdoc @@ -0,0 +1,35 @@ +# 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: Disable reserve_transfer_assets for DOT|KSM|WND|PAS + +doc: + - audience: Runtime Dev + description: | + The reserve_transfer_assets extrinsic on pallet-xcm is also affected by the same issue as transfer_assets. + These extrinsics have been updated to return an error when dealing with DOT|KSM|WND|PAS, effectively disabling them. + We can't afford these extrinsics to be enabled after the Asset Hub Migration (AHM) and risk trapping assets due + to chain misconfigurations. + All chains need to update and coordinate with their dapps to move to the alternatives, like `transfer_assets_using_type_and_then` + or `execute`. + - audience: Runtime User + description: | + The reserve_transfer_assets extrinsic on pallet-xcm is also affected by the same issue as transfer_assets. + These extrinsics have been updated to return an error when dealing with DOT|KSM|WND|PAS, effectively disabling them. + We can't afford these extrinsics to be enabled after the Asset Hub Migration (AHM) and risk trapping assets due + to chain misconfigurations. + All apps should switch to `transfer_assets_using_type_and_then` or `execute`. + +crates: +- name: pallet-xcm + bump: patch +- name: asset-test-utils + bump: patch +- name: westend-runtime + bump: patch +- name: rococo-runtime + bump: patch +- name: asset-hub-rococo-runtime + bump: patch +- name: asset-hub-westend-runtime + bump: patch