git.delta.rocks / unique-network / refs/commits / 742862849b4b

difftreelog

fix EVM mint with properties, minor improvements

Daniel Shiposha2023-10-13parent: #aae21d3.patch.diff
in: master

9 files changed

modifiedpallets/common/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/common/src/benchmarking.rs
+++ b/pallets/common/src/benchmarking.rs
@@ -29,9 +29,8 @@
 use sp_std::{vec, vec::Vec};
 use up_data_structs::{
 	AccessMode, CollectionId, CollectionMode, CollectionPermissions, CreateCollectionData,
-	NestingPermissions, PropertiesPermissionMap, Property, PropertyKey, PropertyValue,
-	MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_COLLECTION_NAME_LENGTH, MAX_PROPERTIES_PER_ITEM,
-	MAX_TOKEN_PREFIX_LENGTH,
+	NestingPermissions, Property, PropertyKey, PropertyValue, MAX_COLLECTION_DESCRIPTION_LENGTH,
+	MAX_COLLECTION_NAME_LENGTH, MAX_PROPERTIES_PER_ITEM, MAX_TOKEN_PREFIX_LENGTH,
 };
 
 use crate::{BenchmarkPropertyWriter, CollectionHandle, Config, Pallet};
@@ -190,31 +189,6 @@
 		#[block]
 		{
 			<Pallet<T>>::set_collection_properties(&collection, &owner, props.into_iter())?;
-		}
-
-		Ok(())
-	}
-
-	#[benchmark]
-	fn delete_collection_properties(
-		b: Linear<0, MAX_PROPERTIES_PER_ITEM>,
-	) -> Result<(), BenchmarkError> {
-		bench_init! {
-			owner: sub; collection: collection(owner);
-			owner: cross_from_sub;
-		};
-		let props = (0..b)
-			.map(|p| Property {
-				key: property_key(p as usize),
-				value: property_value(),
-			})
-			.collect::<Vec<_>>();
-		<Pallet<T>>::set_collection_properties(&collection, &owner, props.into_iter())?;
-		let to_delete = (0..b).map(|p| property_key(p as usize)).collect::<Vec<_>>();
-
-		#[block]
-		{
-			<Pallet<T>>::delete_collection_properties(&collection, &owner, to_delete.into_iter())?;
 		}
 
 		Ok(())
@@ -253,7 +227,7 @@
 	}
 
 	#[benchmark]
