diff --git a/evm-template/runtime/src/apis.rs b/evm-template/runtime/src/apis.rs index 43b0785f..dc824693 100644 --- a/evm-template/runtime/src/apis.rs +++ b/evm-template/runtime/src/apis.rs @@ -478,6 +478,7 @@ impl_runtime_apis! { ).into()); /// The base fee for the message delivery fees. Kusama is based for the reference. pub const ToParentBaseDeliveryFee: u128 = CENTS.saturating_mul(3); + pub const InitialTransferAssetAmount: u128 = 4001070000100; } pub type PriceForParentDelivery = polkadot_runtime_common::xcm_sender::ExponentialPrice< FeeAssetId, @@ -486,7 +487,7 @@ impl_runtime_apis! { ParachainSystem, >; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; - use xcm::latest::prelude::{Asset, AssetId, Assets as AssetList, Fungible, Location, Parachain, Parent, ParentThen}; + use xcm::latest::prelude::{Asset, AssetId, Assets as AssetList, Fungible, Location, Parachain, Parent, ParentThen, PalletInstance, GeneralIndex}; impl pallet_xcm::benchmarking::Config for Runtime { type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper< xcm_config::XcmConfig, @@ -503,18 +504,113 @@ impl_runtime_apis! { } fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> { + use frame_support::traits::PalletInfoAccess; + use xcm_primitives::AssetTypeGetter; + use frame_system::RawOrigin; + + // set up fee asset + let fee_location = RelayLocation::get(); + let who: AccountId = frame_benchmarking::whitelisted_caller(); + + let Some(location_v3) = xcm::v3::Location::try_from(fee_location.clone()).ok() else { + return None; + }; + let asset_type = AssetType::Xcm(location_v3); + + let local_asset_id: crate::types::AssetId = asset_type.clone().into(); + let manager_id = AssetManager::account_id(); + let _ = Assets::force_create(RuntimeOrigin::root(), local_asset_id.clone().into(), sp_runtime::MultiAddress::Id(manager_id.clone()), true, 1); + let _ = Assets::mint( + RawOrigin::Signed(manager_id.clone()).into(), + local_asset_id.into(), + sp_runtime::MultiAddress::Id(who), + InitialTransferAssetAmount::get(), + ); + AssetManager::set_asset_type_asset_id(asset_type.clone(), local_asset_id.into()); + + // open a mock parachain channel + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( + RandomParaId::get().into() + ); + + // set up transfer asset + let initial_asset_amount: u128 = InitialTransferAssetAmount::get(); + let (asset_id, _, _) = pallet_assets::benchmarking::create_default_minted_asset::< + Runtime, + () + >(true, initial_asset_amount); + + let asset_id_u128: u128 = asset_id.into(); + let self_reserve = Location { + parents: 0, + interior: [ + PalletInstance(::index() as u8), GeneralIndex(asset_id_u128) + ].into() + }; + + let Some(location_v3) = xcm::v3::Location::try_from(self_reserve.clone()).ok() else { + return None; + }; + let asset_type = AssetType::Xcm(location_v3); + AssetManager::set_asset_type_asset_id(asset_type.clone(), asset_id_u128); + + let asset = Asset { + fun: Fungible(ExistentialDeposit::get()), + id: AssetId(self_reserve.into()) + }.into(); Some(( - Asset { - fun: Fungible(ExistentialDeposit::get()), - id: AssetId(Parent.into()) - }.into(), + asset, ParentThen(Parachain(RandomParaId::get().into()).into()).into(), )) } fn set_up_complex_asset_transfer( ) -> Option<(AssetList, u32, Location, Box)> { - None + use frame_support::traits::PalletInfoAccess; + use xcm_primitives::AssetTypeGetter; + // set up local asset + let initial_asset_amount: u128 = 1000000011; + + let (asset_id, _, _) = pallet_assets::benchmarking::create_default_minted_asset::< + Runtime, + () + >(true, initial_asset_amount); + + let asset_id_u128: u128 = asset_id.into(); + + let self_reserve = Location { + parents:0, + interior: [ + PalletInstance(::index() as u8), GeneralIndex(asset_id_u128) + ].into() + }; + + let Some(location_v3) = xcm::v3::Location::try_from(self_reserve.clone()).ok() else { + return None; + }; + let asset_type = AssetType::Xcm(location_v3); + AssetManager::set_asset_type_asset_id(asset_type.clone(), asset_id_u128); + + let destination: xcm::v4::Location = Parent.into(); + + // set up fee asset + let fee_amount: u128 = ::ExistentialDeposit::get(); + let asset_amount: u128 = 10; + let fee_asset: Asset = (self_reserve.clone(), fee_amount).into(); + let transfer_asset: Asset = (self_reserve.clone(), asset_amount).into(); + + let assets: cumulus_primitives_core::Assets = vec![fee_asset.clone(), transfer_asset].into(); + let fee_index: u32 = 0; + + let who = frame_benchmarking::whitelisted_caller(); + + let verify: Box = Box::new(move || { + // verify balance after transfer, decreased by + // transferred amount (and delivery fees) + assert!(Assets::balance(asset_id_u128, &who) <= initial_asset_amount - fee_amount); + }); + + Some((assets, fee_index, destination, verify)) } fn get_asset() -> Asset { diff --git a/evm-template/runtime/src/configs/xcm_config.rs b/evm-template/runtime/src/configs/xcm_config.rs index 497741cf..be9df132 100644 --- a/evm-template/runtime/src/configs/xcm_config.rs +++ b/evm-template/runtime/src/configs/xcm_config.rs @@ -297,11 +297,13 @@ impl pallet_xcm::Config for Runtime { type Weigher = FixedWeightBounds; /// Rerun benchmarks if you are making changes to runtime configuration. type WeightInfo = weights::pallet_xcm::WeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type XcmExecuteFilter = Everything; + #[cfg(not(feature = "runtime-benchmarks"))] type XcmExecuteFilter = Nothing; - // ^ Disable dispatchable execute on the XCM pallet. // Needs to be `Everything` for local testing. type XcmExecutor = XcmExecutor; - type XcmReserveTransferFilter = Nothing; + type XcmReserveTransferFilter = Everything; type XcmRouter = XcmRouter; type XcmTeleportFilter = Nothing; diff --git a/generic-template/runtime/src/apis.rs b/generic-template/runtime/src/apis.rs index 27a4d80d..7b3ccf3a 100644 --- a/generic-template/runtime/src/apis.rs +++ b/generic-template/runtime/src/apis.rs @@ -261,7 +261,7 @@ impl_runtime_apis! { ParachainSystem, >; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; - use xcm::latest::prelude::{Asset, AssetId, Assets as AssetList, Fungible, Location, Parachain, Parent, ParentThen}; + use xcm::latest::prelude::{Asset, AssetId, Assets as AssetList, Fungible, Location, Parachain, Parent, ParentThen, PalletInstance, GeneralIndex}; impl pallet_xcm::benchmarking::Config for Runtime { type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper< xcm_config::XcmConfig, @@ -278,10 +278,30 @@ impl_runtime_apis! { } fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> { + use frame_support::traits::PalletInfoAccess; + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( + RandomParaId::get().into() + ); + let balance = 3001070000000; + let who = frame_benchmarking::whitelisted_caller(); + let _ = + >::make_free_balance_be(&who, balance); + + let asset_amount: u128 = 10u128; + let initial_asset_amount: u128 = asset_amount * 10; + + let (asset_id, _, _) = pallet_assets::benchmarking::create_default_minted_asset::< + Runtime, + () + >(true, initial_asset_amount); + + let asset_id_u32: u32 = asset_id.into(); + + let location = Location {parents: 0, interior: (PalletInstance(::index() as u8), GeneralIndex(asset_id_u32 as u128)).into()}; Some(( Asset { fun: Fungible(ExistentialDeposit::get()), - id: AssetId(Parent.into()) + id: AssetId(location.into()) }.into(), ParentThen(Parachain(RandomParaId::get().into()).into()).into(), )) @@ -289,12 +309,54 @@ impl_runtime_apis! { fn set_up_complex_asset_transfer( ) -> Option<(AssetList, u32, Location, Box)> { - None + use frame_support::traits::PalletInfoAccess; + // set up local asset + let asset_amount: u128 = 10u128; + let initial_asset_amount: u128 = 1000000011; + let (asset_id, _, _) = pallet_assets::benchmarking::create_default_minted_asset::< + Runtime, + () + >(true, initial_asset_amount); + let asset_id_u32: u32 = asset_id.into(); + + let self_reserve = Location { + parents:0, + interior: [ + PalletInstance(::index() as u8), GeneralIndex(asset_id_u32 as u128) + ].into() + }; + + let destination: xcm::v4::Location = Parent.into(); + + let fee_amount: u128 = ::ExistentialDeposit::get(); + let fee_asset: Asset = (self_reserve.clone(), fee_amount).into(); + + // Give some multiple of transferred amount + let balance = fee_amount * 1000; + let who = frame_benchmarking::whitelisted_caller(); + let _ = + >::make_free_balance_be(&who, balance); + + // verify initial balance + assert_eq!(Balances::free_balance(&who), balance); + let transfer_asset: Asset = (self_reserve.clone(), asset_amount).into(); + + let assets: cumulus_primitives_core::Assets = vec![fee_asset.clone(), transfer_asset].into(); + let fee_index: u32 = 0; + + let verify: Box = Box::new(move || { + // verify balance after transfer, decreased by + // transferred amount (and delivery fees) + assert!(Assets::balance(asset_id_u32, &who) <= initial_asset_amount - fee_amount); + }); + + Some((assets, fee_index, destination, verify)) } fn get_asset() -> Asset { + use frame_support::traits::PalletInfoAccess; Asset { - id: AssetId(Location::parent()), + id: AssetId((Location {parents: 0, interior: (PalletInstance(::index() as u8), GeneralIndex(1)).into()}).into()), fun: Fungible(ExistentialDeposit::get()), } } diff --git a/generic-template/runtime/src/configs/mod.rs b/generic-template/runtime/src/configs/mod.rs index dc05d30c..639fbef2 100644 --- a/generic-template/runtime/src/configs/mod.rs +++ b/generic-template/runtime/src/configs/mod.rs @@ -323,8 +323,8 @@ impl pallet_assets::Config for Runtime { type ApprovalDeposit = ApprovalDeposit; type AssetAccountDeposit = AssetAccountDeposit; type AssetDeposit = AssetDeposit; - type AssetId = u32; - type AssetIdParameter = parity_scale_codec::Compact; + type AssetId = crate::types::AssetId; + type AssetIdParameter = parity_scale_codec::Compact; type Balance = Balance; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); diff --git a/generic-template/runtime/src/configs/xcm_config.rs b/generic-template/runtime/src/configs/xcm_config.rs index aa6bc0f6..352c7e21 100644 --- a/generic-template/runtime/src/configs/xcm_config.rs +++ b/generic-template/runtime/src/configs/xcm_config.rs @@ -223,11 +223,13 @@ impl pallet_xcm::Config for Runtime { type Weigher = FixedWeightBounds; /// Rerun benchmarks if you are making changes to runtime configuration. type WeightInfo = weights::pallet_xcm::WeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type XcmExecuteFilter = Everything; + #[cfg(not(feature = "runtime-benchmarks"))] type XcmExecuteFilter = Nothing; - // ^ Disable dispatchable execute on the XCM pallet. // Needs to be `Everything` for local testing. type XcmExecutor = XcmExecutor; - type XcmReserveTransferFilter = Nothing; + type XcmReserveTransferFilter = Everything; type XcmRouter = XcmRouter; type XcmTeleportFilter = Nothing; diff --git a/generic-template/runtime/src/types.rs b/generic-template/runtime/src/types.rs index c3474e29..1c7a1e60 100644 --- a/generic-template/runtime/src/types.rs +++ b/generic-template/runtime/src/types.rs @@ -39,6 +39,9 @@ pub type AccountId = <::Signer as IdentifyAccount>::Account /// Balance of an account. pub type Balance = u128; +/// Identifier of an asset +pub type AssetId = u32; + /// Index of a transaction in the chain. pub type Nonce = u32;