diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock
index 3c627ee2f98230f25e960c88665f3c53b681db2b..8f4653940f3cb38576fce3fd39a77b9cb11b5ebf 100644
--- a/substrate/Cargo.lock
+++ b/substrate/Cargo.lock
@@ -5007,6 +5007,7 @@ dependencies = [
 name = "pallet-asset-tx-payment"
 version = "4.0.0-dev"
 dependencies = [
+ "frame-benchmarking",
  "frame-support",
  "frame-system",
  "pallet-assets",
diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs
index 1df668cd5f972190affefd19ada7aeaaaa177167..ef1e3bb8f3c4b48f492182de2ac59ab35ca10e24 100644
--- a/substrate/bin/node/runtime/src/lib.rs
+++ b/substrate/bin/node/runtime/src/lib.rs
@@ -1440,6 +1440,7 @@ impl pallet_assets::Config for Runtime {
 	type RuntimeEvent = RuntimeEvent;
 	type Balance = u128;
 	type AssetId = u32;
+	type AssetIdParameter = codec::Compact<u32>;
 	type Currency = Balances;
 	type CreateOrigin = AsEnsureOriginWithArg<EnsureSigned<AccountId>>;
 	type ForceOrigin = EnsureRoot<AccountId>;
@@ -1453,6 +1454,8 @@ impl pallet_assets::Config for Runtime {
 	type Extra = ();
 	type WeightInfo = pallet_assets::weights::SubstrateWeight<Runtime>;
 	type RemoveItemsLimit = ConstU32<1000>;
+	#[cfg(feature = "runtime-benchmarks")]
+	type BenchmarkHelper = ();
 }
 
 parameter_types! {
diff --git a/substrate/frame/assets/src/benchmarking.rs b/substrate/frame/assets/src/benchmarking.rs
index cf141360228e9040c5cbf2f0745a10ef07d26084..ede5b4e77fac6f72c34029f7add7fddafe9a909a 100644
--- a/substrate/frame/assets/src/benchmarking.rs
+++ b/substrate/frame/assets/src/benchmarking.rs
@@ -35,43 +35,49 @@ use crate::Pallet as Assets;
 
 const SEED: u32 = 0;
 
+fn default_asset_id<T: Config<I>, I: 'static>() -> T::AssetIdParameter {
+	T::BenchmarkHelper::create_asset_id_parameter(0)
+}
+
 fn create_default_asset<T: Config<I>, I: 'static>(
 	is_sufficient: bool,
-) -> (T::AccountId, AccountIdLookupOf<T>) {
+) -> (T::AssetIdParameter, T::AccountId, AccountIdLookupOf<T>) {
+	let asset_id = default_asset_id::<T, I>();
 	let caller: T::AccountId = whitelisted_caller();
 	let caller_lookup = T::Lookup::unlookup(caller.clone());
 	let root = SystemOrigin::Root.into();
 	assert!(Assets::<T, I>::force_create(
 		root,
-		Default::default(),
+		asset_id,
 		caller_lookup.clone(),
 		is_sufficient,
 		1u32.into(),
 	)
 	.is_ok());
-	(caller, caller_lookup)
+	(asset_id, caller, caller_lookup)
 }
 
 fn create_default_minted_asset<T: Config<I>, I: 'static>(
 	is_sufficient: bool,
 	amount: T::Balance,
-) -> (T::AccountId, AccountIdLookupOf<T>) {
-	let (caller, caller_lookup) = create_default_asset::<T, I>(is_sufficient);
+) -> (T::AssetIdParameter, T::AccountId, AccountIdLookupOf<T>) {
+	let (asset_id, caller, caller_lookup) = create_default_asset::<T, I>(is_sufficient);
 	if !is_sufficient {
 		T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance());
 	}
 	assert!(Assets::<T, I>::mint(
 		SystemOrigin::Signed(caller.clone()).into(),
-		Default::default(),
+		asset_id,
 		caller_lookup.clone(),
 		amount,
 	)
 	.is_ok());
-	(caller, caller_lookup)
+	(asset_id, caller, caller_lookup)
 }
 
 fn swap_is_sufficient<T: Config<I>, I: 'static>(s: &mut bool) {