-	fn init_token_properties_common() -> Result<(), BenchmarkError> {
+	fn property_writer_load_collection_info() -> Result<(), BenchmarkError> {
 		bench_init! {
 			owner: sub; collection: collection(owner);
 			sender: sub;
modifiedpallets/common/src/erc.rsdiffbeforeafterboth
--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -126,7 +126,7 @@
 	///
 	/// @param key Property key.
 	#[solidity(hide)]
-	#[weight(<SelfWeightOf<T>>::delete_collection_properties(1))]
+	#[weight(<SelfWeightOf<T>>::set_collection_properties(1))]
 	fn delete_collection_property(&mut self, caller: Caller, key: String) -> Result<()> {
 		let caller = T::CrossAccountId::from_eth(caller);
 		let key = <Vec<u8>>::from(key)
@@ -139,7 +139,7 @@
 	/// Delete collection properties.
 	///
 	/// @param keys Properties keys.
-	#[weight(<SelfWeightOf<T>>::delete_collection_properties(keys.len() as u32))]
+	#[weight(<SelfWeightOf<T>>::set_collection_properties(keys.len() as u32))]
 	fn delete_collection_properties(&mut self, caller: Caller, keys: Vec<String>) -> Result<()> {
 		let caller = T::CrossAccountId::from_eth(caller);
 		let keys = keys
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -2626,8 +2626,8 @@
 impl<T: Config> BenchmarkPropertyWriter<T> {
 	/// Creates a [`PropertyWriter`] for benchmarking tokens properties writing.
 	pub fn new<'a, Handle>(
-		collection: &Handle,
-		collection_lazy_info: PropertyWriterLazyCollectionInfo,
+		collection: &'a Handle,
+		collection_lazy_info: PropertyWriterLazyCollectionInfo<'a>,
 	) -> PropertyWriter<'a, Self, T, Handle>
 	where
 		Handle: CommonCollectionOperations<T> + Deref<Target = CollectionHandle<T>>,
modifiedpallets/nonfungible/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/benchmarking.rs
+++ b/pallets/nonfungible/src/benchmarking.rs
@@ -18,7 +18,6 @@
 use pallet_common::{
 	bench_init,
 	benchmarking::{create_collection_raw, property_key, property_value},
-	CommonCollectionOperations,
 };
 use sp_std::prelude::*;
 use up_data_structs::{
@@ -131,53 +130,12 @@
 		#[block]
 		{
 			<Pallet<T>>::burn(&collection, &burner, item)?;
-		}
-
-		Ok(())
-	}
-
-	#[benchmark]
-	fn burn_recursively_self_raw() -> Result<(), BenchmarkError> {
-		bench_init! {
-			owner: sub; collection: collection(owner);
-			sender: cross_from_sub(owner); burner: cross_sub;
-		};
-		let item = create_max_item(&collection, &sender, burner.clone())?;
-
-		#[block]
-		{
-			<Pallet<T>>::burn_recursively(&collection, &burner, item, &Unlimited, &Unlimited)?;
 		}
 
 		Ok(())
 	}
 
 	#[benchmark]
-	fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(
-		b: Linear<0, 200>,
-	) -> Result<(), BenchmarkError> {
-		bench_init! {
-			owner: sub; collection: collection(owner);
-			sender: cross_from_sub(owner); burner: cross_sub;
-		};
-		let item = create_max_item(&collection, &sender, burner.clone())?;
-		for _ in 0..b {
-			create_max_item(
-				&collection,
-				&sender,
-				T::CrossTokenAddressMapping::token_to_address(collection.id, item),
-			)?;
-		}
-
-		#[block]
-		{
-			<Pallet<T>>::burn_recursively(&collection, &burner, item, &Unlimited, &Unlimited)?;
-		}
-
-		Ok(())
-	}
-
-	#[benchmark]
 	fn transfer_raw() -> Result<(), BenchmarkError> {
 		bench_init! {
 			owner: sub; collection: collection(owner);
@@ -262,116 +220,34 @@
 		{
 			<Pallet<T>>::burn_from(&collection, &burner, &sender, item, &Unlimited)?;
 		}
-	}
 
-	// set_token_properties {
-	// 	let b in 0..MAX_PROPERTIES_PER_ITEM;
-	// 	bench_init!{
-	// 		owner: sub; collection: collection(owner);
-	// 		owner: cross_from_sub;
-	// 	};
-	// 	let perms = (0..b).map(|k| PropertyKeyPermission {
-	// 		key: property_key(k as usize),
-	// 		permission: PropertyPermission {
-	// 			mutable: false,
-	// 			collection_admin: true,
-	// 			token_owner: true,
-	// 		},
-	// 	}).collect::<Vec<_>>();
-	// 	<Pallet<T>>::set_token_property_permissions(&collection, &owner, perms)?;
-	// 	let props = (0..b).map(|k| Property {
-	// 		key: property_key(k as usize),
-	// 		value: property_value(),
-	// 	}).collect::<Vec<_>>();
-	// 	let item = create_max_item(&collection, &owner, owner.clone())?;
-	// }: {<Pallet<T>>::set_token_properties(&collection, &owner, item, props.into_iter(), &Unlimited)?}
-
-	// load_token_properties {
-	// 	bench_init!{
-	// 		owner: sub; collection: collection(owner);
-	// 		owner: cross_from_sub;
-	// 	};
-
-	// 	let item = create_max_item(&collection, &owner, owner.clone())?;
-	// }: {
-	// 	pallet_common::BenchmarkPropertyWriter::<T>::load_token_properties(
-	// 		&collection,
-	// 		item,
-	// 	)
-	// }
-
-	// write_token_properties {
-	// 	let b in 0..MAX_PROPERTIES_PER_ITEM;
-	// 	bench_init!{
-	// 		owner: sub; collection: collection(owner);
-	// 		owner: cross_from_sub;
-	// 	};
+		Ok(())
+	}
 
-	// 	let perms = (0..b).map(|k| PropertyKeyPermission {
-	// 		key: property_key(k as usize),
-	// 		permission: PropertyPermission {
-	// 			mutable: false,
-	// 			collection_admin: true,
-	// 			token_owner: true,
-	// 		},
-	// 	}).collect::<Vec<_>>();
-	// 	<Pallet<T>>::set_token_property_permissions(&collection, &owner, perms)?;
-	// 	let props = (0..b).map(|k| Property {
-	// 		key: property_key(k as usize),
-	// 		value: property_value(),
-	// 	}).collect::<Vec<_>>();
-	// 	let item = create_max_item(&collection, &owner, owner.clone())?;
-
-	// 	let lazy_collection_info = pallet_common::BenchmarkPropertyWriter::<T>::load_collection_info(
-	// 		&collection,
-	// 		&owner,
-	// 	);
-	// }: {
-	// 	let mut property_writer = pallet_common::BenchmarkPropertyWriter::new(&collection, lazy_collection_info);
-
-	// 	property_writer.write_token_properties(
-	// 		item,
-	// 		props.into_iter(),
-	// 		crate::erc::ERC721TokenEvent::TokenChanged {
-	// 			token_id: item.into(),
-	// 		}
-	// 		.to_log(T::ContractAddress::get()),
-	// 	)?
-	// }
-
 	#[benchmark]
-	fn set_token_property_permissions(
-		b: Linear<0, MAX_PROPERTIES_PER_ITEM>,
-	) -> Result<(), BenchmarkError> {
+	fn load_token_properties() -> Result<(), BenchmarkError> {
 		bench_init! {
 			owner: sub; collection: collection(owner);
 			owner: cross_from_sub;
 		};
-		let perms = (0..b)
-			.map(|k| PropertyKeyPermission {
-				key: property_key(k as usize),
-				permission: PropertyPermission {
-					mutable: false,
-					collection_admin: false,
-					token_owner: false,
-				},
-			})
-			.collect::<Vec<_>>();
 
+		let item = create_max_item(&collection, &owner, owner.clone())?;
+
 		#[block]
 		{
-			<Pallet<T>>::set_token_property_permissions(&collection, &owner, perms)?;
+			pallet_common::BenchmarkPropertyWriter::<T>::load_token_properties(&collection, item);
 		}
 
 		Ok(())
 	}
 
 	#[benchmark]
-	fn set_token_properties(b: Linear<0, MAX_PROPERTIES_PER_ITEM>) -> Result<(), BenchmarkError> {
+	fn write_token_properties(b: Linear<0, MAX_PROPERTIES_PER_ITEM>) -> Result<(), BenchmarkError> {
 		bench_init! {
 			owner: sub; collection: collection(owner);
 			owner: cross_from_sub;
 		};
+
 		let perms = (0..b)
 			.map(|k| PropertyKeyPermission {
 				key: property_key(k as usize),
@@ -391,71 +267,29 @@
 			.collect::<Vec<_>>();
 		let item = create_max_item(&collection, &owner, owner.clone())?;
 
+		let lazy_collection_info =
+			pallet_common::BenchmarkPropertyWriter::<T>::load_collection_info(&collection, &owner);
+
 		#[block]
 		{
-			<Pallet<T>>::set_token_properties(
-				&collection,
-				&owner,
+			let mut property_writer =
+				pallet_common::BenchmarkPropertyWriter::new(&collection, lazy_collection_info);
+
+			property_writer.write_token_properties(
 				item,
 				props.into_iter(),
-				&Unlimited,
+				crate::erc::ERC721TokenEvent::TokenChanged {
+					token_id: item.into(),
+				}
+				.to_log(T::ContractAddress::get()),
 			)?;
 		}
 
 		Ok(())
 	}
 
-	// TODO:
 	#[benchmark]
-	fn init_token_properties(b: Linear<0, MAX_PROPERTIES_PER_ITEM>) -> Result<(), BenchmarkError> {
-		// bench_init! {
-		// 	owner: sub; collection: collection(owner);
-		// 	owner: cross_from_sub;
-		// };
-
-		// let perms = (0..b)
-		// 	.map(|k| PropertyKeyPermission {
-		// 		key: property_key(k as usize),
-		// 		permission: PropertyPermission {
-		// 			mutable: false,
-		// 			collection_admin: true,
-		// 			token_owner: true,
-		// 		},
-		// 	})
-		// 	.collect::<Vec<_>>();
-		// <Pallet<T>>::set_token_property_permissions(&collection, &owner, perms)?;
-		#[block]
-		{}
-		// let props = (0..b)
-		// 	.map(|k| Property {
-		// 		key: property_key(k as usize),
-		// 		value: property_value(),
-		// 	})
-		// 	.collect::<Vec<_>>();
-		// let item = create_max_item(&collection, &owner, owner.clone())?;
-
-		// let (is_collection_admin, property_permissions) =
-		// 	load_is_admin_and_property_permissions(&collection, &owner);
-		// #[block]
-		// {
-		// 	let mut property_writer =
-		// 		pallet_common::BenchmarkPropertyWriter::new(&collection, lazy_collection_info);
-
-		// 	property_writer.write_token_properties(
-		// 		item,
-		// 		props.into_iter(),
-		// 		crate::erc::ERC721TokenEvent::TokenChanged {
-		// 			token_id: item.into(),
-		// 		}
-		// 		.to_log(T::ContractAddress::get()),
-		// 	)?;
-		// }
-
-		Ok(())
-	}
-
-	#[benchmark]
-	fn delete_token_properties(
+	fn set_token_property_permissions(
 		b: Linear<0, MAX_PROPERTIES_PER_ITEM>,
 	) -> Result<(), BenchmarkError> {
 		bench_init! {
@@ -466,54 +300,16 @@
 			.map(|k| PropertyKeyPermission {
 				key: property_key(k as usize),
 				permission: PropertyPermission {
-					mutable: true,
-					collection_admin: true,
-					token_owner: true,
+					mutable: false,
+					collection_admin: false,
+					token_owner: false,
 				},
-			})
-			.collect::<Vec<_>>();
-		<Pallet<T>>::set_token_property_permissions(&collection, &owner, perms)?;
-		let props = (0..b)
-			.map(|k| Property {
-				key: property_key(k as usize),
-				value: property_value(),
 			})
 			.collect::<Vec<_>>();
-		let item = create_max_item(&collection, &owner, owner.clone())?;
-		<Pallet<T>>::set_token_properties(
-			&collection,
-			&owner,
-			item,
-			props.into_iter(),
-			&Unlimited,
-		)?;
-		let to_delete = (0..b).map(|k| property_key(k as usize)).collect::<Vec<_>>();
 
 		#[block]
 		{
-			<Pallet<T>>::delete_token_properties(
-				&collection,
-				&owner,
-				item,
-				to_delete.into_iter(),
-				&Unlimited,
-			)?;
-		}
-
-		Ok(())
-	}
-
-	#[benchmark]
-	fn token_owner() -> Result<(), BenchmarkError> {
-		bench_init! {
-			owner: sub; collection: collection(owner);
-			owner: cross_from_sub;
-		};
-		let item = create_max_item(&collection, &owner, owner.clone())?;
-
-		#[block]
-		{
-			collection.token_owner(item).unwrap();
+			<Pallet<T>>::set_token_property_permissions(&collection, &owner, perms)?;
 		}
 
 		Ok(())
modifiedpallets/nonfungible/src/common.rsdiffbeforeafterboth
after · pallets/nonfungible/src/common.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617use core::marker::PhantomData;1819use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight};20use pallet_common::{21	weights::WeightInfo as _, with_weight, write_token_properties_total_weight,22	CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions,23	SelfWeightOf as PalletCommonWeightOf,24};25use pallet_structure::Pallet as PalletStructure;26use sp_runtime::DispatchError;27use sp_std::{vec, vec::Vec};28use up_data_structs::{29	budget::Budget, CollectionId, CreateItemExData, Property, PropertyKey, PropertyKeyPermission,30	PropertyValue, TokenId, TokenOwnerError,31};3233use crate::{34	weights::WeightInfo, AccountBalance, Allowance, Config, CreateItemData, Error,35	NonfungibleHandle, Owned, Pallet, SelfWeightOf, TokenData, TokenProperties, TokensMinted,36};3738pub struct CommonWeights<T: Config>(PhantomData<T>);39impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {40	fn create_multiple_items_ex(data: &CreateItemExData<T::CrossAccountId>) -> Weight {41		match data {42			CreateItemExData::NFT(t) => mint_with_props_weight::<T>(43				<SelfWeightOf<T>>::create_multiple_items_ex(t.len() as u32),44				t.iter().map(|t| t.properties.len() as u32),45			),46			_ => Weight::zero(),47		}48	}4950	fn create_multiple_items(data: &[up_data_structs::CreateItemData]) -> Weight {51		mint_with_props_weight::<T>(52			<SelfWeightOf<T>>::create_multiple_items(data.len() as u32),53			data.iter().map(|t| match t {54				up_data_structs::CreateItemData::NFT(n) => n.properties.len() as u32,55				_ => 0,56			}),57		)58	}5960	fn burn_item() -> Weight {61		<SelfWeightOf<T>>::burn_item()62	}6364	fn set_collection_properties(amount: u32) -> Weight {65		<pallet_common::SelfWeightOf<T>>::set_collection_properties(amount)66	}6768	fn set_token_properties(amount: u32) -> Weight {69		write_token_properties_total_weight::<T, _>([amount].into_iter(), |amount| {70			<SelfWeightOf<T>>::load_token_properties()71				.saturating_add(<SelfWeightOf<T>>::write_token_properties(amount))72		})73	}7475	fn delete_token_properties(amount: u32) -> Weight {76		Self::set_token_properties(amount)77	}7879	fn set_token_property_permissions(amount: u32) -> Weight {80		<SelfWeightOf<T>>::set_token_property_permissions(amount)81	}8283	fn transfer() -> Weight {84		<SelfWeightOf<T>>::transfer_raw()85			.saturating_add(<PalletCommonWeightOf<T>>::check_accesslist().saturating_mul(2))86	}8788	fn approve() -> Weight {89		<SelfWeightOf<T>>::approve()90	}9192	fn approve_from() -> Weight {93		<SelfWeightOf<T>>::approve_from()94	}9596	fn transfer_from() -> Weight {97		Self::transfer().saturating_add(<SelfWeightOf<T>>::check_allowed_raw())98	}99100	fn burn_from() -> Weight {101		<SelfWeightOf<T>>::burn_from()102	}103104	fn set_allowance_for_all() -> Weight {105		<SelfWeightOf<T>>::set_allowance_for_all()106	}107108	fn force_repair_item() -> Weight {109		<SelfWeightOf<T>>::repair_item()110	}111}112113pub(crate) fn mint_with_props_weight<T: Config>(114	create_no_data_weight: Weight,115	tokens: impl Iterator<Item = u32> + Clone,116) -> Weight {117	create_no_data_weight.saturating_add(write_token_properties_total_weight::<T, _>(118		tokens,119		<SelfWeightOf<T>>::write_token_properties,120	))121}122123fn map_create_data<T: Config>(124	data: up_data_structs::CreateItemData,125	to: &T::CrossAccountId,126) -> Result<CreateItemData<T>, DispatchError> {127	match data {128		up_data_structs::CreateItemData::NFT(data) => Ok(CreateItemData::<T> {129			properties: data.properties,130			owner: to.clone(),131		}),132		_ => fail!(<Error<T>>::NotNonfungibleDataUsedToMintFungibleCollectionToken),133	}134}135136/// Implementation of `CommonCollectionOperations` for `NonfungibleHandle`. It wraps Nonfungible Pallete137/// methods and adds weight info.138impl<T: Config> CommonCollectionOperations<T> for NonfungibleHandle<T> {139	fn create_item(140		&self,141		sender: T::CrossAccountId,142		to: T::CrossAccountId,143		data: up_data_structs::CreateItemData,144		nesting_budget: &dyn Budget,145	) -> DispatchResultWithPostInfo {146		let weight = <CommonWeights<T>>::create_item(&data);147		with_weight(148			<Pallet<T>>::create_item(149				self,150				&sender,151				map_create_data::<T>(data, &to)?,152				nesting_budget,153			),154			weight,155		)156	}157158	fn create_multiple_items(159		&self,160		sender: T::CrossAccountId,161		to: T::CrossAccountId,162		data: Vec<up_data_structs::CreateItemData>,163		nesting_budget: &dyn Budget,164	) -> DispatchResultWithPostInfo {165		let weight = <CommonWeights<T>>::create_multiple_items(&data);166		let data = data167			.into_iter()168			.map(|d| map_create_data::<T>(d, &to))169			.collect::<Result<Vec<_>, DispatchError>>()?;170171		with_weight(172			<Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),173			weight,174		)175	}176177	fn create_multiple_items_ex(178		&self,179		sender: <T>::CrossAccountId,180		data: up_data_structs::CreateItemExData<<T>::CrossAccountId>,181		nesting_budget: &dyn Budget,182	) -> DispatchResultWithPostInfo {183		let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);184		let data = match data {185			up_data_structs::CreateItemExData::NFT(nft) => nft,186			_ => fail!(Error::<T>::NotNonfungibleDataUsedToMintFungibleCollectionToken),187		};188189		with_weight(190			<Pallet<T>>::create_multiple_items(self, &sender, data.into_inner(), nesting_budget),191			weight,192		)193	}194195	fn set_collection_properties(196		&self,197		sender: T::CrossAccountId,198		properties: Vec<Property>,199	) -> DispatchResultWithPostInfo {200		let weight = <CommonWeights<T>>::set_collection_properties(properties.len() as u32);201202		with_weight(203			<Pallet<T>>::set_collection_properties(self, &sender, properties),204			weight,205		)206	}207208	fn delete_collection_properties(209		&self,210		sender: &T::CrossAccountId,211		property_keys: Vec<PropertyKey>,212	) -> DispatchResultWithPostInfo {213		let weight = <CommonWeights<T>>::delete_collection_properties(property_keys.len() as u32);214215		with_weight(216			<Pallet<T>>::delete_collection_properties(self, sender, property_keys),217			weight,218		)219	}220221	fn set_token_properties(222		&self,223		sender: T::CrossAccountId,224		token_id: TokenId,225		properties: Vec<Property>,226		nesting_budget: &dyn Budget,227	) -> DispatchResultWithPostInfo {228		let weight = <CommonWeights<T>>::set_token_properties(properties.len() as u32);229230		with_weight(231			<Pallet<T>>::set_token_properties(232				self,233				&sender,234				token_id,235				properties.into_iter(),236				nesting_budget,237			),238			weight,239		)240	}241242	fn delete_token_properties(243		&self,244		sender: T::CrossAccountId,245		token_id: TokenId,246		property_keys: Vec<PropertyKey>,247		nesting_budget: &dyn Budget,248	) -> DispatchResultWithPostInfo {249		let weight = <CommonWeights<T>>::delete_token_properties(property_keys.len() as u32);250251		with_weight(252			<Pallet<T>>::delete_token_properties(253				self,254				&sender,255				token_id,256				property_keys.into_iter(),257				nesting_budget,258			),259			weight,260		)261	}262263	fn get_token_properties_raw(264		&self,265		token_id: TokenId,266	) -> Option<up_data_structs::TokenProperties> {267		<TokenProperties<T>>::get((self.id, token_id))268	}269270	fn set_token_properties_raw(&self, token_id: TokenId, map: up_data_structs::TokenProperties) {271		<TokenProperties<T>>::insert((self.id, token_id), map)272	}273274	fn set_token_property_permissions(275		&self,276		sender: &T::CrossAccountId,277		property_permissions: Vec<PropertyKeyPermission>,278	) -> DispatchResultWithPostInfo {279		let weight =280			<CommonWeights<T>>::set_token_property_permissions(property_permissions.len() as u32);281282		with_weight(283			<Pallet<T>>::set_token_property_permissions(self, sender, property_permissions),284			weight,285		)286	}287288	fn burn_item(289		&self,290		sender: T::CrossAccountId,291		token: TokenId,292		amount: u128,293	) -> DispatchResultWithPostInfo {294		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);295		if amount == 1 {296			with_weight(297				<Pallet<T>>::burn(self, &sender, token),298				<CommonWeights<T>>::burn_item(),299			)300		} else {301			<Pallet<T>>::check_token_immediate_ownership(self, token, &sender)?;302			Ok(().into())303		}304	}305306	fn transfer(307		&self,308		from: T::CrossAccountId,309		to: T::CrossAccountId,310		token: TokenId,311		amount: u128,312		nesting_budget: &dyn Budget,313	) -> DispatchResultWithPostInfo {314		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);315		if amount == 1 {316			<Pallet<T>>::transfer(self, &from, &to, token, nesting_budget)317		} else {318			<Pallet<T>>::check_token_immediate_ownership(self, token, &from)?;319			Ok(().into())320		}321	}322323	fn approve(324		&self,325		sender: T::CrossAccountId,326		spender: T::CrossAccountId,327		token: TokenId,328		amount: u128,329	) -> DispatchResultWithPostInfo {330		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);331332		with_weight(333			if amount == 1 {334				<Pallet<T>>::set_allowance(self, &sender, token, Some(&spender))335			} else {336				<Pallet<T>>::set_allowance(self, &sender, token, None)337			},338			<CommonWeights<T>>::approve(),339		)340	}341342	fn approve_from(343		&self,344		sender: T::CrossAccountId,345		from: T::CrossAccountId,346		to: T::CrossAccountId,347		token: TokenId,348		amount: u128,349	) -> DispatchResultWithPostInfo {350		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);351352		with_weight(353			if amount == 1 {354				<Pallet<T>>::set_allowance_from(self, &sender, &from, token, Some(&to))355			} else {356				<Pallet<T>>::set_allowance_from(self, &sender, &from, token, None)357			},358			<CommonWeights<T>>::approve_from(),359		)360	}361362	fn transfer_from(363		&self,364		sender: T::CrossAccountId,365		from: T::CrossAccountId,366		to: T::CrossAccountId,367		token: TokenId,368		amount: u128,369		nesting_budget: &dyn Budget,370	) -> DispatchResultWithPostInfo {371		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);372373		if amount == 1 {374			<Pallet<T>>::transfer_from(self, &sender, &from, &to, token, nesting_budget)375		} else {376			<Pallet<T>>::check_allowed(self, &sender, &from, token, nesting_budget)?;377378			Ok(().into())379		}380	}381382	fn burn_from(383		&self,384		sender: T::CrossAccountId,385		from: T::CrossAccountId,386		token: TokenId,387		amount: u128,388		nesting_budget: &dyn Budget,389	) -> DispatchResultWithPostInfo {390		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);391392		if amount == 1 {393			with_weight(394				<Pallet<T>>::burn_from(self, &sender, &from, token, nesting_budget),395				<CommonWeights<T>>::burn_from(),396			)397		} else {398			<Pallet<T>>::check_allowed(self, &sender, &from, token, nesting_budget)?;399400			Ok(().into())401		}402	}403404	fn check_nesting(405		&self,406		sender: T::CrossAccountId,407		from: (CollectionId, TokenId),408		under: TokenId,409		nesting_budget: &dyn Budget,410	) -> sp_runtime::DispatchResult {411		<Pallet<T>>::check_nesting(self, sender, from, under, nesting_budget)412	}413414	fn nest(&self, under: TokenId, to_nest: (CollectionId, TokenId)) {415		<Pallet<T>>::nest((self.id, under), to_nest);416	}417418	fn unnest(&self, under: TokenId, to_unnest: (CollectionId, TokenId)) {419		<Pallet<T>>::unnest((self.id, under), to_unnest);420	}421422	fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {423		<Owned<T>>::iter_prefix((self.id, account))424			.map(|(id, _)| id)425			.collect()426	}427428	fn collection_tokens(&self) -> Vec<TokenId> {429		<TokenData<T>>::iter_prefix((self.id,))430			.map(|(id, _)| id)431			.collect()432	}433434	fn token_exists(&self, token: TokenId) -> bool {435		<Pallet<T>>::token_exists(self, token)436	}437438	fn last_token_id(&self) -> TokenId {439		TokenId(<TokensMinted<T>>::get(self.id))440	}441442	fn token_owner(&self, token: TokenId) -> Result<T::CrossAccountId, TokenOwnerError> {443		<TokenData<T>>::get((self.id, token))444			.map(|t| t.owner)445			.ok_or(TokenOwnerError::NotFound)446	}447448	fn check_token_indirect_owner(449		&self,450		token: TokenId,451		maybe_owner: &T::CrossAccountId,452		nesting_budget: &dyn Budget,453	) -> Result<bool, DispatchError> {454		<PalletStructure<T>>::check_indirectly_owned(455			maybe_owner.clone(),456			self.id,457			token,458			None,459			nesting_budget,460		)461	}462463	/// Returns token owners.464	fn token_owners(&self, token: TokenId) -> Vec<T::CrossAccountId> {465		self.token_owner(token).map_or_else(|_| vec![], |t| vec![t])466	}467468	fn token_property(&self, token_id: TokenId, key: &PropertyKey) -> Option<PropertyValue> {469		<Pallet<T>>::token_properties((self.id, token_id))?470			.get(key)471			.cloned()472	}473474	fn token_properties(&self, token_id: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property> {475		let Some(properties) = <Pallet<T>>::token_properties((self.id, token_id)) else {476			return vec![];477		};478479		keys.map(|keys| {480			keys.into_iter()481				.filter_map(|key| {482					properties.get(&key).map(|value| Property {483						key,484						value: value.clone(),485					})486				})487				.collect()488		})489		.unwrap_or_else(|| {490			properties491				.into_iter()492				.map(|(key, value)| Property { key, value })493				.collect()494		})495	}496497	fn total_supply(&self) -> u32 {498		<Pallet<T>>::total_supply(self)499	}500501	fn account_balance(&self, account: T::CrossAccountId) -> u32 {502		<AccountBalance<T>>::get((self.id, account))503	}504505	fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {506		if <TokenData<T>>::get((self.id, token))507			.map(|a| a.owner == account)508			.unwrap_or(false)509		{510			1511		} else {512			0513		}514	}515516	fn allowance(517		&self,518		sender: T::CrossAccountId,519		spender: T::CrossAccountId,520		token: TokenId,521	) -> u128 {522		if <TokenData<T>>::get((self.id, token))523			.map(|a| a.owner != sender)524			.unwrap_or(true)525		{526			0527		} else if <Allowance<T>>::get((self.id, token)) == Some(spender) {528			1529		} else {530			0531		}532	}533534	fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>> {535		None536	}537538	fn total_pieces(&self, token: TokenId) -> Option<u128> {539		if <TokenData<T>>::contains_key((self.id, token)) {540			Some(1)541		} else {542			None543		}544	}545546	fn set_allowance_for_all(547		&self,548		owner: T::CrossAccountId,549		operator: T::CrossAccountId,550		approve: bool,551	) -> DispatchResultWithPostInfo {552		with_weight(553			<Pallet<T>>::set_allowance_for_all(self, &owner, &operator, approve),554			<CommonWeights<T>>::set_allowance_for_all(),555		)556	}557558	fn allowance_for_all(&self, owner: T::CrossAccountId, operator: T::CrossAccountId) -> bool {559		<Pallet<T>>::allowance_for_all(self, &owner, &operator)560	}561562	fn repair_item(&self, token: TokenId) -> DispatchResultWithPostInfo {563		with_weight(564			<Pallet<T>>::repair_item(self, token),565			<CommonWeights<T>>::force_repair_item(),566		)567	}568}
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -49,8 +49,10 @@
 };
 
 use crate::{
-	common::CommonWeights, weights::WeightInfo, AccountBalance, Config, CreateItemData,
-	NonfungibleHandle, Pallet, SelfWeightOf, TokenData, TokenProperties, TokensMinted,
+	common::{mint_with_props_weight, CommonWeights},
+	weights::WeightInfo,
+	AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, SelfWeightOf, TokenData,
+	TokenProperties, TokensMinted,
 };
 
 /// Nft events.
@@ -620,7 +622,7 @@
 	/// @param tokenUri Token URI that would be stored in the NFT properties
 	/// @return uint256 The id of the newly minted token
 	#[solidity(rename_selector = "mintWithTokenURI")]
-	#[weight(<SelfWeightOf<T>>::create_item() + <SelfWeightOf<T>>::set_token_properties(1))]
+	#[weight(mint_with_props_weight::<T>(<SelfWeightOf<T>>::create_item(), [1].into_iter()))]
 	fn mint_with_token_uri(
 		&mut self,
 		caller: Caller,
@@ -642,7 +644,7 @@
 	/// @param tokenId ID of the minted NFT
 	/// @param tokenUri Token URI that would be stored in the NFT properties
 	#[solidity(hide, rename_selector = "mintWithTokenURI")]
-	#[weight(<SelfWeightOf<T>>::create_item() + <SelfWeightOf<T>>::set_token_properties(1))]
+	#[weight(mint_with_props_weight::<T>(<SelfWeightOf<T>>::create_item(), [1].into_iter()))]
 	fn mint_with_token_uri_check_id(
 		&mut self,
 		caller: Caller,
@@ -974,7 +976,12 @@
 
 	/// @notice Function to mint a token.
 	/// @param data Array of pairs of token owner and token's properties for minted token
-	#[weight(<SelfWeightOf<T>>::create_multiple_items(data.len() as u32) + <SelfWeightOf<T>>::set_token_properties(data.len() as u32))]
+	#[weight(
+		mint_with_props_weight::<T>(
+			<SelfWeightOf<T>>::create_multiple_items_ex(data.len() as u32),
+			data.iter().map(|d| d.properties.len() as u32),
+		)
+	)]
 	fn mint_bulk_cross(&mut self, caller: Caller, data: Vec<MintTokenData>) -> Result<bool> {
 		let caller = T::CrossAccountId::from_eth(caller);
 
@@ -1008,7 +1015,12 @@
 	/// @param to The new owner
 	/// @param tokens array of pairs of token ID and token URI for minted tokens
 	#[solidity(hide, rename_selector = "mintBulkWithTokenURI")]
-	#[weight(<SelfWeightOf<T>>::create_multiple_items(tokens.len() as u32) + <SelfWeightOf<T>>::set_token_properties(tokens.len() as u32))]
+	#[weight(
+		mint_with_props_weight::<T>(
+			<SelfWeightOf<T>>::create_multiple_items(tokens.len() as u32),
+			tokens.iter().map(|_| 1),
+		)
+	)]
 	fn mint_bulk_with_token_uri(
 		&mut self,
 		caller: Caller,
@@ -1056,7 +1068,7 @@
 	/// @param to The new owner crossAccountId
 	/// @param properties Properties of minted token
 	/// @return uint256 The id of the newly minted token
-	#[weight(<SelfWeightOf<T>>::create_item() + <SelfWeightOf<T>>::set_token_properties(properties.len() as u32))]
+	#[weight(mint_with_props_weight::<T>(<SelfWeightOf<T>>::create_item(), [properties.len() as u32].into_iter()))]
 	fn mint_cross(
 		&mut self,
 		caller: Caller,
modifiedpallets/refungible/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/refungible/src/benchmarking.rs
+++ b/pallets/refungible/src/benchmarking.rs
@@ -421,114 +421,30 @@
 		Ok(())
 	}
 
-	// set_token_properties {
-	// 	let b in 0..MAX_PROPERTIES_PER_ITEM;
-	// 	bench_init!{
-	// 		owner: sub; collection: collection(owner);
-	// 		owner: cross_from_sub;
-	// 	};
-	// 	let perms = (0..b).map(|k| PropertyKeyPermission {
-	// 		key: property_key(k as usize),
-	// 		permission: PropertyPermission {
-	// 			mutable: false,
-	// 			collection_admin: true,
-	// 			token_owner: true,
-	// 		},
-	// 	}).collect::<Vec<_>>();
-	// 	<Pallet<T>>::set_token_property_permissions(&collection, &owner, perms)?;
-	// 	let props = (0..b).map(|k| Property {
-	// 		key: property_key(k as usize),
-	// 		value: property_value(),
-	// 	}).collect::<Vec<_>>();
-	// 	let item = create_max_item(&collection, &owner, [(owner.clone(), 200)])?;
-	// }: {<Pallet<T>>::set_token_properties(&collection, &owner, item, props.into_iter(), &Unlimited)?}
-
-	// load_token_properties {
-	// 	bench_init!{
-	// 		owner: sub; collection: collection(owner);
-	// 		owner: cross_from_sub;
-	// 	};
-
-	// 	let item = create_max_item(&collection, &owner, [(owner.clone(), 200)])?;
-	// }: {
-	// 	pallet_common::BenchmarkPropertyWriter::<T>::load_token_properties(
-	// 		&collection,
-	// 		item,
-	// 	)
-	// }
-
-	// write_token_properties {
-	// 	let b in 0..MAX_PROPERTIES_PER_ITEM;
-	// 	bench_init!{
-	// 		owner: sub; collection: collection(owner);
-	// 		owner: cross_from_sub;
-	// 	};
-
-	// 	let perms = (0..b).map(|k| PropertyKeyPermission {
-	// 		key: property_key(k as usize),
-	// 		permission: PropertyPermission {
-	// 			mutable: false,
-	// 			collection_admin: true,
-	// 			token_owner: true,
-	// 		},
-	// 	}).collect::<Vec<_>>();
-	// 	<Pallet<T>>::set_token_property_permissions(&collection, &owner, perms)?;
-	// 	let props = (0..b).map(|k| Property {
-	// 		key: property_key(k as usize),
-	// 		value: property_value(),
-	// 	}).collect::<Vec<_>>();
-	// 	let item = create_max_item(&collection, &owner, [(owner.clone(), 200)])?;
-
-	// 	let lazy_collection_info = pallet_common::BenchmarkPropertyWriter::<T>::load_collection_info(
-	// 		&collection,
-	// 		&owner,
-	// 	);
-	// }: {
-	// 	let mut property_writer = pallet_common::BenchmarkPropertyWriter::new(&collection, lazy_collection_info);
-
-	// 	property_writer.write_token_properties(
-	// 		item,
-	// 		props.into_iter(),
-	// 		crate::erc::ERC721TokenEvent::TokenChanged {
-	// 			token_id: item.into(),
-	// 		}
-	// 		.to_log(T::ContractAddress::get()),
-	// 	)?
-	// }
-
 	#[benchmark]
-	fn set_token_property_permissions(
-		b: Linear<0, MAX_PROPERTIES_PER_ITEM>,
-	) -> Result<(), BenchmarkError> {
+	fn load_token_properties() -> Result<(), BenchmarkError> {
 		bench_init! {
 			owner: sub; collection: collection(owner);
 			owner: cross_from_sub;
 		};
-		let perms = (0..b)
-			.map(|k| PropertyKeyPermission {
-				key: property_key(k as usize),
-				permission: PropertyPermission {
-					mutable: false,
-					collection_admin: false,
-					token_owner: false,
-				},
-			})
-			.collect::<Vec<_>>();
 
+		let item = create_max_item(&collection, &owner, [(owner.clone(), 200)])?;
+
 		#[block]
 		{
-			<Pallet<T>>::set_token_property_permissions(&collection, &owner, perms)?;
+			pallet_common::BenchmarkPropertyWriter::<T>::load_token_properties(&collection, item);
 		}
 
 		Ok(())
 	}
 
 	#[benchmark]
-	fn set_token_properties(b: Linear<0, MAX_PROPERTIES_PER_ITEM>) -> Result<(), BenchmarkError> {
+	fn write_token_properties(b: Linear<0, MAX_PROPERTIES_PER_ITEM>) -> Result<(), BenchmarkError> {
 		bench_init! {
 			owner: sub; collection: collection(owner);
 			owner: cross_from_sub;
 		};
+
 		let perms = (0..b)
 			.map(|k| PropertyKeyPermission {
 				key: property_key(k as usize),
@@ -548,73 +464,29 @@
 			.collect::<Vec<_>>();
 		let item = create_max_item(&collection, &owner, [(owner.clone(), 200)])?;
 
+		let lazy_collection_info =
+			pallet_common::BenchmarkPropertyWriter::<T>::load_collection_info(&collection, &owner);
+
 		#[block]
 		{
-			<Pallet<T>>::set_token_properties(
-				&collection,
-				&owner,
+			let mut property_writer =
+				pallet_common::BenchmarkPropertyWriter::new(&collection, lazy_collection_info);
+
+			property_writer.write_token_properties(
 				item,
 				props.into_iter(),
-				&Unlimited,
+				crate::erc::ERC721TokenEvent::TokenChanged {
+					token_id: item.into(),
+				}
+				.to_log(T::ContractAddress::get()),
 			)?;
 		}
 
 		Ok(())
 	}
 
-	// TODO:
 	#[benchmark]
-	fn init_token_properties(b: Linear<0, MAX_PROPERTIES_PER_ITEM>) -> Result<(), BenchmarkError> {
-		// bench_init! {
-		// 	owner: sub; collection: collection(owner);
-		// 	owner: cross_from_sub;
-		// };
-
-		// let perms = (0..b)
-		// 	.map(|k| PropertyKeyPermission {
-		// 		key: property_key(k as usize),
-		// 		permission: PropertyPermission {
-		// 			mutable: false,
-		// 			collection_admin: true,
-		// 			token_owner: true,
-		// 		},
-		// 	})
-		// 	.collect::<Vec<_>>();
-		// <Pallet<T>>::set_token_property_permissions(&collection, &owner, perms)?;
-
-		#[block]
-		{}
-		// let props = (0..b).map(|k| Property {
-		// 	key: property_key(k as usize),
-		// 	value: property_value(),
-		// }).collect::<Vec<_>>();
-		// let item = create_max_item(&collection, &owner, [(owner.clone(), 200)])?;
-
-		// let (is_collection_admin, property_permissions) = load_is_admin_and_property_permissions(&collection, &owner)
-		// let mut property_writer = pallet_common::collection_info_loaded_property_writer(
-		// 	&collection,
-		// 	is_collection_admin,
-		// 	property_permissions,
-		// );
-
-		// #[block]
-		// {
-		// 	property_writer.write_token_properties(
-		// 		true,
-		// 		item,
-		// 		props.into_iter(),
-		// 		crate::erc::ERC721TokenEvent::TokenChanged {
-		// 			token_id: item.into(),
-		// 		}
-		// 		.to_log(T::ContractAddress::get()),
-		// 	)?;
-		// }
-
-		Ok(())
-	}
-
-	#[benchmark]
-	fn delete_token_properties(
+	fn set_token_property_permissions(
 		b: Linear<0, MAX_PROPERTIES_PER_ITEM>,
 	) -> Result<(), BenchmarkError> {
 		bench_init! {
@@ -625,38 +497,16 @@
 			.map(|k| PropertyKeyPermission {
 				key: property_key(k as usize),
 				permission: PropertyPermission {
-					mutable: true,
-					collection_admin: true,
-					token_owner: true,
+					mutable: false,
+					collection_admin: false,
+					token_owner: false,
 				},
-			})
-			.collect::<Vec<_>>();
-		<Pallet<T>>::set_token_property_permissions(&collection, &owner, perms)?;
-		let props = (0..b)
-			.map(|k| Property {
-				key: property_key(k as usize),
-				value: property_value(),
 			})
 			.collect::<Vec<_>>();
-		let item = create_max_item(&collection, &owner, [(owner.clone(), 200)])?;
-		<Pallet<T>>::set_token_properties(
-			&collection,
-			&owner,
-			item,
-			props.into_iter(),
-			&Unlimited,
-		)?;
-		let to_delete = (0..b).map(|k| property_key(k as usize)).collect::<Vec<_>>();
 
 		#[block]
 		{
-			<Pallet<T>>::delete_token_properties(
-				&collection,
-				&owner,
-				item,
-				to_delete.into_iter(),
-				&Unlimited,
-			)?;
+			<Pallet<T>>::set_token_property_permissions(&collection, &owner, perms)?;
 		}
 
 		Ok(())
@@ -673,22 +523,6 @@
 		#[block]
 		{
 			<Pallet<T>>::repartition(&collection, &owner, item, 200)?;
-		}
-
-		Ok(())
-	}
-
-	#[benchmark]
-	fn token_owner() -> Result<(), BenchmarkError> {
-		bench_init! {
-			owner: sub; collection: collection(owner);
-			sender: cross_from_sub(owner); owner: cross_sub;
-		};
-		let item = create_max_item(&collection, &sender, [(owner, 100)])?;
-
-		#[block]
-		{
-			<Pallet<T>>::token_owner(collection.id, item).unwrap();
 		}
 
 		Ok(())
modifiedpallets/refungible/src/common.rsdiffbeforeafterboth
--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -47,35 +47,27 @@
 pub struct CommonWeights<T: Config>(PhantomData<T>);
 impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {
 	fn create_multiple_items(data: &[up_data_structs::CreateItemData]) -> Weight {
-		<SelfWeightOf<T>>::create_multiple_items(data.len() as u32).saturating_add(
-			write_token_properties_total_weight::<T, _>(
-				data.iter().map(|data| match data {
-					up_data_structs::CreateItemData::ReFungible(rft_data) => {
-						rft_data.properties.len() as u32
-					}
-					_ => 0,
-				}),
-				<SelfWeightOf<T>>::write_token_properties,
-			),
+		mint_with_props_weight::<T>(
+			<SelfWeightOf<T>>::create_multiple_items(data.len() as u32),
+			data.iter().map(|data| match data {
+				up_data_structs::CreateItemData::ReFungible(rft_data) => {
+					rft_data.properties.len() as u32
+				}
+				_ => 0,
+			}),
 		)
 	}
 
 	fn create_multiple_items_ex(call: &CreateItemExData<T::CrossAccountId>) -> Weight {
 		match call {
-			CreateItemExData::RefungibleMultipleOwners(i) => {
-				<SelfWeightOf<T>>::create_multiple_items_ex_multiple_owners(i.users.len() as u32)
-					.saturating_add(write_token_properties_total_weight::<T, _>(
-						[i.properties.len() as u32].into_iter(),
-						<SelfWeightOf<T>>::write_token_properties,
-					))
-			}
-			CreateItemExData::RefungibleMultipleItems(i) => {
-				<SelfWeightOf<T>>::create_multiple_items_ex_multiple_items(i.len() as u32)
-					.saturating_add(write_token_properties_total_weight::<T, _>(
-						i.iter().map(|d| d.properties.len() as u32),
-						<SelfWeightOf<T>>::write_token_properties,
-					))
-			}
+			CreateItemExData::RefungibleMultipleOwners(i) => mint_with_props_weight::<T>(
+				<SelfWeightOf<T>>::create_multiple_items_ex_multiple_owners(i.users.len() as u32),
+				[i.properties.len() as u32].into_iter(),
+			),
+			CreateItemExData::RefungibleMultipleItems(i) => mint_with_props_weight::<T>(
+				<SelfWeightOf<T>>::create_multiple_items_ex_multiple_items(i.len() as u32),
+				i.iter().map(|d| d.properties.len() as u32),
+			),
 			_ => Weight::zero(),
 		}
 	}
@@ -138,6 +130,16 @@
 	}
 }
 
+pub(crate) fn mint_with_props_weight<T: Config>(
+	create_no_data_weight: Weight,
+	tokens: impl Iterator<Item = u32> + Clone,
+) -> Weight {
+	create_no_data_weight.saturating_add(write_token_properties_total_weight::<T, _>(
+		tokens,
+		<SelfWeightOf<T>>::write_token_properties,
+	))
+}
+
 fn map_create_data<T: Config>(
 	data: up_data_structs::CreateItemData,
 	to: &T::CrossAccountId,
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -50,8 +50,10 @@
 };
 
 use crate::{
-	common::CommonWeights, weights::WeightInfo, AccountBalance, Balance, Config, CreateItemData,
-	Pallet, RefungibleHandle, SelfWeightOf, TokenProperties, TokensMinted, TotalSupply,
+	common::{mint_with_props_weight, CommonWeights},
+	weights::WeightInfo,
+	AccountBalance, Balance, Config, CreateItemData, Pallet, RefungibleHandle, SelfWeightOf,
+	TokenProperties, TokensMinted, TotalSupply,
 };
 
 frontier_contract! {
@@ -661,7 +663,7 @@
 	/// @param tokenUri Token URI that would be stored in the NFT properties
 	/// @return uint256 The id of the newly minted token
 	#[solidity(rename_selector = "mintWithTokenURI")]
-	#[weight(<SelfWeightOf<T>>::create_item() + <SelfWeightOf<T>>::set_token_properties(1))]
+	#[weight(mint_with_props_weight::<T>(<SelfWeightOf<T>>::create_item(), [1].into_iter()))]
 	fn mint_with_token_uri(
 		&mut self,
 		caller: Caller,
@@ -683,7 +685,7 @@
 	/// @param tokenId ID of the minted RFT
 	/// @param tokenUri Token URI that would be stored in the RFT properties
 	#[solidity(hide, rename_selector = "mintWithTokenURI")]
-	#[weight(<SelfWeightOf<T>>::create_item() + <SelfWeightOf<T>>::set_token_properties(1))]
+	#[weight(mint_with_props_weight::<T>(<SelfWeightOf<T>>::create_item(), [1].into_iter()))]
 	fn mint_with_token_uri_check_id(
 		&mut self,
 		caller: Caller,
@@ -1052,22 +1054,26 @@
 	}
 
 	/// @notice Function to mint a token.
-	/// @param tokenProperties Properties of minted token
-	#[weight(if token_properties.len() == 1 {
-		<SelfWeightOf<T>>::create_multiple_items_ex_multiple_owners(token_properties.iter().next().unwrap().owners.len() as u32)
+	/// @param tokensData Data of minted token(s)
+	#[weight(if tokens_data.len() == 1 {
+		let token_data = tokens_data.first().unwrap();
+
+		mint_with_props_weight::<T>(
+			<SelfWeightOf<T>>::create_multiple_items_ex_multiple_owners(token_data.owners.len() as u32),
+			[token_data.properties.len() as u32].into_iter(),
+		)
 	} else {
-		<SelfWeightOf<T>>::create_multiple_items_ex_multiple_items(token_properties.len() as u32)
-	} + <SelfWeightOf<T>>::set_token_properties(token_properties.len() as u32))]
-	fn mint_bulk_cross(
-		&mut self,
-		caller: Caller,
-		token_properties: Vec<MintTokenData>,
-	) -> Result<bool> {
+		mint_with_props_weight::<T>(
+			<SelfWeightOf<T>>::create_multiple_items_ex_multiple_items(tokens_data.len() as u32),
+			tokens_data.iter().map(|d| d.properties.len() as u32),
+		)
+	})]
+	fn mint_bulk_cross(&mut self, caller: Caller, tokens_data: Vec<MintTokenData>) -> Result<bool> {
 		let caller = T::CrossAccountId::from_eth(caller);
-		let has_multiple_tokens = token_properties.len() > 1;
+		let has_multiple_tokens = tokens_data.len() > 1;
 
-		let mut create_rft_data = Vec::with_capacity(token_properties.len());
-		for MintTokenData { owners, properties } in token_properties {
+		let mut create_rft_data = Vec::with_capacity(tokens_data.len());
+		for MintTokenData { owners, properties } in tokens_data {
 			let has_multiple_owners = owners.len() > 1;
 			if has_multiple_tokens & has_multiple_owners {
 				return Err(
@@ -1108,7 +1114,12 @@
 	/// @param to The new owner
 	/// @param tokens array of pairs of token ID and token URI for minted tokens
 	#[solidity(hide, rename_selector = "mintBulkWithTokenURI")]
-	#[weight(<SelfWeightOf<T>>::create_multiple_items(tokens.len() as u32) + <SelfWeightOf<T>>::set_token_properties(tokens.len() as u32))]
+	#[weight(
+		mint_with_props_weight::<T>(
+			<SelfWeightOf<T>>::create_multiple_items(tokens.len() as u32),
+			tokens.iter().map(|_| 1),
+		)
+	)]
 	fn mint_bulk_with_token_uri(
 		&mut self,
 		caller: Caller,
@@ -1162,7 +1173,7 @@
 	/// @param to The new owner crossAccountId
 	/// @param properties Properties of minted token
 	/// @return uint256 The id of the newly minted token
-	#[weight(<SelfWeightOf<T>>::create_item() + <SelfWeightOf<T>>::set_token_properties(properties.len() as u32))]
+	#[weight(mint_with_props_weight::<T>(<SelfWeightOf<T>>::create_item(), [properties.len() as u32].into_iter()))]
 	fn mint_cross(
 		&mut self,
 		caller: Caller,