diff --git a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs index 84f76333ab66b..a1bb8534a24eb 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs @@ -827,6 +827,17 @@ macro_rules! test_cross_chain_alias { #[macro_export] macro_rules! create_pool_with_native_on { ( $chain:ident, $asset:expr, $is_foreign:expr, $asset_owner:expr ) => { + $crate::create_pool_with_native_on!( + $chain, + $asset, + $is_foreign, + $asset_owner, + 1_000_000_000_000, + 2_000_000_000_000 + ); + }; + + ( $chain:ident, $asset:expr, $is_foreign:expr, $asset_owner:expr, $native_amount:expr, $asset_amount:expr ) => { emulated_integration_tests_common::impls::paste::paste! { <$chain>::execute_with(|| { type RuntimeEvent = <$chain as Chain>::RuntimeEvent; @@ -871,8 +882,8 @@ macro_rules! create_pool_with_native_on { signed_owner, Box::new(native_asset), Box::new($asset), - 1_000_000_000_000, - 2_000_000_000_000, // $asset is worth half of native_asset + $native_amount, + $asset_amount, 0, 0, owner.into() diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs index 75714acb07cd9..0c425a7650716 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs @@ -23,3 +23,80 @@ mod swap; mod teleport; mod treasury; mod xcm_fee_estimation; + +#[macro_export] +macro_rules! create_pool_with_roc_on { + // default amounts + ( $chain:ident, $asset_id:expr, $is_foreign:expr, $asset_owner:expr ) => { + $crate::create_pool_with_roc_on!( + $chain, + $asset_id, + $is_foreign, + $asset_owner, + 1_000_000_000_000, + 2_000_000_000_000 + ); + }; + + // custom amounts + ( $chain:ident, $asset_id:expr, $is_foreign:expr, $asset_owner:expr, $roc_amount:expr, $asset_amount:expr ) => { + emulated_integration_tests_common::impls::paste::paste! { + <$chain>::execute_with(|| { + type RuntimeEvent = <$chain as Chain>::RuntimeEvent; + let owner = $asset_owner; + let signed_owner = <$chain as Chain>::RuntimeOrigin::signed(owner.clone()); + let roc_location: Location = Parent.into(); + if $is_foreign { + assert_ok!(<$chain as [<$chain Pallet>]>::ForeignAssets::mint( + signed_owner.clone(), + $asset_id.clone().into(), + owner.clone().into(), + 10_000_000_000_000, // For it to have more than enough. + )); + } else { + let asset_id = match $asset_id.interior.last() { + Some(GeneralIndex(id)) => *id as u32, + _ => unreachable!(), + }; + assert_ok!(<$chain as [<$chain Pallet>]>::Assets::mint( + signed_owner.clone(), + asset_id.into(), + owner.clone().into(), + 10_000_000_000_000, // For it to have more than enough. + )); + } + + assert_ok!(<$chain as [<$chain Pallet>]>::AssetConversion::create_pool( + signed_owner.clone(), + Box::new(roc_location.clone()), + Box::new($asset_id.clone()), + )); + + assert_expected_events!( + $chain, + vec![ + RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::PoolCreated { .. }) => {}, + ] + ); + + assert_ok!(<$chain as [<$chain Pallet>]>::AssetConversion::add_liquidity( + signed_owner, + Box::new(roc_location), + Box::new($asset_id), + $roc_amount, + $asset_amount, + 0, + 0, + owner.into() + )); + + assert_expected_events!( + $chain, + vec![ + RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::LiquidityAdded { .. }) => {}, + ] + ); + }); + } + }; +} diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/send.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/send.rs index ea8f6c1defba4..663615b187ca4 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/send.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/send.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::imports::*; +use crate::{create_pool_with_roc_on, imports::*}; /// Relay Chain should be able to execute `Transact` instructions in System Parachain /// when `OriginKind::Superuser`. @@ -139,6 +139,8 @@ fn send_xcm_from_para_to_asset_hub_paying_fee_with_sufficient_asset() { let fee_amount = ASSET_MIN_BALANCE * 1000000; let asset = ([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], fee_amount).into(); + let asset_location = + Location::new(0, [PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())]); let root_origin = ::RuntimeOrigin::root(); let system_para_destination = PenpalA::sibling_location_of(AssetHubRococo::para_id()).into(); @@ -150,6 +152,15 @@ fn send_xcm_from_para_to_asset_hub_paying_fee_with_sufficient_asset() { ASSET_HUB_ROCOCO_ED * 10000000000, )]); + create_pool_with_roc_on!( + AssetHubRococo, + asset_location, + false, + para_sovereign_account.clone(), + 9_000_000_000_000_000, + 9_000_000_000_000 + ); + PenpalA::execute_with(|| { assert_ok!(::PolkadotXcm::send( root_origin, diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs index 40f24add03065..f46dc66d24129 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs @@ -43,7 +43,20 @@ macro_rules! foreign_balance_on { #[macro_export] macro_rules! create_pool_with_wnd_on { + // default amounts ( $chain:ident, $asset_id:expr, $is_foreign:expr, $asset_owner:expr ) => { + $crate::create_pool_with_wnd_on!( + $chain, + $asset_id, + $is_foreign, + $asset_owner, + 1_000_000_000_000, + 2_000_000_000_000 + ); + }; + + // custom amounts + ( $chain:ident, $asset_id:expr, $is_foreign:expr, $asset_owner:expr, $wnd_amount:expr, $asset_amount:expr ) => { emulated_integration_tests_common::impls::paste::paste! { <$chain>::execute_with(|| { type RuntimeEvent = <$chain as Chain>::RuntimeEvent; @@ -87,8 +100,8 @@ macro_rules! create_pool_with_wnd_on { signed_owner, Box::new(wnd_location), Box::new($asset_id), - 1_000_000_000_000, - 2_000_000_000_000, // $asset_id is worth half of wnd + $wnd_amount, + $asset_amount, 0, 0, owner.into() diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/send.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/send.rs index d4f239df48774..0dd3177dff4c5 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/send.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/send.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::imports::*; +use crate::{create_pool_with_wnd_on, imports::*}; /// Relay Chain should be able to execute `Transact` instructions in System Parachain /// when `OriginKind::Superuser`. @@ -139,6 +139,8 @@ fn send_xcm_from_para_to_asset_hub_paying_fee_with_sufficient_asset() { let fee_amount = ASSET_MIN_BALANCE * 1000000; let asset = ([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], fee_amount).into(); + let asset_location = + Location::new(0, [PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())]); let root_origin = ::RuntimeOrigin::root(); let system_para_destination = PenpalA::sibling_location_of(AssetHubWestend::para_id()).into(); @@ -150,6 +152,15 @@ fn send_xcm_from_para_to_asset_hub_paying_fee_with_sufficient_asset() { ASSET_HUB_WESTEND_ED * 10000000000, )]); + create_pool_with_wnd_on!( + AssetHubWestend, + asset_location, + false, + para_sovereign_account.clone(), + 9_000_000_000_000_000, + 9_000_000_000_000 + ); + PenpalA::execute_with(|| { assert_ok!(::PolkadotXcm::send( root_origin, diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/transact.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/transact.rs index abaa557b0f5b4..ad886dbe5e24d 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/transact.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/transact.rs @@ -113,7 +113,14 @@ fn transact_from_para_to_para_through_asset_hub() { // We create a pool between WND and USDT in AssetHub. let usdt = Location::new(0, [PalletInstance(ASSETS_PALLET_ID), GeneralIndex(USDT_ID.into())]); - create_pool_with_wnd_on!(AssetHubWestend, usdt, false, AssetHubWestendSender::get()); + create_pool_with_wnd_on!( + AssetHubWestend, + usdt, + false, + AssetHubWestendSender::get(), + 1_000_000_000_000, + 20_000_000_000 + ); // We also need a pool between WND and USDT on PenpalA. create_pool_with_wnd_on!(PenpalA, PenpalUsdtFromAssetHub::get(), true, PenpalAssetOwner::get()); // We also need a pool between WND and USDT on PenpalB. 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 f058803f16f7e..20ba9e4801379 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 @@ -363,6 +363,7 @@ fn send_rocs_from_penpal_rococo_through_asset_hub_rococo_to_asset_hub_westend() let local_asset_hub = PenpalA::sibling_location_of(AssetHubRococo::para_id()); let (roc_at_rococo_parachains, roc_at_asset_hub_westend) = set_up_rocs_for_penpal_rococo_through_ahr_to_ahw(&sender, amount); + set_up_pool_with_wnd_on_ah_westend(roc_at_asset_hub_westend.clone(), true); let sov_ahw_on_ahr = AssetHubRococo::sovereign_account_of_parachain_on_other_global_consensus( ByGenesis(WESTEND_GENESIS_HASH), diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge_common.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge_common.rs index d9c65ae26a146..a397f7beeb3f2 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge_common.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge_common.rs @@ -322,8 +322,22 @@ pub fn create_pools_on_ah() { let ethereum_sovereign = snowbridge_sovereign(); AssetHubWestend::fund_accounts(vec![(ethereum_sovereign.clone(), INITIAL_FUND)]); PenpalB::fund_accounts(vec![(ethereum_sovereign.clone(), INITIAL_FUND)]); - create_pool_with_native_on!(AssetHubWestend, weth_location(), true, ethereum_sovereign.clone()); - create_pool_with_native_on!(AssetHubWestend, ethereum(), true, ethereum_sovereign.clone()); + create_pool_with_native_on!( + AssetHubWestend, + weth_location(), + true, + ethereum_sovereign.clone(), + 1_000_000_000_000, + 20_000_000_000 + ); + create_pool_with_native_on!( + AssetHubWestend, + ethereum(), + true, + ethereum_sovereign.clone(), + 1_000_000_000_000, + 20_000_000_000 + ); } pub(crate) fn set_up_eth_and_dot_pool() { diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge_v2_inbound.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge_v2_inbound.rs index 1009a23b22744..0aae34c0a5c7c 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge_v2_inbound.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge_v2_inbound.rs @@ -161,6 +161,7 @@ fn send_token_v2() { NativeTokenERC20 { token_id: token.into(), value: token_transfer_value }, ]; + set_up_eth_and_dot_pool(); let topic_id = BridgeHubWestend::execute_with(|| { type RuntimeEvent = ::RuntimeEvent; let instructions = vec![ @@ -280,6 +281,7 @@ fn send_weth_v2() { NativeTokenERC20 { token_id: WETH.into(), value: token_transfer_value }, ]; + set_up_eth_and_dot_pool(); BridgeHubWestend::execute_with(|| { type RuntimeEvent = ::RuntimeEvent; let instructions = vec![ @@ -769,6 +771,7 @@ fn send_foreign_erc20_token_back_to_polkadot() { .appended_with(asset_id.clone().interior) .unwrap(); + set_up_eth_and_dot_pool(); // Register token BridgeHubWestend::execute_with(|| { type RuntimeOrigin = ::RuntimeOrigin; @@ -963,6 +966,7 @@ fn invalid_claimer_does_not_fail_the_message() { let origin = H160::random(); + set_up_eth_and_dot_pool(); BridgeHubWestend::execute_with(|| { type RuntimeEvent = ::RuntimeEvent; let instructions = vec![ diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/transact.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/transact.rs index 96937a95a99b5..26c45a5e723e1 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/transact.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/transact.rs @@ -138,9 +138,23 @@ fn transact_from_ethereum_to_penpalb_through_asset_hub() { // We create a pool between WND and WETH in AssetHub to support paying for fees with WETH. let snowbridge_sovereign = snowbridge_sovereign(); - create_pool_with_native_on!(AssetHubWestend, bridged_weth.clone(), true, snowbridge_sovereign); + create_pool_with_native_on!( + AssetHubWestend, + bridged_weth.clone(), + true, + snowbridge_sovereign, + 1_000_000_000_000, + 20_000_000_000 + ); // We also need a pool between WND and WETH on PenpalB to support paying for fees with WETH. - create_pool_with_native_on!(PenpalB, bridged_weth.clone(), true, PenpalAssetOwner::get()); + create_pool_with_native_on!( + PenpalB, + bridged_weth.clone(), + true, + PenpalAssetOwner::get(), + 1_000_000_000_000, + 20_000_000_000 + ); // Init values for Parachain Destination let receiver = PenpalBReceiver::get(); diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index de87fd2b19a30..839e58ca9d5fa 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -14,11 +14,10 @@ // limitations under the License. use super::{ - AccountId, AllPalletsWithSystem, Assets, Authorship, Balance, Balances, BaseDeliveryFee, - CollatorSelection, FeeAssetId, ForeignAssets, ForeignAssetsInstance, ParachainInfo, - ParachainSystem, PolkadotXcm, PoolAssets, Runtime, RuntimeCall, RuntimeEvent, - RuntimeHoldReason, RuntimeOrigin, ToWestendXcmRouter, TransactionByteFee, - TrustBackedAssetsInstance, Uniques, WeightToFee, XcmpQueue, + AccountId, AllPalletsWithSystem, Assets, Balance, Balances, BaseDeliveryFee, CollatorSelection, + FeeAssetId, ForeignAssets, ParachainInfo, ParachainSystem, PolkadotXcm, PoolAssets, Runtime, + RuntimeCall, RuntimeEvent, RuntimeHoldReason, RuntimeOrigin, ToWestendXcmRouter, + TransactionByteFee, Uniques, WeightToFee, XcmpQueue, }; use assets_common::{ matching::{FromNetwork, FromSiblingParachain, IsForeignConcreteAsset, ParentLocation}, @@ -36,14 +35,14 @@ use frame_system::EnsureRoot; use pallet_xcm::{AuthorizedAliasers, XcmPassthrough}; use parachains_common::{ xcm_config::{ - AllSiblingSystemParachains, AssetFeeAsExistentialDepositMultiplier, - ConcreteAssetFromSystem, ParentRelayOrSiblingParachains, RelayOrOtherSystemParachains, + AllSiblingSystemParachains, ConcreteAssetFromSystem, ParentRelayOrSiblingParachains, + RelayOrOtherSystemParachains, }, TREASURY_PALLET_ID, }; use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::xcm_sender::ExponentialPrice; -use sp_runtime::traits::{AccountIdConversion, ConvertInto, TryConvertInto}; +use sp_runtime::traits::{AccountIdConversion, TryConvertInto}; use testnet_parachains_constants::rococo::snowbridge::{ EthereumNetwork, INBOUND_QUEUE_PALLET_INDEX, }; @@ -252,7 +251,6 @@ pub type XcmOriginToTransactDispatchOrigin = ( parameter_types! { pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; - pub XcmAssetFeesReceiver: Option = Authorship::author(); } pub struct ParentOrParentsPlurality; @@ -294,23 +292,6 @@ pub type Barrier = TrailingSetTopicAsId< >, >; -/// Multiplier used for dedicated `TakeFirstAssetTrader` with `Assets` instance. -pub type AssetFeeAsExistentialDepositMultiplierFeeCharger = AssetFeeAsExistentialDepositMultiplier< - Runtime, - WeightToFee, - pallet_assets::BalanceToAssetBalance, - TrustBackedAssetsInstance, ->; - -/// Multiplier used for dedicated `TakeFirstAssetTrader` with `ForeignAssets` instance. -pub type ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger = - AssetFeeAsExistentialDepositMultiplier< - Runtime, - WeightToFee, - pallet_assets::BalanceToAssetBalance, - ForeignAssetsInstance, - >; - /// Locations that will not be charged fees in the executor, /// either execution or delivery. /// We only waive fees for system functions, which these locations represent. @@ -405,32 +386,6 @@ impl xcm_executor::Config for XcmConfig { ResolveAssetTo, AccountId, >, - // This trader allows to pay with `is_sufficient=true` "Trust Backed" assets from dedicated - // `pallet_assets` instance - `Assets`. - cumulus_primitives_utility::TakeFirstAssetTrader< - AccountId, - AssetFeeAsExistentialDepositMultiplierFeeCharger, - TrustBackedAssetsConvertedConcreteId, - Assets, - cumulus_primitives_utility::XcmFeesTo32ByteAccount< - FungiblesTransactor, - AccountId, - XcmAssetFeesReceiver, - >, - >, - // This trader allows to pay with `is_sufficient=true` "Foreign" assets from dedicated - // `pallet_assets` instance - `ForeignAssets`. - cumulus_primitives_utility::TakeFirstAssetTrader< - AccountId, - ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, - ForeignAssetsConvertedConcreteId, - ForeignAssets, - cumulus_primitives_utility::XcmFeesTo32ByteAccount< - ForeignFungiblesTransactor, - AccountId, - XcmAssetFeesReceiver, - >, - >, ); type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs index 934cf71e009b6..ffdecbc2dd47c 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs @@ -20,9 +20,8 @@ use asset_hub_rococo_runtime::{ xcm_config, xcm_config::{ - bridging, AssetFeeAsExistentialDepositMultiplierFeeCharger, CheckingAccount, - ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, GovernanceLocation, - LocationToAccountId, StakingPot, TokenLocation, TrustBackedAssetsPalletLocation, XcmConfig, + bridging, CheckingAccount, GovernanceLocation, LocationToAccountId, StakingPot, + TokenLocation, TrustBackedAssetsPalletLocation, XcmConfig, }, AllPalletsWithoutSystem, AssetConversion, AssetDeposit, Assets, Balances, Block, CollatorSelection, ExistentialDeposit, ForeignAssets, ForeignAssetsInstance, @@ -36,7 +35,6 @@ use asset_test_utils::{ }; use codec::{Decode, Encode}; use core::ops::Mul; -use cumulus_primitives_utility::ChargeWeightInFungibles; use frame_support::{ assert_noop, assert_ok, parameter_types, traits::{ @@ -402,241 +400,6 @@ fn test_buy_and_refund_weight_with_swap_foreign_asset_xcm_trader() { }) } -#[test] -fn test_asset_xcm_take_first_trader() { - ExtBuilder::::default() - .with_collators(vec![AccountId::from(ALICE)]) - .with_session_keys(vec![( - AccountId::from(ALICE), - AccountId::from(ALICE), - SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }, - )]) - .build() - .execute_with(|| { - // We need root origin to create a sufficient asset - let minimum_asset_balance = 3333333_u128; - let local_asset_id = 1; - assert_ok!(Assets::force_create( - RuntimeHelper::root_origin(), - local_asset_id.into(), - AccountId::from(ALICE).into(), - true, - minimum_asset_balance - )); - - // We first mint enough asset for the account to exist for assets - assert_ok!(Assets::mint( - RuntimeHelper::origin_of(AccountId::from(ALICE)), - local_asset_id.into(), - AccountId::from(ALICE).into(), - minimum_asset_balance - )); - - // get asset id as location - let asset_location = - AssetIdForTrustBackedAssetsConvert::convert_back(&local_asset_id).unwrap(); - - // Set Alice as block author, who will receive fees - RuntimeHelper::run_to_block(2, AccountId::from(ALICE)); - - // We are going to buy 4e9 weight - let bought = Weight::from_parts(4_000_000_000u64, 0); - - // Lets calculate amount needed - let asset_amount_needed = - AssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles( - local_asset_id, - bought, - ) - .expect("failed to compute"); - - // Lets pay with: asset_amount_needed + asset_amount_extra - let asset_amount_extra = 100_u128; - let asset: Asset = - (asset_location.clone(), asset_amount_needed + asset_amount_extra).into(); - - let mut trader = ::Trader::new(); - let ctx = XcmContext { origin: None, message_id: XcmHash::default(), topic: None }; - - // Lets buy_weight and make sure buy_weight does not return an error - let unused_assets = trader.buy_weight(bought, asset.into(), &ctx).expect("Expected Ok"); - // Check whether a correct amount of unused assets is returned - assert_ok!(unused_assets.ensure_contains(&(asset_location, asset_amount_extra).into())); - - // Drop trader - drop(trader); - - // Make sure author(Alice) has received the amount - assert_eq!( - Assets::balance(local_asset_id, AccountId::from(ALICE)), - minimum_asset_balance + asset_amount_needed - ); - - // We also need to ensure the total supply increased - assert_eq!( - Assets::total_supply(local_asset_id), - minimum_asset_balance + asset_amount_needed - ); - }); -} - -#[test] -fn test_foreign_asset_xcm_take_first_trader() { - ExtBuilder::::default() - .with_collators(vec![AccountId::from(ALICE)]) - .with_session_keys(vec![( - AccountId::from(ALICE), - AccountId::from(ALICE), - SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }, - )]) - .build() - .execute_with(|| { - // We need root origin to create a sufficient asset - let minimum_asset_balance = 3333333_u128; - let foreign_location = Location { - parents: 1, - interior: (Junction::Parachain(1234), Junction::GeneralIndex(12345)).into(), - }; - assert_ok!(ForeignAssets::force_create( - RuntimeHelper::root_origin(), - foreign_location.clone().into(), - AccountId::from(ALICE).into(), - true, - minimum_asset_balance - )); - - // We first mint enough asset for the account to exist for assets - assert_ok!(ForeignAssets::mint( - RuntimeHelper::origin_of(AccountId::from(ALICE)), - foreign_location.clone().into(), - AccountId::from(ALICE).into(), - minimum_asset_balance - )); - - // Set Alice as block author, who will receive fees - RuntimeHelper::run_to_block(2, AccountId::from(ALICE)); - - // We are going to buy 4e9 weight - let bought = Weight::from_parts(4_000_000_000u64, 0); - - // Lets calculate amount needed - let asset_amount_needed - = ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles( - foreign_location.clone(), - bought - ) - .expect("failed to compute"); - - // Lets pay with: asset_amount_needed + asset_amount_extra - let asset_amount_extra = 100_u128; - let asset: Asset = - (foreign_location.clone(), asset_amount_needed + asset_amount_extra).into(); - - let mut trader = ::Trader::new(); - let ctx = XcmContext { origin: None, message_id: XcmHash::default(), topic: None }; - - // Lets buy_weight and make sure buy_weight does not return an error - let unused_assets = trader.buy_weight(bought, asset.into(), &ctx).expect("Expected Ok"); - // Check whether a correct amount of unused assets is returned - assert_ok!(unused_assets - .ensure_contains(&(foreign_location.clone(), asset_amount_extra).into())); - - // Drop trader - drop(trader); - - // Make sure author(Alice) has received the amount - assert_eq!( - ForeignAssets::balance(foreign_location.clone(), AccountId::from(ALICE)), - minimum_asset_balance + asset_amount_needed - ); - - // We also need to ensure the total supply increased - assert_eq!( - ForeignAssets::total_supply(foreign_location), - minimum_asset_balance + asset_amount_needed - ); - }); -} - -#[test] -fn test_asset_xcm_take_first_trader_with_refund() { - ExtBuilder::::default() - .with_collators(vec![AccountId::from(ALICE)]) - .with_session_keys(vec![( - AccountId::from(ALICE), - AccountId::from(ALICE), - SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }, - )]) - .build() - .execute_with(|| { - // We need root origin to create a sufficient asset - // We set existential deposit to be identical to the one for Balances first - assert_ok!(Assets::force_create( - RuntimeHelper::root_origin(), - 1.into(), - AccountId::from(ALICE).into(), - true, - ExistentialDeposit::get() - )); - - // We first mint enough asset for the account to exist for assets - assert_ok!(Assets::mint( - RuntimeHelper::origin_of(AccountId::from(ALICE)), - 1.into(), - AccountId::from(ALICE).into(), - ExistentialDeposit::get() - )); - - let mut trader = ::Trader::new(); - let ctx = XcmContext { origin: None, message_id: XcmHash::default(), topic: None }; - - // Set Alice as block author, who will receive fees - RuntimeHelper::run_to_block(2, AccountId::from(ALICE)); - - // We are going to buy 4e9 weight - let bought = Weight::from_parts(4_000_000_000u64, 0); - let asset_location = AssetIdForTrustBackedAssetsConvert::convert_back(&1).unwrap(); - - // lets calculate amount needed - let amount_bought = WeightToFee::weight_to_fee(&bought); - - let asset: Asset = (asset_location.clone(), amount_bought).into(); - - // Make sure buy_weight does not return an error - assert_ok!(trader.buy_weight(bought, asset.clone().into(), &ctx)); - - // Make sure again buy_weight does return an error - // This assert relies on the fact, that we use `TakeFirstAssetTrader` in `WeightTrader` - // tuple chain, which cannot be called twice - assert_noop!(trader.buy_weight(bought, asset.into(), &ctx), XcmError::TooExpensive); - - // We actually use half of the weight - let weight_used = bought / 2; - - // Make sure refund works. - let amount_refunded = WeightToFee::weight_to_fee(&(bought - weight_used)); - - assert_eq!( - trader.refund_weight(bought - weight_used, &ctx), - Some((asset_location, amount_refunded).into()) - ); - - // Drop trader - drop(trader); - - // We only should have paid for half of the bought weight - let fees_paid = WeightToFee::weight_to_fee(&weight_used); - - assert_eq!( - Assets::balance(1, AccountId::from(ALICE)), - ExistentialDeposit::get() + fees_paid - ); - - // We also need to ensure the total supply increased - assert_eq!(Assets::total_supply(1), ExistentialDeposit::get() + fees_paid); - }); -} - #[test] fn test_asset_xcm_take_first_trader_refund_not_possible_since_amount_less_than_ed() { ExtBuilder::::default() @@ -689,71 +452,6 @@ fn test_asset_xcm_take_first_trader_refund_not_possible_since_amount_less_than_e }); } -#[test] -fn test_that_buying_ed_refund_does_not_refund_for_take_first_trader() { - ExtBuilder::::default() - .with_collators(vec![AccountId::from(ALICE)]) - .with_session_keys(vec![( - AccountId::from(ALICE), - AccountId::from(ALICE), - SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }, - )]) - .build() - .execute_with(|| { - // We need root origin to create a sufficient asset - // We set existential deposit to be identical to the one for Balances first - assert_ok!(Assets::force_create( - RuntimeHelper::root_origin(), - 1.into(), - AccountId::from(ALICE).into(), - true, - ExistentialDeposit::get() - )); - - let mut trader = ::Trader::new(); - let ctx = XcmContext { origin: None, message_id: XcmHash::default(), topic: None }; - - // Set Alice as block author, who will receive fees - RuntimeHelper::run_to_block(2, AccountId::from(ALICE)); - - // We are gonna buy ED - let bought = Weight::from_parts(ExistentialDeposit::get().try_into().unwrap(), 0); - - let asset_location = AssetIdForTrustBackedAssetsConvert::convert_back(&1).unwrap(); - - let amount_bought = WeightToFee::weight_to_fee(&bought); - - assert!( - amount_bought < ExistentialDeposit::get(), - "we are testing what happens when the amount does not exceed ED" - ); - - // We know we will have to buy at least ED, so lets make sure first it will - // fail with a payment of less than ED - let asset: Asset = (asset_location.clone(), amount_bought).into(); - assert_noop!(trader.buy_weight(bought, asset.into(), &ctx), XcmError::TooExpensive); - - // Now lets buy ED at least - let asset: Asset = (asset_location, ExistentialDeposit::get()).into(); - - // Buy weight should work - assert_ok!(trader.buy_weight(bought, asset.into(), &ctx)); - - // Should return None. We have a specific check making sure we dont go below ED for - // drop payment - assert_eq!(trader.refund_weight(bought, &ctx), None); - - // Drop trader - drop(trader); - - // Make sure author(Alice) has received the amount - assert_eq!(Assets::balance(1, AccountId::from(ALICE)), ExistentialDeposit::get()); - - // We also need to ensure the total supply increased - assert_eq!(Assets::total_supply(1), ExistentialDeposit::get()); - }); -} - #[test] fn test_asset_xcm_trader_not_possible_for_non_sufficient_assets() { ExtBuilder::::default() @@ -1219,9 +917,12 @@ mod asset_hub_rococo_tests { AccountId::from([73; 32]), block_author_account.clone(), // receiving WNDs - foreign_asset_create_params, + foreign_asset_create_params.clone(), 1000000000000, - bridging_to_asset_hub_westend, + || { + setup_pool_for_paying_fees_with_foreign_assets(foreign_asset_create_params); + bridging_to_asset_hub_westend() + }, ( [PalletInstance(bp_bridge_hub_rococo::WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX)].into(), GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)), @@ -1238,15 +939,16 @@ mod asset_hub_rococo_tests { ); }, || { - // `TakeFirstAssetTrader` puts fees to the block author - assert!( + // check staking pot has at least ED + assert!(Balances::free_balance(&staking_pot) >= ExistentialDeposit::get()); + // check now foreign asset for staking pot + assert_eq!( ForeignAssets::balance( foreign_asset_id_location.clone().into(), - &block_author_account - ) > 0 + &staking_pot + ), + 0 ); - // `SwapFirstAssetTrader` did not work - assert_eq!(Balances::free_balance(&staking_pot), 0); } ) } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs index a619e986c5852..5187e0e69a4fb 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs @@ -14,11 +14,10 @@ // limitations under the License. use super::{ - AccountId, AllPalletsWithSystem, Assets, Authorship, Balance, Balances, BaseDeliveryFee, - CollatorSelection, DepositPerByte, DepositPerItem, FeeAssetId, ForeignAssets, - ForeignAssetsInstance, ParachainInfo, ParachainSystem, PolkadotXcm, PoolAssets, Runtime, - RuntimeCall, RuntimeEvent, RuntimeHoldReason, RuntimeOrigin, ToRococoXcmRouter, - TransactionByteFee, TrustBackedAssetsInstance, Uniques, WeightToFee, XcmpQueue, + AccountId, AllPalletsWithSystem, Assets, Balance, Balances, BaseDeliveryFee, CollatorSelection, + DepositPerByte, DepositPerItem, FeeAssetId, ForeignAssets, ParachainInfo, ParachainSystem, + PolkadotXcm, PoolAssets, Runtime, RuntimeCall, RuntimeEvent, RuntimeHoldReason, RuntimeOrigin, + ToRococoXcmRouter, TransactionByteFee, Uniques, WeightToFee, XcmpQueue, }; use assets_common::{ matching::{FromSiblingParachain, IsForeignConcreteAsset, ParentLocation}, @@ -36,15 +35,14 @@ use frame_system::EnsureRoot; use pallet_xcm::{AuthorizedAliasers, XcmPassthrough}; use parachains_common::{ xcm_config::{ - AllSiblingSystemParachains, AssetFeeAsExistentialDepositMultiplier, - ConcreteAssetFromSystem, RelayOrOtherSystemParachains, + AllSiblingSystemParachains, ConcreteAssetFromSystem, RelayOrOtherSystemParachains, }, TREASURY_PALLET_ID, }; use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::xcm_sender::ExponentialPrice; use snowbridge_outbound_queue_primitives::v2::exporter::PausableExporter; -use sp_runtime::traits::{AccountIdConversion, ConvertInto, TryConvertInto}; +use sp_runtime::traits::{AccountIdConversion, TryConvertInto}; use westend_runtime_constants::system_parachain::COLLECTIVES_ID; use xcm::latest::{prelude::*, ROCOCO_GENESIS_HASH, WESTEND_GENESIS_HASH}; use xcm_builder::{ @@ -247,7 +245,6 @@ pub type XcmOriginToTransactDispatchOrigin = ( parameter_types! { pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; - pub XcmAssetFeesReceiver: Option = Authorship::author(); } pub struct ParentOrParentsPlurality; @@ -310,27 +307,6 @@ pub type Barrier = TrailingSetTopicAsId< >, >; -// TODO: This calls into the Assets pallet's default `BalanceToAssetBalance` implementation, which -// uses the ratio of minimum balances and requires asset sufficiency. This means that purchasing -// weight within XCM programs will still use the old way, and paying fees via asset conversion will -// only be possible when transacting locally. We should add an impl of this trait that does asset -// conversion. -pub type AssetFeeAsExistentialDepositMultiplierFeeCharger = AssetFeeAsExistentialDepositMultiplier< - Runtime, - WeightToFee, - pallet_assets::BalanceToAssetBalance, - TrustBackedAssetsInstance, ->; - -/// Multiplier used for dedicated `TakeFirstAssetTrader` with `ForeignAssets` instance. -pub type ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger = - AssetFeeAsExistentialDepositMultiplier< - Runtime, - WeightToFee, - pallet_assets::BalanceToAssetBalance, - ForeignAssetsInstance, - >; - /// Locations that will not be charged fees in the executor, /// either execution or delivery. /// We only waive fees for system functions, which these locations represent. @@ -426,32 +402,6 @@ impl xcm_executor::Config for XcmConfig { ResolveAssetTo, AccountId, >, - // This trader allows to pay with `is_sufficient=true` "Trust Backed" assets from dedicated - // `pallet_assets` instance - `Assets`. - cumulus_primitives_utility::TakeFirstAssetTrader< - AccountId, - AssetFeeAsExistentialDepositMultiplierFeeCharger, - TrustBackedAssetsConvertedConcreteId, - Assets, - cumulus_primitives_utility::XcmFeesTo32ByteAccount< - FungiblesTransactor, - AccountId, - XcmAssetFeesReceiver, - >, - >, - // This trader allows to pay with `is_sufficient=true` "Foreign" assets from dedicated - // `pallet_assets` instance - `ForeignAssets`. - cumulus_primitives_utility::TakeFirstAssetTrader< - AccountId, - ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, - ForeignAssetsConvertedConcreteId, - ForeignAssets, - cumulus_primitives_utility::XcmFeesTo32ByteAccount< - ForeignFungiblesTransactor, - AccountId, - XcmAssetFeesReceiver, - >, - >, ); type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs index 564228d307476..951b33124404e 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs @@ -20,10 +20,8 @@ use asset_hub_westend_runtime::{ xcm_config, xcm_config::{ - bridging, AssetFeeAsExistentialDepositMultiplierFeeCharger, CheckingAccount, - ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, GovernanceLocation, - LocationToAccountId, StakingPot, TrustBackedAssetsPalletLocation, WestendLocation, - XcmConfig, + bridging, CheckingAccount, GovernanceLocation, LocationToAccountId, StakingPot, + TrustBackedAssetsPalletLocation, WestendLocation, XcmConfig, }, AllPalletsWithoutSystem, Assets, Balances, Block, ExistentialDeposit, ForeignAssets, ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, @@ -36,7 +34,6 @@ use asset_test_utils::{ ExtBuilder, GovernanceOrigin, SlotDurations, }; use codec::{Decode, Encode}; -use cumulus_primitives_utility::ChargeWeightInFungibles; use frame_support::{ assert_err, assert_noop, assert_ok, parameter_types, traits::{ @@ -420,247 +417,6 @@ fn test_buy_and_refund_weight_with_swap_foreign_asset_xcm_trader() { }) } -#[test] -fn test_asset_xcm_take_first_trader() { - ExtBuilder::::default() - .with_tracing() - .with_collators(vec![AccountId::from(ALICE)]) - .with_session_keys(vec![( - AccountId::from(ALICE), - AccountId::from(ALICE), - SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }, - )]) - .build() - .execute_with(|| { - // We need root origin to create a sufficient asset - let minimum_asset_balance = 3333333_u128; - let local_asset_id = 1; - assert_ok!(Assets::force_create( - RuntimeHelper::root_origin(), - local_asset_id.into(), - AccountId::from(ALICE).into(), - true, - minimum_asset_balance - )); - - // We first mint enough asset for the account to exist for assets - assert_ok!(Assets::mint( - RuntimeHelper::origin_of(AccountId::from(ALICE)), - local_asset_id.into(), - AccountId::from(ALICE).into(), - minimum_asset_balance - )); - - // get asset id as location - let asset_location = - AssetIdForTrustBackedAssetsConvert::convert_back(&local_asset_id).unwrap(); - - // Set Alice as block author, who will receive fees - RuntimeHelper::run_to_block(2, AccountId::from(ALICE)); - - // We are going to buy 4e9 weight - let bought = Weight::from_parts(4_000_000_000u64, 0); - - // Lets calculate amount needed - let asset_amount_needed = - AssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles( - local_asset_id, - bought, - ) - .expect("failed to compute"); - - // Lets pay with: asset_amount_needed + asset_amount_extra - let asset_amount_extra = 100_u128; - let asset: Asset = - (asset_location.clone(), asset_amount_needed + asset_amount_extra).into(); - - let mut trader = ::Trader::new(); - let ctx = XcmContext { origin: None, message_id: XcmHash::default(), topic: None }; - - // Lets buy_weight and make sure buy_weight does not return an error - let unused_assets = trader.buy_weight(bought, asset.into(), &ctx).expect("Expected Ok"); - // Check whether a correct amount of unused assets is returned - assert_ok!(unused_assets.ensure_contains(&(asset_location, asset_amount_extra).into())); - - // Drop trader - drop(trader); - - // Make sure author(Alice) has received the amount - assert_eq!( - Assets::balance(local_asset_id, AccountId::from(ALICE)), - minimum_asset_balance + asset_amount_needed - ); - - // We also need to ensure the total supply increased - assert_eq!( - Assets::total_supply(local_asset_id), - minimum_asset_balance + asset_amount_needed - ); - }); -} - -#[test] -fn test_foreign_asset_xcm_take_first_trader() { - ExtBuilder::::default() - .with_tracing() - .with_collators(vec![AccountId::from(ALICE)]) - .with_session_keys(vec![( - AccountId::from(ALICE), - AccountId::from(ALICE), - SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }, - )]) - .build() - .execute_with(|| { - // We need root origin to create a sufficient asset - let minimum_asset_balance = 3333333_u128; - let foreign_location = xcm::v5::Location { - parents: 1, - interior: ( - xcm::v5::Junction::Parachain(1234), - xcm::v5::Junction::GeneralIndex(12345), - ) - .into(), - }; - assert_ok!(ForeignAssets::force_create( - RuntimeHelper::root_origin(), - foreign_location.clone().into(), - AccountId::from(ALICE).into(), - true, - minimum_asset_balance - )); - - // We first mint enough asset for the account to exist for assets - assert_ok!(ForeignAssets::mint( - RuntimeHelper::origin_of(AccountId::from(ALICE)), - foreign_location.clone().into(), - AccountId::from(ALICE).into(), - minimum_asset_balance - )); - - let asset_location_v5: Location = foreign_location.clone().try_into().unwrap(); - - // Set Alice as block author, who will receive fees - RuntimeHelper::run_to_block(2, AccountId::from(ALICE)); - - // We are going to buy 4e9 weight - let bought = Weight::from_parts(4_000_000_000u64, 0); - - // Lets calculate amount needed - let asset_amount_needed = ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles(foreign_location.clone(), bought) - .expect("failed to compute"); - - // Lets pay with: asset_amount_needed + asset_amount_extra - let asset_amount_extra = 100_u128; - let asset: Asset = - (asset_location_v5.clone(), asset_amount_needed + asset_amount_extra).into(); - - let mut trader = ::Trader::new(); - let ctx = XcmContext { origin: None, message_id: XcmHash::default(), topic: None }; - - // Lets buy_weight and make sure buy_weight does not return an error - let unused_assets = trader.buy_weight(bought, asset.into(), &ctx).expect("Expected Ok"); - // Check whether a correct amount of unused assets is returned - assert_ok!( - unused_assets.ensure_contains(&(asset_location_v5, asset_amount_extra).into()) - ); - - // Drop trader - drop(trader); - - // Make sure author(Alice) has received the amount - assert_eq!( - ForeignAssets::balance(foreign_location.clone(), AccountId::from(ALICE)), - minimum_asset_balance + asset_amount_needed - ); - - // We also need to ensure the total supply increased - assert_eq!( - ForeignAssets::total_supply(foreign_location), - minimum_asset_balance + asset_amount_needed - ); - }); -} - -#[test] -fn test_asset_xcm_take_first_trader_with_refund() { - ExtBuilder::::default() - .with_tracing() - .with_collators(vec![AccountId::from(ALICE)]) - .with_session_keys(vec![( - AccountId::from(ALICE), - AccountId::from(ALICE), - SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }, - )]) - .build() - .execute_with(|| { - // We need root origin to create a sufficient asset - // We set existential deposit to be identical to the one for Balances first - assert_ok!(Assets::force_create( - RuntimeHelper::root_origin(), - 1.into(), - AccountId::from(ALICE).into(), - true, - ExistentialDeposit::get() - )); - - // We first mint enough asset for the account to exist for assets - assert_ok!(Assets::mint( - RuntimeHelper::origin_of(AccountId::from(ALICE)), - 1.into(), - AccountId::from(ALICE).into(), - ExistentialDeposit::get() - )); - - let mut trader = ::Trader::new(); - let ctx = XcmContext { origin: None, message_id: XcmHash::default(), topic: None }; - - // Set Alice as block author, who will receive fees - RuntimeHelper::run_to_block(2, AccountId::from(ALICE)); - - // We are going to buy 4e9 weight - let bought = Weight::from_parts(4_000_000_000u64, 0); - let asset_location = AssetIdForTrustBackedAssetsConvert::convert_back(&1).unwrap(); - - // lets calculate amount needed - let amount_bought = WeightToFee::weight_to_fee(&bought); - - let asset: Asset = (asset_location.clone(), amount_bought).into(); - - // Make sure buy_weight does not return an error - assert_ok!(trader.buy_weight(bought, asset.clone().into(), &ctx)); - - // Make sure again buy_weight does return an error - // This assert relies on the fact, that we use `TakeFirstAssetTrader` in `WeightTrader` - // tuple chain, which cannot be called twice - assert_noop!(trader.buy_weight(bought, asset.into(), &ctx), XcmError::TooExpensive); - - // We actually use half of the weight - let weight_used = bought / 2; - - // Make sure refund works. - let amount_refunded = WeightToFee::weight_to_fee(&(bought - weight_used)); - - assert_eq!( - trader.refund_weight(bought - weight_used, &ctx), - Some((asset_location, amount_refunded).into()) - ); - - // Drop trader - drop(trader); - - // We only should have paid for half of the bought weight - let fees_paid = WeightToFee::weight_to_fee(&weight_used); - - assert_eq!( - Assets::balance(1, AccountId::from(ALICE)), - ExistentialDeposit::get() + fees_paid - ); - - // We also need to ensure the total supply increased - assert_eq!(Assets::total_supply(1), ExistentialDeposit::get() + fees_paid); - }); -} - #[test] fn test_asset_xcm_take_first_trader_refund_not_possible_since_amount_less_than_ed() { ExtBuilder::::default() @@ -714,71 +470,6 @@ fn test_asset_xcm_take_first_trader_refund_not_possible_since_amount_less_than_e }); } -#[test] -fn test_that_buying_ed_refund_does_not_refund_for_take_first_trader() { - ExtBuilder::::default() - .with_tracing() - .with_collators(vec![AccountId::from(ALICE)]) - .with_session_keys(vec![( - AccountId::from(ALICE), - AccountId::from(ALICE), - SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }, - )]) - .build() - .execute_with(|| { - // We need root origin to create a sufficient asset - // We set existential deposit to be identical to the one for Balances first - assert_ok!(Assets::force_create( - RuntimeHelper::root_origin(), - 1.into(), - AccountId::from(ALICE).into(), - true, - ExistentialDeposit::get() - )); - - let mut trader = ::Trader::new(); - let ctx = XcmContext { origin: None, message_id: XcmHash::default(), topic: None }; - - // Set Alice as block author, who will receive fees - RuntimeHelper::run_to_block(2, AccountId::from(ALICE)); - - let bought = Weight::from_parts(500_000_000u64, 0); - - let asset_location = AssetIdForTrustBackedAssetsConvert::convert_back(&1).unwrap(); - - let amount_bought = WeightToFee::weight_to_fee(&bought); - - assert!( - amount_bought < ExistentialDeposit::get(), - "we are testing what happens when the amount does not exceed ED" - ); - - // We know we will have to buy at least ED, so lets make sure first it will - // fail with a payment of less than ED - let asset: Asset = (asset_location.clone(), amount_bought).into(); - assert_noop!(trader.buy_weight(bought, asset.into(), &ctx), XcmError::TooExpensive); - - // Now lets buy ED at least - let asset: Asset = (asset_location.clone(), ExistentialDeposit::get()).into(); - - // Buy weight should work - assert_ok!(trader.buy_weight(bought, asset.into(), &ctx)); - - // Should return None. We have a specific check making sure we don't go below ED for - // drop payment - assert_eq!(trader.refund_weight(bought, &ctx), None); - - // Drop trader - drop(trader); - - // Make sure author(Alice) has received the amount - assert_eq!(Assets::balance(1, AccountId::from(ALICE)), ExistentialDeposit::get()); - - // We also need to ensure the total supply increased - assert_eq!(Assets::total_supply(1), ExistentialDeposit::get()); - }); -} - #[test] fn test_asset_xcm_take_first_trader_not_possible_for_non_sufficient_assets() { ExtBuilder::::default() @@ -1320,9 +1011,12 @@ fn receive_reserve_asset_deposited_roc_from_asset_hub_rococo_fees_paid_by_suffic AccountId::from([73; 32]), block_author_account.clone(), // receiving ROCs - foreign_asset_create_params, + foreign_asset_create_params.clone(), 1000000000000, - bridging_to_asset_hub_rococo, + || { + setup_pool_for_paying_fees_with_foreign_assets(foreign_asset_create_params); + bridging_to_asset_hub_rococo() + }, ( [PalletInstance(bp_bridge_hub_westend::WITH_BRIDGE_WESTEND_TO_ROCOCO_MESSAGES_PALLET_INDEX)].into(), GlobalConsensus(ByGenesis(ROCOCO_GENESIS_HASH)), @@ -1339,15 +1033,16 @@ fn receive_reserve_asset_deposited_roc_from_asset_hub_rococo_fees_paid_by_suffic ); }, || { - // `TakeFirstAssetTrader` puts fees to the block author - assert!( + // check staking pot has at least ED + assert!(Balances::free_balance(&staking_pot) >= ExistentialDeposit::get()); + // check now foreign asset for staking pot + assert_eq!( ForeignAssets::balance( foreign_asset_id_location.clone().into(), - &block_author_account - ) > 0 + &staking_pot + ), + 0 ); - // `SwapFirstAssetTrader` did not work - assert_eq!(Balances::free_balance(&staking_pot), 0); } ) } diff --git a/prdoc/pr_8376.prdoc b/prdoc/pr_8376.prdoc new file mode 100644 index 0000000000000..0427e4129005e --- /dev/null +++ b/prdoc/pr_8376.prdoc @@ -0,0 +1,24 @@ +title: 'Remove TakeFirstAssetTrader from AH Westend and Rococo' +doc: +- audience: [Runtime Dev, Runtime User] + description: |- + Removed `TakeFirstAssetTrader` from Asset Hub Westend and Rococo. Improved macros, fixed tests. + This implies asset sufficiency no longer guarantees that weight can also be bought with it. + `SwapFirstAssetTrader` is used instead which will attempt to swap some of the given asset for the + required amount of native asset to buy weight. This may or may not succeed depending on whether + there is a local pool present with enough liquidity to serve the swap. +crates: +- name: asset-hub-westend-runtime + bump: minor +- name: asset-hub-rococo-runtime + bump: minor +- name: asset-hub-westend-integration-tests + bump: minor +- name: asset-hub-rococo-integration-tests + bump: minor +- name: emulated-integration-tests-common + bump: minor +- name: bridge-hub-westend-integration-tests + bump: minor +- name: bridge-hub-rococo-integration-tests + bump: minor