-	Asset::<T, I>::mutate(&T::AssetId::default(), |maybe_a| {
+	let asset_id = default_asset_id::<T, I>();
+	Asset::<T, I>::mutate(&asset_id.into(), |maybe_a| {
 		if let Some(ref mut a) = maybe_a {
 			sp_std::mem::swap(s, &mut a.is_sufficient)
 		}
@@ -79,6 +85,7 @@ fn swap_is_sufficient<T: Config<I>, I: 'static>(s: &mut bool) {
 }
 
 fn add_sufficients<T: Config<I>, I: 'static>(minter: T::AccountId, n: u32) {
+	let asset_id = default_asset_id::<T, I>();
 	let origin = SystemOrigin::Signed(minter);
 	let mut s = true;
 	swap_is_sufficient::<T, I>(&mut s);
@@ -87,7 +94,7 @@ fn add_sufficients<T: Config<I>, I: 'static>(minter: T::AccountId, n: u32) {
 		let target_lookup = T::Lookup::unlookup(target);
 		assert!(Assets::<T, I>::mint(
 			origin.clone().into(),
-			Default::default(),
+			asset_id,
 			target_lookup,
 			100u32.into()
 		)
@@ -97,23 +104,19 @@ fn add_sufficients<T: Config<I>, I: 'static>(minter: T::AccountId, n: u32) {
 }
 
 fn add_approvals<T: Config<I>, I: 'static>(minter: T::AccountId, n: u32) {
+	let asset_id = default_asset_id::<T, I>();
 	T::Currency::deposit_creating(&minter, T::ApprovalDeposit::get() * n.into());
 	let minter_lookup = T::Lookup::unlookup(minter.clone());
 	let origin = SystemOrigin::Signed(minter);
-	Assets::<T, I>::mint(
-		origin.clone().into(),
-		Default::default(),
-		minter_lookup,
-		(100 * (n + 1)).into(),
-	)
-	.unwrap();
+	Assets::<T, I>::mint(origin.clone().into(), asset_id, minter_lookup, (100 * (n + 1)).into())
+		.unwrap();
 	for i in 0..n {
 		let target = account("approval", i, SEED);
 		T::Currency::make_free_balance_be(&target, T::Currency::minimum_balance());
 		let target_lookup = T::Lookup::unlookup(target);
 		Assets::<T, I>::approve_transfer(
 			origin.clone().into(),
-			Default::default(),
+			asset_id,
 			target_lookup,
 			100u32.into(),
 		)
@@ -131,48 +134,49 @@ fn assert_event<T: Config<I>, I: 'static>(generic_event: <T as Config<I>>::Runti
 
 benchmarks_instance_pallet! {
 	create {
-		let asset_id = Default::default();
-		let origin = T::CreateOrigin::successful_origin(&asset_id);
-		let caller = T::CreateOrigin::ensure_origin(origin, &asset_id).unwrap();
+		let asset_id = default_asset_id::<T, I>();
+		let origin = T::CreateOrigin::successful_origin(&asset_id.into());
+		let caller = T::CreateOrigin::ensure_origin(origin, &asset_id.into()).unwrap();
 		let caller_lookup = T::Lookup::unlookup(caller.clone());
 		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
 	}: _(SystemOrigin::Signed(caller.clone()), asset_id, caller_lookup, 1u32.into())
 	verify {
-		assert_last_event::<T, I>(Event::Created { asset_id, creator: caller.clone(), owner: caller }.into());
+		assert_last_event::<T, I>(Event::Created { asset_id: asset_id.into(), creator: caller.clone(), owner: caller }.into());
 	}
 
 	force_create {
+		let asset_id = default_asset_id::<T, I>();
 		let caller: T::AccountId = whitelisted_caller();
 		let caller_lookup = T::Lookup::unlookup(caller.clone());
-	}: _(SystemOrigin::Root, Default::default(), caller_lookup, true, 1u32.into())
+	}: _(SystemOrigin::Root, asset_id, caller_lookup, true, 1u32.into())
 	verify {
-		assert_last_event::<T, I>(Event::ForceCreated { asset_id: Default::default(), owner: caller }.into());
+		assert_last_event::<T, I>(Event::ForceCreated { asset_id: asset_id.into(), owner: caller }.into());
 	}
 
 	start_destroy {
-		let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
+		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
 		Assets::<T, I>::freeze_asset(
 			SystemOrigin::Signed(caller.clone()).into(),
-			Default::default(),
+			asset_id,
 		)?;
-	}:_(SystemOrigin::Signed(caller), Default::default())
+	}:_(SystemOrigin::Signed(caller), asset_id)
 	verify {
-		assert_last_event::<T, I>(Event::DestructionStarted { asset_id: Default::default() }.into());
+		assert_last_event::<T, I>(Event::DestructionStarted { asset_id: asset_id.into() }.into());
 	}
 
 	destroy_accounts {
 		let c in 0 .. T::RemoveItemsLimit::get();
-		let (caller, _) = create_default_asset::<T, I>(true);
+		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
 		add_sufficients::<T, I>(caller.clone(), c);
 		Assets::<T, I>::freeze_asset(
 			SystemOrigin::Signed(caller.clone()).into(),
-			Default::default(),
+			asset_id,
 		)?;
-		Assets::<T,I>::start_destroy(SystemOrigin::Signed(caller.clone()).into(), Default::default())?;
-	}:_(SystemOrigin::Signed(caller), Default::default())
+		Assets::<T,I>::start_destroy(SystemOrigin::Signed(caller.clone()).into(), asset_id)?;
+	}:_(SystemOrigin::Signed(caller), asset_id)
 	verify {
 		assert_last_event::<T, I>(Event::AccountsDestroyed {
-			asset_id: Default::default() ,
+			asset_id: asset_id.into(),
 			accounts_destroyed: c,
 			accounts_remaining: 0,
 		}.into());
@@ -180,142 +184,142 @@ benchmarks_instance_pallet! {
 
 	destroy_approvals {
 		let a in 0 .. T::RemoveItemsLimit::get();
-		let (caller, _) = create_default_minted_asset::<T, I>(true, 100u32.into());
+		let (asset_id, caller, _) = create_default_minted_asset::<T, I>(true, 100u32.into());
 		add_approvals::<T, I>(caller.clone(), a);
 		Assets::<T, I>::freeze_asset(
 			SystemOrigin::Signed(caller.clone()).into(),
-			Default::default(),
+			asset_id,
 		)?;
-		Assets::<T,I>::start_destroy(SystemOrigin::Signed(caller.clone()).into(), Default::default())?;
-	}:_(SystemOrigin::Signed(caller), Default::default())
+		Assets::<T,I>::start_destroy(SystemOrigin::Signed(caller.clone()).into(), asset_id)?;
+	}:_(SystemOrigin::Signed(caller), asset_id)
 	verify {
 		assert_last_event::<T, I>(Event::ApprovalsDestroyed {
-			asset_id: Default::default() ,
+			asset_id: asset_id.into(),
 			approvals_destroyed: a,
 			approvals_remaining: 0,
 		}.into());
 	}
 
 	finish_destroy {
-		let (caller, caller_lookup) = create_default_asset::<T, I>(true);
+		let (asset_id, caller, caller_lookup) = create_default_asset::<T, I>(true);
 		Assets::<T, I>::freeze_asset(
 			SystemOrigin::Signed(caller.clone()).into(),
-			Default::default(),
+			asset_id,
 		)?;
-		Assets::<T,I>::start_destroy(SystemOrigin::Signed(caller.clone()).into(), Default::default())?;
-	}:_(SystemOrigin::Signed(caller), Default::default())
+		Assets::<T,I>::start_destroy(SystemOrigin::Signed(caller.clone()).into(), asset_id)?;
+	}:_(SystemOrigin::Signed(caller), asset_id)
 	verify {
 		assert_last_event::<T, I>(Event::Destroyed {
-			asset_id: Default::default() ,
+			asset_id: asset_id.into(),
 		}.into()
 		);
 	}
 
 	mint {
-		let (caller, caller_lookup) = create_default_asset::<T, I>(true);
+		let (asset_id, caller, caller_lookup) = create_default_asset::<T, I>(true);
 		let amount = T::Balance::from(100u32);
-	}: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup, amount)
+	}: _(SystemOrigin::Signed(caller.clone()), asset_id, caller_lookup, amount)
 	verify {
-		assert_last_event::<T, I>(Event::Issued { asset_id: Default::default(), owner: caller, total_supply: amount }.into());
+		assert_last_event::<T, I>(Event::Issued { asset_id: asset_id.into(), owner: caller, total_supply: amount }.into());
 	}
 
 	burn {
 		let amount = T::Balance::from(100u32);
-		let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, amount);
-	}: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup, amount)
+		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, amount);
+	}: _(SystemOrigin::Signed(caller.clone()), asset_id, caller_lookup, amount)
 	verify {
-		assert_last_event::<T, I>(Event::Burned { asset_id: Default::default(), owner: caller, balance: amount }.into());
+		assert_last_event::<T, I>(Event::Burned { asset_id: asset_id.into(), owner: caller, balance: amount }.into());
 	}
 
 	transfer {
 		let amount = T::Balance::from(100u32);
-		let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, amount);
+		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, amount);
 		let target: T::AccountId = account("target", 0, SEED);
 		let target_lookup = T::Lookup::unlookup(target.clone());
-	}: _(SystemOrigin::Signed(caller.clone()), Default::default(), target_lookup, amount)
+	}: _(SystemOrigin::Signed(caller.clone()), asset_id, target_lookup, amount)
 	verify {
-		assert_last_event::<T, I>(Event::Transferred { asset_id: Default::default(), from: caller, to: target, amount }.into());
+		assert_last_event::<T, I>(Event::Transferred { asset_id: asset_id.into(), from: caller, to: target, amount }.into());
 	}
 
 	transfer_keep_alive {
 		let mint_amount = T::Balance::from(200u32);
 		let amount = T::Balance::from(100u32);
-		let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, mint_amount);
+		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, mint_amount);
 		let target: T::AccountId = account("target", 0, SEED);
 		let target_lookup = T::Lookup::unlookup(target.clone());
-	}: _(SystemOrigin::Signed(caller.clone()), Default::default(), target_lookup, amount)
+	}: _(SystemOrigin::Signed(caller.clone()), asset_id, target_lookup, amount)
 	verify {
 		assert!(frame_system::Pallet::<T>::account_exists(&caller));
-		assert_last_event::<T, I>(Event::Transferred { asset_id: Default::default(), from: caller, to: target, amount }.into());
+		assert_last_event::<T, I>(Event::Transferred { asset_id: asset_id.into(), from: caller, to: target, amount }.into());
 	}
 
 	force_transfer {
 		let amount = T::Balance::from(100u32);
-		let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, amount);
+		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, amount);
 		let target: T::AccountId = account("target", 0, SEED);
 		let target_lookup = T::Lookup::unlookup(target.clone());
-	}: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup, target_lookup, amount)
+	}: _(SystemOrigin::Signed(caller.clone()), asset_id, caller_lookup, target_lookup, amount)
 	verify {
 		assert_last_event::<T, I>(
-			Event::Transferred { asset_id: Default::default(), from: caller, to: target, amount }.into()
+			Event::Transferred { asset_id: asset_id.into(), from: caller, to: target, amount }.into()
 		);
 	}
 
 	freeze {
-		let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
-	}: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup)
+		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
+	}: _(SystemOrigin::Signed(caller.clone()), asset_id, caller_lookup)
 	verify {
-		assert_last_event::<T, I>(Event::Frozen { asset_id: Default::default(), who: caller }.into());
+		assert_last_event::<T, I>(Event::Frozen { asset_id: asset_id.into(), who: caller }.into());
 	}
 
 	thaw {
-		let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
+		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
 		Assets::<T, I>::freeze(
 			SystemOrigin::Signed(caller.clone()).into(),
-			Default::default(),
+			asset_id,
 			caller_lookup.clone(),
 		)?;
-	}: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup)
+	}: _(SystemOrigin::Signed(caller.clone()), asset_id, caller_lookup)
 	verify {
-		assert_last_event::<T, I>(Event::Thawed { asset_id: Default::default(), who: caller }.into());
+		assert_last_event::<T, I>(Event::Thawed { asset_id: asset_id.into(), who: caller }.into());
 	}
 
 	freeze_asset {
-		let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
-	}: _(SystemOrigin::Signed(caller.clone()), Default::default())
+		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
+	}: _(SystemOrigin::Signed(caller.clone()), asset_id)
 	verify {
-		assert_last_event::<T, I>(Event::AssetFrozen { asset_id: Default::default() }.into());
+		assert_last_event::<T, I>(Event::AssetFrozen { asset_id: asset_id.into() }.into());
 	}
 
 	thaw_asset {
-		let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
+		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
 		Assets::<T, I>::freeze_asset(
 			SystemOrigin::Signed(caller.clone()).into(),
-			Default::default(),
+			asset_id,
 		)?;
-	}: _(SystemOrigin::Signed(caller.clone()), Default::default())
+	}: _(SystemOrigin::Signed(caller.clone()), asset_id)
 	verify {
-		assert_last_event::<T, I>(Event::AssetThawed { asset_id: Default::default() }.into());
+		assert_last_event::<T, I>(Event::AssetThawed { asset_id: asset_id.into() }.into());
 	}
 
 	transfer_ownership {
-		let (caller, _) = create_default_asset::<T, I>(true);
+		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
 		let target: T::AccountId = account("target", 0, SEED);
 		let target_lookup = T::Lookup::unlookup(target.clone());
-	}: _(SystemOrigin::Signed(caller), Default::default(), target_lookup)
+	}: _(SystemOrigin::Signed(caller), asset_id, target_lookup)
 	verify {
-		assert_last_event::<T, I>(Event::OwnerChanged { asset_id: Default::default(), owner: target }.into());
+		assert_last_event::<T, I>(Event::OwnerChanged { asset_id: asset_id.into(), owner: target }.into());
 	}
 
 	set_team {
-		let (caller, _) = create_default_asset::<T, I>(true);
+		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
 		let target0 = T::Lookup::unlookup(account("target", 0, SEED));
 		let target1 = T::Lookup::unlookup(account("target", 1, SEED));
 		let target2 = T::Lookup::unlookup(account("target", 2, SEED));
-	}: _(SystemOrigin::Signed(caller), Default::default(), target0, target1, target2)
+	}: _(SystemOrigin::Signed(caller), asset_id, target0, target1, target2)
 	verify {
 		assert_last_event::<T, I>(Event::TeamChanged {
-			asset_id: Default::default(),
+			asset_id: asset_id.into(),
 			issuer: account("target", 0, SEED),
 			admin: account("target", 1, SEED),
 			freezer: account("target", 2, SEED),
@@ -330,23 +334,22 @@ benchmarks_instance_pallet! {
 		let symbol = vec![0u8; s as usize];
 		let decimals = 12;
 
-		let (caller, _) = create_default_asset::<T, I>(true);
+		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
 		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
-	}: _(SystemOrigin::Signed(caller), Default::default(), name.clone(), symbol.clone(), decimals)
+	}: _(SystemOrigin::Signed(caller), asset_id, name.clone(), symbol.clone(), decimals)
 	verify {
-		let id = Default::default();
-		assert_last_event::<T, I>(Event::MetadataSet { asset_id: id, name, symbol, decimals, is_frozen: false }.into());
+		assert_last_event::<T, I>(Event::MetadataSet { asset_id: asset_id.into(), name, symbol, decimals, is_frozen: false }.into());
 	}
 
 	clear_metadata {
-		let (caller, _) = create_default_asset::<T, I>(true);
+		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
 		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
 		let dummy = vec![0u8; T::StringLimit::get() as usize];
 		let origin = SystemOrigin::Signed(caller.clone()).into();
-		Assets::<T, I>::set_metadata(origin, Default::default(), dummy.clone(), dummy, 12)?;
-	}: _(SystemOrigin::Signed(caller), Default::default())
+		Assets::<T, I>::set_metadata(origin, asset_id, dummy.clone(), dummy, 12)?;
+	}: _(SystemOrigin::Signed(caller), asset_id)
 	verify {
-		assert_last_event::<T, I>(Event::MetadataCleared { asset_id: Default::default() }.into());
+		assert_last_event::<T, I>(Event::MetadataCleared { asset_id: asset_id.into() }.into());
 	}
 
 	force_set_metadata {
@@ -357,11 +360,11 @@ benchmarks_instance_pallet! {
 		let symbol = vec![0u8; s as usize];
 		let decimals = 12;
 
-		create_default_asset::<T, I>(true);
+		let (asset_id, _, _) = create_default_asset::<T, I>(true);
 
 		let origin = T::ForceOrigin::successful_origin();
 		let call = Call::<T, I>::force_set_metadata {
-			id: Default::default(),
+			id: asset_id,
 			name: name.clone(),
 			symbol: symbol.clone(),
 			decimals,
@@ -369,30 +372,29 @@ benchmarks_instance_pallet! {
 		};
 	}: { call.dispatch_bypass_filter(origin)? }
 	verify {
-		let id = Default::default();
-		assert_last_event::<T, I>(Event::MetadataSet { asset_id: id, name, symbol, decimals, is_frozen: false }.into());
+		assert_last_event::<T, I>(Event::MetadataSet { asset_id: asset_id.into(), name, symbol, decimals, is_frozen: false }.into());
 	}
 
 	force_clear_metadata {
-		let (caller, _) = create_default_asset::<T, I>(true);
+		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
 		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
 		let dummy = vec![0u8; T::StringLimit::get() as usize];
 		let origin = SystemOrigin::Signed(caller).into();
-		Assets::<T, I>::set_metadata(origin, Default::default(), dummy.clone(), dummy, 12)?;
+		Assets::<T, I>::set_metadata(origin, asset_id, dummy.clone(), dummy, 12)?;
 
 		let origin = T::ForceOrigin::successful_origin();
-		let call = Call::<T, I>::force_clear_metadata { id: Default::default() };
+		let call = Call::<T, I>::force_clear_metadata { id: asset_id };
 	}: { call.dispatch_bypass_filter(origin)? }
 	verify {
-		assert_last_event::<T, I>(Event::MetadataCleared { asset_id: Default::default() }.into());
+		assert_last_event::<T, I>(Event::MetadataCleared { asset_id: asset_id.into() }.into());
 	}
 
 	force_asset_status {
-		let (caller, caller_lookup) = create_default_asset::<T, I>(true);
+		let (asset_id, caller, caller_lookup) = create_default_asset::<T, I>(true);
 
 		let origin = T::ForceOrigin::successful_origin();
 		let call = Call::<T, I>::force_asset_status {
-			id: Default::default(),
+			id: asset_id,
 			owner: caller_lookup.clone(),
 			issuer: caller_lookup.clone(),
 			admin: caller_lookup.clone(),
@@ -403,70 +405,66 @@ benchmarks_instance_pallet! {
 		};
 	}: { call.dispatch_bypass_filter(origin)? }
 	verify {
-		assert_last_event::<T, I>(Event::AssetStatusChanged { asset_id: Default::default() }.into());
+		assert_last_event::<T, I>(Event::AssetStatusChanged { asset_id: asset_id.into() }.into());
 	}
 
 	approve_transfer {
-		let (caller, _) = create_default_minted_asset::<T, I>(true, 100u32.into());
+		let (asset_id, caller, _) = create_default_minted_asset::<T, I>(true, 100u32.into());
 		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
 
-		let id = Default::default();
 		let delegate: T::AccountId = account("delegate", 0, SEED);
 		let delegate_lookup = T::Lookup::unlookup(delegate.clone());
 		let amount = 100u32.into();
-	}: _(SystemOrigin::Signed(caller.clone()), id, delegate_lookup, amount)
+	}: _(SystemOrigin::Signed(caller.clone()), asset_id, delegate_lookup, amount)
 	verify {
-		assert_last_event::<T, I>(Event::ApprovedTransfer { asset_id: id, source: caller, delegate, amount }.into());
+		assert_last_event::<T, I>(Event::ApprovedTransfer { asset_id: asset_id.into(), source: caller, delegate, amount }.into());
 	}
 
 	transfer_approved {
-		let (owner, owner_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
+		let (asset_id, owner, owner_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
 		T::Currency::make_free_balance_be(&owner, DepositBalanceOf::<T, I>::max_value());
 
-		let id = Default::default();
 		let delegate: T::AccountId = account("delegate", 0, SEED);
 		whitelist_account!(delegate);
 		let delegate_lookup = T::Lookup::unlookup(delegate.clone());
 		let amount = 100u32.into();
 		let origin = SystemOrigin::Signed(owner.clone()).into();
-		Assets::<T, I>::approve_transfer(origin, id, delegate_lookup, amount)?;
+		Assets::<T, I>::approve_transfer(origin, asset_id, delegate_lookup, amount)?;
 
 		let dest: T::AccountId = account("dest", 0, SEED);
 		let dest_lookup = T::Lookup::unlookup(dest.clone());
-	}: _(SystemOrigin::Signed(delegate.clone()), id, owner_lookup, dest_lookup, amount)
+	}: _(SystemOrigin::Signed(delegate.clone()), asset_id, owner_lookup, dest_lookup, amount)
 	verify {
 		assert!(T::Currency::reserved_balance(&owner).is_zero());
-		assert_event::<T, I>(Event::Transferred { asset_id: id, from: owner, to: dest, amount }.into());
+		assert_event::<T, I>(Event::Transferred { asset_id: asset_id.into(), from: owner, to: dest, amount }.into());
 	}
 
 	cancel_approval {
-		let (caller, _) = create_default_minted_asset::<T, I>(true, 100u32.into());
+		let (asset_id, caller, _) = create_default_minted_asset::<T, I>(true, 100u32.into());
 		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
 
-		let id = Default::default();
 		let delegate: T::AccountId = account("delegate", 0, SEED);
 		let delegate_lookup = T::Lookup::unlookup(delegate.clone());
 		let amount = 100u32.into();
 		let origin = SystemOrigin::Signed(caller.clone()).into();
-		Assets::<T, I>::approve_transfer(origin, id, delegate_lookup.clone(), amount)?;
-	}: _(SystemOrigin::Signed(caller.clone()), id, delegate_lookup)
+		Assets::<T, I>::approve_transfer(origin, asset_id, delegate_lookup.clone(), amount)?;
+	}: _(SystemOrigin::Signed(caller.clone()), asset_id, delegate_lookup)
 	verify {
-		assert_last_event::<T, I>(Event::ApprovalCancelled { asset_id: id, owner: caller, delegate }.into());
+		assert_last_event::<T, I>(Event::ApprovalCancelled { asset_id: asset_id.into(), owner: caller, delegate }.into());
 	}
 
 	force_cancel_approval {
-		let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
+		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
 		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
 
-		let id = Default::default();
 		let delegate: T::AccountId = account("delegate", 0, SEED);
 		let delegate_lookup = T::Lookup::unlookup(delegate.clone());
 		let amount = 100u32.into();
 		let origin = SystemOrigin::Signed(caller.clone()).into();
-		Assets::<T, I>::approve_transfer(origin, id, delegate_lookup.clone(), amount)?;
-	}: _(SystemOrigin::Signed(caller.clone()), id, caller_lookup, delegate_lookup)
+		Assets::<T, I>::approve_transfer(origin, asset_id, delegate_lookup.clone(), amount)?;
+	}: _(SystemOrigin::Signed(caller.clone()), asset_id, caller_lookup, delegate_lookup)
 	verify {
-		assert_last_event::<T, I>(Event::ApprovalCancelled { asset_id: id, owner: caller, delegate }.into());
+		assert_last_event::<T, I>(Event::ApprovalCancelled { asset_id: asset_id.into(), owner: caller, delegate }.into());
 	}
 
 	impl_benchmark_test_suite!(Assets, crate::mock::new_test_ext(), crate::mock::Test)
diff --git a/substrate/frame/assets/src/lib.rs b/substrate/frame/assets/src/lib.rs
index cdd0553218225300f2eeb360c30908e8ee2d6a5b..2902477d0f2b556b65c0df288215b89c7515ac5a 100644
--- a/substrate/frame/assets/src/lib.rs
+++ b/substrate/frame/assets/src/lib.rs
@@ -144,7 +144,6 @@ mod impl_stored_map;
 mod types;
 pub use types::*;
 
-use codec::HasCompact;
 use scale_info::TypeInfo;
 use sp_runtime::{
 	traits::{
@@ -186,6 +185,17 @@ pub mod pallet {
 	#[pallet::storage_version(STORAGE_VERSION)]
 	pub struct Pallet<T, I = ()>(_);
 
+	#[cfg(feature = "runtime-benchmarks")]
+	pub trait BenchmarkHelper<AssetIdParameter> {
+		fn create_asset_id_parameter(id: u32) -> AssetIdParameter;
+	}
+	#[cfg(feature = "runtime-benchmarks")]
+	impl<AssetIdParameter: From<u32>> BenchmarkHelper<AssetIdParameter> for () {
+		fn create_asset_id_parameter(id: u32) -> AssetIdParameter {
+			id.into()
+		}
+	}
+
 	#[pallet::config]
 	/// The module configuration trait.
 	pub trait Config<I: 'static = ()>: frame_system::Config {
@@ -210,14 +220,20 @@ pub mod pallet {
 		type RemoveItemsLimit: Get<u32>;
 
 		/// Identifier for the class of asset.
-		type AssetId: Member
-			+ Parameter
-			+ Default
+		type AssetId: Member + Parameter + Copy + MaybeSerializeDeserialize + MaxEncodedLen;
+
+		/// Wrapper around `Self::AssetId` to use in dispatchable call signatures. Allows the use
+		/// of compact encoding in instances of the pallet, which will prevent breaking changes
+		/// resulting from the removal of `HasCompact` from `Self::AssetId`.
+		///
+		/// This type includes the `From<Self::AssetId>` bound, since tightly coupled pallets may
+		/// want to convert an `AssetId` into a parameter for calling dispatchable functions
+		/// directly.
+		type AssetIdParameter: Parameter
 			+ Copy
-			+ HasCompact
-			+ MaybeSerializeDeserialize
-			+ MaxEncodedLen
-			+ TypeInfo;
+			+ From<Self::AssetId>
+			+ Into<Self::AssetId>
+			+ MaxEncodedLen;
 
 		/// The currency mechanism.
 		type Currency: ReservableCurrency<Self::AccountId>;
@@ -269,6 +285,10 @@ pub mod pallet {
 
 		/// Weight information for extrinsics in this pallet.
 		type WeightInfo: WeightInfo;
+
+		/// Helper trait for benchmarks.
+		#[cfg(feature = "runtime-benchmarks")]
+		type BenchmarkHelper: BenchmarkHelper<Self::AssetIdParameter>;
 	}
 
 	#[pallet::storage]
@@ -546,10 +566,11 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::create())]
 		pub fn create(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			admin: AccountIdLookupOf<T>,
 			min_balance: T::Balance,
 		) -> DispatchResult {
+			let id: T::AssetId = id.into();
 			let owner = T::CreateOrigin::ensure_origin(origin, &id)?;
 			let admin = T::Lookup::lookup(admin)?;
 
@@ -602,84 +623,86 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::force_create())]
 		pub fn force_create(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			owner: AccountIdLookupOf<T>,
 			is_sufficient: bool,
 			#[pallet::compact] min_balance: T::Balance,
 		) -> DispatchResult {
 			T::ForceOrigin::ensure_origin(origin)?;
 			let owner = T::Lookup::lookup(owner)?;
+			let id: T::AssetId = id.into();
 			Self::do_force_create(id, owner, is_sufficient, min_balance)
 		}
 
-		/// Start the process of destroying a class of fungible asset
-		/// start_destroy is the first in a series of extrinsics that should be called, to allow
-		/// destroying an asset.
+		/// Start the process of destroying a fungible asset class.
+		///
+		/// `start_destroy` is the first in a series of extrinsics that should be called, to allow
+		/// destruction of an asset class.
 		///
-		/// The origin must conform to `ForceOrigin` or must be Signed and the sender must be the
-		/// owner of the asset `id`.
+		/// The origin must conform to `ForceOrigin` or must be `Signed` by the asset's `owner`.
 		///
 		/// - `id`: The identifier of the asset to be destroyed. This must identify an existing
 		///   asset.
 		///
-		/// Assets must be freezed before calling start_destroy.
+		/// The asset class must be frozen before calling `start_destroy`.
 		#[pallet::weight(T::WeightInfo::start_destroy())]
-		pub fn start_destroy(
-			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
-		) -> DispatchResult {
+		pub fn start_destroy(origin: OriginFor<T>, id: T::AssetIdParameter) -> DispatchResult {
 			let maybe_check_owner = match T::ForceOrigin::try_origin(origin) {
 				Ok(_) => None,
 				Err(origin) => Some(ensure_signed(origin)?),
 			};
+			let id: T::AssetId = id.into();
 			Self::do_start_destroy(id, maybe_check_owner)
 		}
 
 		/// Destroy all accounts associated with a given asset.
+		///
 		/// `destroy_accounts` should only be called after `start_destroy` has been called, and the
-		/// asset is in a `Destroying` state
+		/// asset is in a `Destroying` state.
 		///
-		/// Due to weight restrictions, this function may need to be called multiple
-		/// times to fully destroy all accounts. It will destroy `RemoveItemsLimit` accounts at a
-		/// time.
+		/// Due to weight restrictions, this function may need to be called multiple times to fully
+		/// destroy all accounts. It will destroy `RemoveItemsLimit` accounts at a time.
 		///
 		/// - `id`: The identifier of the asset to be destroyed. This must identify an existing
 		///   asset.
 		///
-		/// Each call Emits the `Event::DestroyedAccounts` event.
+		/// Each call emits the `Event::DestroyedAccounts` event.
 		#[pallet::weight(T::WeightInfo::destroy_accounts(T::RemoveItemsLimit::get()))]
 		pub fn destroy_accounts(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 		) -> DispatchResultWithPostInfo {
 			let _ = ensure_signed(origin)?;
+			let id: T::AssetId = id.into();
 			let removed_accounts = Self::do_destroy_accounts(id, T::RemoveItemsLimit::get())?;
 			Ok(Some(T::WeightInfo::destroy_accounts(removed_accounts)).into())
 		}
 
-		/// Destroy all approvals associated with a given asset up to the max (T::RemoveItemsLimit),
+		/// Destroy all approvals associated with a given asset up to the max (T::RemoveItemsLimit).
+		///
 		/// `destroy_approvals` should only be called after `start_destroy` has been called, and the
-		/// asset is in a `Destroying` state
+		/// asset is in a `Destroying` state.
 		///
-		/// Due to weight restrictions, this function may need to be called multiple
-		/// times to fully destroy all approvals. It will destroy `RemoveItemsLimit` approvals at a
-		/// time.
+		/// Due to weight restrictions, this function may need to be called multiple times to fully
+		/// destroy all approvals. It will destroy `RemoveItemsLimit` approvals at a time.
 		///
 		/// - `id`: The identifier of the asset to be destroyed. This must identify an existing
 		///   asset.
 		///
-		/// Each call Emits the `Event::DestroyedApprovals` event.
+		/// Each call emits the `Event::DestroyedApprovals` event.
 		#[pallet::weight(T::WeightInfo::destroy_approvals(T::RemoveItemsLimit::get()))]
 		pub fn destroy_approvals(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 		) -> DispatchResultWithPostInfo {
 			let _ = ensure_signed(origin)?;
+			let id: T::AssetId = id.into();
 			let removed_approvals = Self::do_destroy_approvals(id, T::RemoveItemsLimit::get())?;
 			Ok(Some(T::WeightInfo::destroy_approvals(removed_approvals)).into())
 		}
 
 		/// Complete destroying asset and unreserve currency.
+		///
 		/// `finish_destroy` should only be called after `start_destroy` has been called, and the
 		/// asset is in a `Destroying` state. All accounts or approvals should be destroyed before
 		/// hand.
@@ -687,13 +710,11 @@ pub mod pallet {
 		/// - `id`: The identifier of the asset to be destroyed. This must identify an existing
 		///   asset.
 		///
-		/// Each successful call Emits the `Event::Destroyed` event.
+		/// Each successful call emits the `Event::Destroyed` event.
 		#[pallet::weight(T::WeightInfo::finish_destroy())]
-		pub fn finish_destroy(
-			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
-		) -> DispatchResult {
+		pub fn finish_destroy(origin: OriginFor<T>, id: T::AssetIdParameter) -> DispatchResult {
 			let _ = ensure_signed(origin)?;
+			let id: T::AssetId = id.into();
 			Self::do_finish_destroy(id)
 		}
 
@@ -712,12 +733,13 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::mint())]
 		pub fn mint(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			beneficiary: AccountIdLookupOf<T>,
 			#[pallet::compact] amount: T::Balance,
 		) -> DispatchResult {
 			let origin = ensure_signed(origin)?;
 			let beneficiary = T::Lookup::lookup(beneficiary)?;
+			let id: T::AssetId = id.into();
 			Self::do_mint(id, &beneficiary, amount, Some(origin))?;
 			Ok(())
 		}
@@ -740,12 +762,13 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::burn())]
 		pub fn burn(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			who: AccountIdLookupOf<T>,
 			#[pallet::compact] amount: T::Balance,
 		) -> DispatchResult {
 			let origin = ensure_signed(origin)?;
 			let who = T::Lookup::lookup(who)?;
+			let id: T::AssetId = id.into();
 
 			let f = DebitFlags { keep_alive: false, best_effort: true };
 			let _ = Self::do_burn(id, &who, amount, Some(origin), f)?;
@@ -773,12 +796,13 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::transfer())]
 		pub fn transfer(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			target: AccountIdLookupOf<T>,
 			#[pallet::compact] amount: T::Balance,
 		) -> DispatchResult {
 			let origin = ensure_signed(origin)?;
 			let dest = T::Lookup::lookup(target)?;
+			let id: T::AssetId = id.into();
 
 			let f = TransferFlags { keep_alive: false, best_effort: false, burn_dust: false };
 			Self::do_transfer(id, &origin, &dest, amount, None, f).map(|_| ())
@@ -805,12 +829,13 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::transfer_keep_alive())]
 		pub fn transfer_keep_alive(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			target: AccountIdLookupOf<T>,
 			#[pallet::compact] amount: T::Balance,
 		) -> DispatchResult {
 			let source = ensure_signed(origin)?;
 			let dest = T::Lookup::lookup(target)?;
+			let id: T::AssetId = id.into();
 
 			let f = TransferFlags { keep_alive: true, best_effort: false, burn_dust: false };
 			Self::do_transfer(id, &source, &dest, amount, None, f).map(|_| ())
@@ -838,7 +863,7 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::force_transfer())]
 		pub fn force_transfer(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			source: AccountIdLookupOf<T>,
 			dest: AccountIdLookupOf<T>,
 			#[pallet::compact] amount: T::Balance,
@@ -846,6 +871,7 @@ pub mod pallet {
 			let origin = ensure_signed(origin)?;
 			let source = T::Lookup::lookup(source)?;
 			let dest = T::Lookup::lookup(dest)?;
+			let id: T::AssetId = id.into();
 
 			let f = TransferFlags { keep_alive: false, best_effort: false, burn_dust: false };
 			Self::do_transfer(id, &source, &dest, amount, Some(origin), f).map(|_| ())
@@ -864,10 +890,11 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::freeze())]
 		pub fn freeze(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			who: AccountIdLookupOf<T>,
 		) -> DispatchResult {
 			let origin = ensure_signed(origin)?;
+			let id: T::AssetId = id.into();
 
 			let d = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?;
 			ensure!(
@@ -899,10 +926,11 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::thaw())]
 		pub fn thaw(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			who: AccountIdLookupOf<T>,
 		) -> DispatchResult {
 			let origin = ensure_signed(origin)?;
+			let id: T::AssetId = id.into();
 
 			let details = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?;
 			ensure!(
@@ -931,11 +959,9 @@ pub mod pallet {
 		///
 		/// Weight: `O(1)`
 		#[pallet::weight(T::WeightInfo::freeze_asset())]
-		pub fn freeze_asset(
-			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
-		) -> DispatchResult {
+		pub fn freeze_asset(origin: OriginFor<T>, id: T::AssetIdParameter) -> DispatchResult {
 			let origin = ensure_signed(origin)?;
+			let id: T::AssetId = id.into();
 
 			Asset::<T, I>::try_mutate(id, |maybe_details| {
 				let d = maybe_details.as_mut().ok_or(Error::<T, I>::Unknown)?;
@@ -959,11 +985,9 @@ pub mod pallet {
 		///
 		/// Weight: `O(1)`
 		#[pallet::weight(T::WeightInfo::thaw_asset())]
-		pub fn thaw_asset(
-			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
-		) -> DispatchResult {
+		pub fn thaw_asset(origin: OriginFor<T>, id: T::AssetIdParameter) -> DispatchResult {
 			let origin = ensure_signed(origin)?;
+			let id: T::AssetId = id.into();
 
 			Asset::<T, I>::try_mutate(id, |maybe_details| {
 				let d = maybe_details.as_mut().ok_or(Error::<T, I>::Unknown)?;
@@ -990,11 +1014,12 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::transfer_ownership())]
 		pub fn transfer_ownership(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			owner: AccountIdLookupOf<T>,
 		) -> DispatchResult {
 			let origin = ensure_signed(origin)?;
 			let owner = T::Lookup::lookup(owner)?;
+			let id: T::AssetId = id.into();
 
 			Asset::<T, I>::try_mutate(id, |maybe_details| {
 				let details = maybe_details.as_mut().ok_or(Error::<T, I>::Unknown)?;
@@ -1032,7 +1057,7 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::set_team())]
 		pub fn set_team(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			issuer: AccountIdLookupOf<T>,
 			admin: AccountIdLookupOf<T>,
 			freezer: AccountIdLookupOf<T>,
@@ -1041,6 +1066,7 @@ pub mod pallet {
 			let issuer = T::Lookup::lookup(issuer)?;
 			let admin = T::Lookup::lookup(admin)?;
 			let freezer = T::Lookup::lookup(freezer)?;
+			let id: T::AssetId = id.into();
 
 			Asset::<T, I>::try_mutate(id, |maybe_details| {
 				let details = maybe_details.as_mut().ok_or(Error::<T, I>::Unknown)?;
@@ -1075,12 +1101,13 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::set_metadata(name.len() as u32, symbol.len() as u32))]
 		pub fn set_metadata(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			name: Vec<u8>,
 			symbol: Vec<u8>,
 			decimals: u8,
 		) -> DispatchResult {
 			let origin = ensure_signed(origin)?;
+			let id: T::AssetId = id.into();
 			Self::do_set_metadata(id, &origin, name, symbol, decimals)
 		}
 
@@ -1096,11 +1123,9 @@ pub mod pallet {
 		///
 		/// Weight: `O(1)`
 		#[pallet::weight(T::WeightInfo::clear_metadata())]
-		pub fn clear_metadata(
-			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
-		) -> DispatchResult {
+		pub fn clear_metadata(origin: OriginFor<T>, id: T::AssetIdParameter) -> DispatchResult {
 			let origin = ensure_signed(origin)?;
+			let id: T::AssetId = id.into();
 
 			let d = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?;
 			ensure!(d.status == AssetStatus::Live, Error::<T, I>::AssetNotLive);
@@ -1131,13 +1156,14 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::force_set_metadata(name.len() as u32, symbol.len() as u32))]
 		pub fn force_set_metadata(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			name: Vec<u8>,
 			symbol: Vec<u8>,
 			decimals: u8,
 			is_frozen: bool,
 		) -> DispatchResult {
 			T::ForceOrigin::ensure_origin(origin)?;
+			let id: T::AssetId = id.into();
 
 			let bounded_name: BoundedVec<u8, T::StringLimit> =
 				name.clone().try_into().map_err(|_| Error::<T, I>::BadMetadata)?;
@@ -1181,9 +1207,10 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::force_clear_metadata())]
 		pub fn force_clear_metadata(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 		) -> DispatchResult {
 			T::ForceOrigin::ensure_origin(origin)?;
+			let id: T::AssetId = id.into();
 
 			let d = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?;
 			Metadata::<T, I>::try_mutate_exists(id, |metadata| {
@@ -1219,7 +1246,7 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::force_asset_status())]
 		pub fn force_asset_status(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			owner: AccountIdLookupOf<T>,
 			issuer: AccountIdLookupOf<T>,
 			admin: AccountIdLookupOf<T>,
@@ -1229,6 +1256,7 @@ pub mod pallet {
 			is_frozen: bool,
 		) -> DispatchResult {
 			T::ForceOrigin::ensure_origin(origin)?;
+			let id: T::AssetId = id.into();
 
 			Asset::<T, I>::try_mutate(id, |maybe_asset| {
 				let mut asset = maybe_asset.take().ok_or(Error::<T, I>::Unknown)?;
@@ -1274,12 +1302,13 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::approve_transfer())]
 		pub fn approve_transfer(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			delegate: AccountIdLookupOf<T>,
 			#[pallet::compact] amount: T::Balance,
 		) -> DispatchResult {
 			let owner = ensure_signed(origin)?;
 			let delegate = T::Lookup::lookup(delegate)?;
+			let id: T::AssetId = id.into();
 			Self::do_approve_transfer(id, &owner, &delegate, amount)
 		}
 
@@ -1299,13 +1328,15 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::cancel_approval())]
 		pub fn cancel_approval(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			delegate: AccountIdLookupOf<T>,
 		) -> DispatchResult {
 			let owner = ensure_signed(origin)?;
 			let delegate = T::Lookup::lookup(delegate)?;
+			let id: T::AssetId = id.into();
 			let mut d = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?;
 			ensure!(d.status == AssetStatus::Live, Error::<T, I>::AssetNotLive);
+
 			let approval =
 				Approvals::<T, I>::take((id, &owner, &delegate)).ok_or(Error::<T, I>::Unknown)?;
 			T::Currency::unreserve(&owner, approval.deposit);
@@ -1333,10 +1364,11 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::force_cancel_approval())]
 		pub fn force_cancel_approval(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			owner: AccountIdLookupOf<T>,
 			delegate: AccountIdLookupOf<T>,
 		) -> DispatchResult {
+			let id: T::AssetId = id.into();
 			let mut d = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?;
 			ensure!(d.status == AssetStatus::Live, Error::<T, I>::AssetNotLive);
 			T::ForceOrigin::try_origin(origin)
@@ -1381,7 +1413,7 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::transfer_approved())]
 		pub fn transfer_approved(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			owner: AccountIdLookupOf<T>,
 			destination: AccountIdLookupOf<T>,
 			#[pallet::compact] amount: T::Balance,
@@ -1389,6 +1421,7 @@ pub mod pallet {
 			let delegate = ensure_signed(origin)?;
 			let owner = T::Lookup::lookup(owner)?;
 			let destination = T::Lookup::lookup(destination)?;
+			let id: T::AssetId = id.into();
 			Self::do_transfer_approved(id, &owner, &delegate, &destination, amount)
 		}
 
@@ -1402,7 +1435,8 @@ pub mod pallet {
 		///
 		/// Emits `Touched` event when successful.
 		#[pallet::weight(T::WeightInfo::mint())]
-		pub fn touch(origin: OriginFor<T>, #[pallet::compact] id: T::AssetId) -> DispatchResult {
+		pub fn touch(origin: OriginFor<T>, id: T::AssetIdParameter) -> DispatchResult {
+			let id: T::AssetId = id.into();
 			Self::do_touch(id, ensure_signed(origin)?)
 		}
 
@@ -1417,9 +1451,10 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::mint())]
 		pub fn refund(
 			origin: OriginFor<T>,
-			#[pallet::compact] id: T::AssetId,
+			id: T::AssetIdParameter,
 			allow_burn: bool,
 		) -> DispatchResult {
+			let id: T::AssetId = id.into();
 			Self::do_refund(id, ensure_signed(origin)?, allow_burn)
 		}
 	}
diff --git a/substrate/frame/assets/src/mock.rs b/substrate/frame/assets/src/mock.rs
index 567d63356a4ad3af7e56e5abf627e25773853184..06b6ccf06c57ef4209dd130b273b6386bdec8a5d 100644
--- a/substrate/frame/assets/src/mock.rs
+++ b/substrate/frame/assets/src/mock.rs
@@ -88,6 +88,7 @@ impl Config for Test {
 	type RuntimeEvent = RuntimeEvent;
 	type Balance = u64;
 	type AssetId = u32;
+	type AssetIdParameter = u32;
 	type Currency = Balances;
 	type CreateOrigin = AsEnsureOriginWithArg<frame_system::EnsureSigned<u64>>;
 	type ForceOrigin = frame_system::EnsureRoot<u64>;
@@ -101,6 +102,8 @@ impl Config for Test {
 	type WeightInfo = ();
 	type Extra = ();
 	type RemoveItemsLimit = ConstU32<5>;
+	#[cfg(feature = "runtime-benchmarks")]
+	type BenchmarkHelper = ();
 }
 
 use std::collections::HashMap;
diff --git a/substrate/frame/transaction-payment/asset-tx-payment/Cargo.toml b/substrate/frame/transaction-payment/asset-tx-payment/Cargo.toml
index 51ce2f69a4d8ee47644770270af8cd7f037f6c66..cfc56c91effd1f0c26da9c3c5c1143b6635d2e8c 100644
--- a/substrate/frame/transaction-payment/asset-tx-payment/Cargo.toml
+++ b/substrate/frame/transaction-payment/asset-tx-payment/Cargo.toml
@@ -22,6 +22,7 @@ sp-std = { version = "5.0.0", default-features = false, path = "../../../primiti
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" }
 pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = ".." }
+frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking", optional = true }
 
 # Other dependencies
 codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
@@ -51,5 +52,12 @@ std = [
 	"sp-io/std",
 	"sp-core/std",
 	"pallet-transaction-payment/std",
+	"frame-benchmarking?/std",
+]
+runtime-benchmarks = [
+	"frame-benchmarking/runtime-benchmarks",
+	"sp-runtime/runtime-benchmarks",
+	"frame-system/runtime-benchmarks",
+	"pallet-assets/runtime-benchmarks",
 ]
 try-runtime = ["frame-support/try-runtime"]
diff --git a/substrate/frame/transaction-payment/asset-tx-payment/src/tests.rs b/substrate/frame/transaction-payment/asset-tx-payment/src/tests.rs
index 7b605be5f830cecc33a2911ea23b321f2dd80b53..02e15654f3eed6deea1ce8cd37ca8fc1dd191178 100644
--- a/substrate/frame/transaction-payment/asset-tx-payment/src/tests.rs
+++ b/substrate/frame/transaction-payment/asset-tx-payment/src/tests.rs
@@ -16,6 +16,7 @@
 use super::*;
 use crate as pallet_asset_tx_payment;
 
+use codec;
 use frame_support::{
 	assert_ok,
 	dispatch::{DispatchClass, DispatchInfo, PostDispatchInfo},
@@ -152,10 +153,13 @@ impl pallet_transaction_payment::Config for Runtime {
 	type OperationalFeeMultiplier = ConstU8<5>;
 }
 
+type AssetId = u32;
+
 impl pallet_assets::Config for Runtime {
 	type RuntimeEvent = RuntimeEvent;
 	type Balance = Balance;
-	type AssetId = u32;
+	type AssetId = AssetId;
+	type AssetIdParameter = codec::Compact<AssetId>;
 	type Currency = Balances;
 	type CreateOrigin = AsEnsureOriginWithArg<frame_system::EnsureSigned<AccountId>>;
 	type ForceOrigin = EnsureRoot<AccountId>;
@@ -169,6 +173,8 @@ impl pallet_assets::Config for Runtime {
 	type Extra = ();
 	type WeightInfo = ();
 	type RemoveItemsLimit = ConstU32<1000>;
+	#[cfg(feature = "runtime-benchmarks")]
+	type BenchmarkHelper = ();
 }
 
 pub struct HardcodedAuthor;
@@ -341,7 +347,7 @@ fn transaction_payment_in_asset_possible() {
 			let min_balance = 2;
 			assert_ok!(Assets::force_create(
 				RuntimeOrigin::root(),
-				asset_id,
+				asset_id.into(),
 				42,   /* owner */
 				true, /* is_sufficient */
 				min_balance
@@ -351,7 +357,7 @@ fn transaction_payment_in_asset_possible() {
 			let caller = 1;
 			let beneficiary = <Runtime as system::Config>::Lookup::unlookup(caller);
 			let balance = 100;
-			assert_ok!(Assets::mint_into(asset_id, &beneficiary, balance));
+			assert_ok!(Assets::mint_into(asset_id.into(), &beneficiary, balance));
 			assert_eq!(Assets::balance(asset_id, caller), balance);
 			let weight = 5;
 			let len = 10;
@@ -394,7 +400,7 @@ fn transaction_payment_without_fee() {
 			let min_balance = 2;
 			assert_ok!(Assets::force_create(
 				RuntimeOrigin::root(),
-				asset_id,
+				asset_id.into(),
 				42,   /* owner */
 				true, /* is_sufficient */
 				min_balance
@@ -404,7 +410,7 @@ fn transaction_payment_without_fee() {
 			let caller = 1;
 			let beneficiary = <Runtime as system::Config>::Lookup::unlookup(caller);
 			let balance = 100;
-			assert_ok!(Assets::mint_into(asset_id, &beneficiary, balance));
+			assert_ok!(Assets::mint_into(asset_id.into(), &beneficiary, balance));
 			assert_eq!(Assets::balance(asset_id, caller), balance);
 			let weight = 5;
 			let len = 10;
@@ -447,7 +453,7 @@ fn asset_transaction_payment_with_tip_and_refund() {
 			let min_balance = 2;
 			assert_ok!(Assets::force_create(
 				RuntimeOrigin::root(),
-				asset_id,
+				asset_id.into(),
 				42,   /* owner */
 				true, /* is_sufficient */
 				min_balance
@@ -457,7 +463,7 @@ fn asset_transaction_payment_with_tip_and_refund() {
 			let caller = 2;
 			let beneficiary = <Runtime as system::Config>::Lookup::unlookup(caller);
 			let balance = 1000;
-			assert_ok!(Assets::mint_into(asset_id, &beneficiary, balance));
+			assert_ok!(Assets::mint_into(asset_id.into(), &beneficiary, balance));
 			assert_eq!(Assets::balance(asset_id, caller), balance);
 			let weight = 100;
 			let tip = 5;
@@ -499,7 +505,7 @@ fn payment_from_account_with_only_assets() {
 			let min_balance = 2;
 			assert_ok!(Assets::force_create(
 				RuntimeOrigin::root(),
-				asset_id,
+				asset_id.into(),
 				42,   /* owner */
 				true, /* is_sufficient */
 				min_balance
@@ -509,7 +515,7 @@ fn payment_from_account_with_only_assets() {
 			let caller = 333;
 			let beneficiary = <Runtime as system::Config>::Lookup::unlookup(caller);
 			let balance = 100;
-			assert_ok!(Assets::mint_into(asset_id, &beneficiary, balance));
+			assert_ok!(Assets::mint_into(asset_id.into(), &beneficiary, balance));
 			assert_eq!(Assets::balance(asset_id, caller), balance);
 			// assert that native balance is not necessary
 			assert_eq!(Balances::free_balance(caller), 0);
@@ -558,7 +564,7 @@ fn payment_only_with_existing_sufficient_asset() {
 			let min_balance = 2;
 			assert_ok!(Assets::force_create(
 				RuntimeOrigin::root(),
-				asset_id,
+				asset_id.into(),
 				42,    /* owner */
 				false, /* is_sufficient */
 				min_balance
@@ -583,7 +589,7 @@ fn converted_fee_is_never_zero_if_input_fee_is_not() {
 			let min_balance = 1;
 			assert_ok!(Assets::force_create(
 				RuntimeOrigin::root(),
-				asset_id,
+				asset_id.into(),
 				42,   /* owner */
 				true, /* is_sufficient */
 				min_balance
@@ -593,7 +599,7 @@ fn converted_fee_is_never_zero_if_input_fee_is_not() {
 			let caller = 333;
 			let beneficiary = <Runtime as system::Config>::Lookup::unlookup(caller);
 			let balance = 100;
-			assert_ok!(Assets::mint_into(asset_id, &beneficiary, balance));
+			assert_ok!(Assets::mint_into(asset_id.into(), &beneficiary, balance));
 			assert_eq!(Assets::balance(asset_id, caller), balance);
 			let weight = 1;
 			let len = 1;
@@ -648,7 +654,7 @@ fn post_dispatch_fee_is_zero_if_pre_dispatch_fee_is_zero() {
 			let min_balance = 100;
 			assert_ok!(Assets::force_create(
 				RuntimeOrigin::root(),
-				asset_id,
+				asset_id.into(),
 				42,   /* owner */
 				true, /* is_sufficient */
 				min_balance
@@ -658,7 +664,7 @@ fn post_dispatch_fee_is_zero_if_pre_dispatch_fee_is_zero() {
 			let caller = 333;
 			let beneficiary = <Runtime as system::Config>::Lookup::unlookup(caller);
 			let balance = 100;
-			assert_ok!(Assets::mint_into(asset_id, &beneficiary, balance));
+			assert_ok!(Assets::mint_into(asset_id.into(), &beneficiary, balance));
 			assert_eq!(Assets::balance(asset_id, caller), balance);
 			let weight = 1;
 			let len = 1;
@@ -705,7 +711,7 @@ fn post_dispatch_fee_is_zero_if_unsigned_pre_dispatch_fee_is_zero() {
 			let min_balance = 100;
 			assert_ok!(Assets::force_create(
 				RuntimeOrigin::root(),
-				asset_id,
+				asset_id.into(),
 				42,   /* owner */
 				true, /* is_sufficient */
 				min_balance
@@ -715,7 +721,7 @@ fn post_dispatch_fee_is_zero_if_unsigned_pre_dispatch_fee_is_zero() {
 			let caller = 333;
 			let beneficiary = <Runtime as system::Config>::Lookup::unlookup(caller);
 			let balance = 100;
-			assert_ok!(Assets::mint_into(asset_id, &beneficiary, balance));
+			assert_ok!(Assets::mint_into(asset_id.into(), &beneficiary, balance));
 			assert_eq!(Assets::balance(asset_id, caller), balance);
 			let weight = 1;
 			let len = 1;