git.delta.rocks / unique-network / refs/commits / 940b0a339ab0

difftreelog

fix clippy warnings

Grigoriy Simonov2023-06-05parent: #e7cba9a.patch.diff
in: master

36 files changed

modifiednode/cli/src/chain_spec.rsdiffbeforeafterboth
--- a/node/cli/src/chain_spec.rs
+++ b/node/cli/src/chain_spec.rs
@@ -110,7 +110,7 @@
 
 /// Helper function to generate a crypto pair from seed
 pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
-	TPublic::Pair::from_string(&format!("//{}", seed), None)
+	TPublic::Pair::from_string(&format!("//{seed}"), None)
 		.expect("static values are valid; qed")
 		.public()
 }
modifiednode/cli/src/command.rsdiffbeforeafterboth
--- a/node/cli/src/command.rs
+++ b/node/cli/src/command.rs
@@ -83,7 +83,7 @@
 		"" | "local" => Box::new(chain_spec::local_testnet_config()),
 		path => {
 			let path = std::path::PathBuf::from(path);
-			let chain_spec = Box::new(chain_spec::OpalChainSpec::from_json_file(path.clone())?)
+			let chain_spec = Box::new(chain_spec::OpalChainSpec::from_json_file(path)?)
 				as Box<dyn sc_service::ChainSpec>;
 
 			match chain_spec.runtime_id() {
@@ -352,7 +352,7 @@
 					&polkadot_cli,
 					config.tokio_handle.clone(),
 				)
-				.map_err(|err| format!("Relay chain argument error: {}", err))?;
+				.map_err(|err| format!("Relay chain argument error: {err}"))?;
 
 				cmd.run(config, polkadot_config)
 			})
@@ -464,7 +464,7 @@
 			runner.run_node_until_exit(|config| async move {
 				let hwbench = if !cli.no_hardware_benchmarks {
 					config.database.path().map(|database_path| {
-						let _ = std::fs::create_dir_all(&database_path);
+						let _ = std::fs::create_dir_all(database_path);
 						sc_sysinfo::gather_hwbench(Some(database_path))
 					})
 				} else {
@@ -513,7 +513,7 @@
 				let state_version =
 					RelayChainCli::native_runtime_version(&config.chain_spec).state_version();
 				let block: Block = generate_genesis_block(&*config.chain_spec, state_version)
-					.map_err(|e| format!("{:?}", e))?;
+					.map_err(|e| format!("{e:?}"))?;
 				let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode()));
 				let genesis_hash = format!("0x{:?}", HexDisplay::from(&block.header().hash().0));
 
@@ -522,7 +522,7 @@
 					&polkadot_cli,
 					config.tokio_handle.clone(),
 				)
-				.map_err(|err| format!("Relay chain argument error: {}", err))?;
+				.map_err(|err| format!("Relay chain argument error: {err}"))?;
 
 				info!("Parachain id: {:?}", para_id);
 				info!("Parachain Account: {}", parachain_account);
modifiednode/cli/src/service.rsdiffbeforeafterboth
--- a/node/cli/src/service.rs
+++ b/node/cli/src/service.rs
@@ -698,7 +698,7 @@
 {
 	let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;
 
-	let block_import = ParachainBlockImport::new(client.clone(), backend.clone());
+	let block_import = ParachainBlockImport::new(client.clone(), backend);
 
 	cumulus_client_consensus_aura::import_queue::<
 		sp_consensus_aura::sr25519::AuthorityPair,
@@ -709,7 +709,7 @@
 		_,
 	>(cumulus_client_consensus_aura::ImportQueueParams {
 		block_import,
-		client: client.clone(),
+		client,
 		create_inherent_data_providers: move |_, _| async move {
 			let time = sp_timestamp::InherentDataProvider::from_system_time();
 
@@ -787,7 +787,7 @@
 				telemetry.clone(),
 			);
 
-			let block_import = ParachainBlockImport::new(client.clone(), backend.clone());
+			let block_import = ParachainBlockImport::new(client.clone(), backend);
 
 			Ok(AuraConsensus::build::<
 				sp_consensus_aura::sr25519::AuthorityPair,
@@ -864,7 +864,7 @@
 	ExecutorDispatch: NativeExecutionDispatch + 'static,
 {
 	Ok(sc_consensus_manual_seal::import_queue(
-		Box::new(client.clone()),
+		Box::new(client),
 		&task_manager.spawn_essential_handle(),
 		config.prometheus_registry(),
 	))
@@ -956,7 +956,7 @@
 
 	let collator = config.role.is_authority();
 
-	let select_chain = maybe_select_chain.clone();
+	let select_chain = maybe_select_chain;
 
 	if collator {
 		let block_import =
modifiednode/rpc/src/lib.rsdiffbeforeafterboth
--- a/node/rpc/src/lib.rs
+++ b/node/rpc/src/lib.rs
@@ -289,7 +289,7 @@
 	io.merge(
 		Net::new(
 			client.clone(),
-			network.clone(),
+			network,
 			// Whether to format the `peer_count` response as Hex (default) or not.
 			true,
 		)
modifiedpallets/app-promotion/src/lib.rsdiffbeforeafterboth
--- a/pallets/app-promotion/src/lib.rs
+++ b/pallets/app-promotion/src/lib.rs
@@ -296,7 +296,7 @@
 
 			if !block_pending.is_empty() {
 				block_pending.into_iter().for_each(|(staker, amount)| {
-					Self::get_frozen_balance(&staker).map(|b| {
+					if let Some(b) = Self::get_frozen_balance(&staker) {
 						let new_state = b.checked_sub(&amount).unwrap_or_default();
 
 						// In this case, setting a new state for the frozen funds cannot fail
@@ -305,7 +305,7 @@
 						// that we cannot (in the current implementation) unfreeze more funds
 						// than were originally frozen by the pallet. Either way, `on_initialize()` cannot fail.
 						Self::set_freeze_unchecked(&staker, new_state);
-					});
+					};
 				});
 			}
 
@@ -598,8 +598,8 @@
 			// this value is set for the stakers to whom the recalculation will be performed
 			let next_recalc_block = current_recalc_block + config.recalculation_interval;
 
-			let mut storage_iterator = Self::get_next_calculated_key()
-				.map_or(Staked::<T>::iter(), |key| Staked::<T>::iter_from(key));
+			let storage_iterator =
+				Self::get_next_calculated_key().map_or(Staked::<T>::iter(), Staked::<T>::iter_from);
 
 			PreviousCalculatedRecord::<T>::set(None);
 
@@ -658,10 +658,8 @@
 				// stakers_number - keeps the remaining number of iterations (staker addresses to handle)
 				// next_recalc_block_for_stake - is taken from the state and stores the starting relay block from which reward should be paid out
 				// income_acc - stores the reward amount to pay to the staker address (accumulates over all address stake records)
-				while let Some((
-					(current_id, staked_block),
-					(amount, next_recalc_block_for_stake),
-				)) = storage_iterator.next()
+				for ((current_id, staked_block), (amount, next_recalc_block_for_stake)) in
+					storage_iterator
 				{
 					// last_id is not equal current_id when we switch to handling a new staker address
 					// or just start handling the very first address. In the latter case last_id will be None and
@@ -859,11 +857,11 @@
 				if acc_amount < balance_per_block {
 					let res = (block, balance_per_block - acc_amount);
 					acc_amount = <BalanceOf<T>>::default();
-					return Some(res);
+					Some(res)
 				} else {
 					acc_amount -= balance_per_block;
 					will_deleted_stakes_count += 1;
-					return Some((block, <BalanceOf<T>>::default()));
+					Some((block, <BalanceOf<T>>::default()))
 				}
 			})
 			.collect::<Vec<_>>();
@@ -926,7 +924,7 @@
 		if amount.is_zero() {
 			<<T as Config>::Currency as MutateFreeze<T::AccountId>>::thaw(
 				&T::FreezeIdentifier::get(),
-				&staker,
+				staker,
 			)
 		} else {
 			<<T as Config>::Currency as MutateFreeze<T::AccountId>>::set_freeze(
@@ -1026,10 +1024,10 @@
 	) {
 		let income = Self::calculate_income(base, iters);
 
-		base.checked_add(&income).map(|res| {
+		if let Some(res) = base.checked_add(&income) {
 			<Staked<T>>::insert((staker, staked_block), (res, next_recalc_block));
 			*income_acc += income;
-		});
+		};
 	}
 
 	fn calculate_income<I>(base: I, iters: u32) -> I
modifiedpallets/app-promotion/src/types.rsdiffbeforeafterboth
--- a/pallets/app-promotion/src/types.rs
+++ b/pallets/app-promotion/src/types.rs
@@ -149,16 +149,16 @@
 		Self {
 			recalculation_interval: config
 				.recalculation_interval
-				.unwrap_or_else(|| T::RecalculationInterval::get()),
+				.unwrap_or_else(T::RecalculationInterval::get),
 			pending_interval: config
 				.pending_interval
-				.unwrap_or_else(|| T::PendingInterval::get()),
+				.unwrap_or_else(T::PendingInterval::get),
 			interval_income: config
 				.interval_income
-				.unwrap_or_else(|| T::IntervalIncome::get()),
+				.unwrap_or_else(T::IntervalIncome::get),
 			max_stakers_per_calculation: config
 				.max_stakers_per_calculation
-				.unwrap_or_else(|| MAX_NUMBER_PAYOUTS),
+				.unwrap_or(MAX_NUMBER_PAYOUTS),
 		}
 	}
 }
modifiedpallets/balances-adapter/src/lib.rsdiffbeforeafterboth
--- a/pallets/balances-adapter/src/lib.rs
+++ b/pallets/balances-adapter/src/lib.rs
@@ -31,6 +31,12 @@
 	}
 }
 
+impl<T: Config> Default for NativeFungibleHandle<T> {
+	fn default() -> Self {
+		Self::new()
+	}
+}
+
 impl<T: Config> WithRecorder<T> for NativeFungibleHandle<T> {
 	fn recorder(&self) -> &pallet_evm_coder_substrate::SubstrateRecorder<T> {
 		&self.0
modifiedpallets/common/src/eth.rsdiffbeforeafterboth
--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -136,7 +136,7 @@
 
 	fn try_from(from: up_data_structs::Property) -> Result<Self, Self::Error> {
 		let key = evm_coder::types::String::from_utf8(from.key.into())
-			.map_err(|e| Self::Error::Revert(format!("utf8 conversion error: {}", e)))?;
+			.map_err(|e| Self::Error::Revert(format!("utf8 conversion error: {e}")))?;
 		let value = evm_coder::types::Bytes(from.value.to_vec());
 		Ok(Property { key, value })
 	}
@@ -201,10 +201,7 @@
 	pub fn new(field: CollectionLimitField, value: Option<u32>) -> Self {
 		Self {
 			field,
-			value: match value {
-				Some(value) => Some(value.into()),
-				None => None,
-			},
+			value: value.map(|value| value.into()),
 		}
 	}
 	/// Whether the field contains a value.
@@ -222,8 +219,7 @@
 			.ok_or::<Self::Error>("can't convert `None` value to boolean".into())?;
 		let value = Some(value.try_into().map_err(|error| {
 			Self::Error::Revert(format!(
-				"can't convert value to u32 \"{}\" because: \"{error}\"",
-				value
+				"can't convert value to u32 \"{value}\" because: \"{error}\""
 			))
 		})?);
 
@@ -249,10 +245,8 @@
 				limits.sponsored_data_size = value;
 			}
 			CollectionLimitField::SponsoredDataRateLimit => {
-				limits.sponsored_data_rate_limit = match value {
-					Some(value) => Some(up_data_structs::SponsoringRateLimit::Blocks(value)),
-					None => None,
-				};
+				limits.sponsored_data_rate_limit =
+					value.map(up_data_structs::SponsoringRateLimit::Blocks);
 			}
 			CollectionLimitField::TokenLimit => {
 				limits.token_limit = value;
@@ -454,9 +448,9 @@
 	}
 }
 
-impl Into<up_data_structs::AccessMode> for AccessMode {
-	fn into(self) -> up_data_structs::AccessMode {
-		match self {
+impl From<AccessMode> for up_data_structs::AccessMode {
+	fn from(value: AccessMode) -> Self {
+		match value {
 			AccessMode::Normal => up_data_structs::AccessMode::Normal,
 			AccessMode::AllowList => up_data_structs::AccessMode::AllowList,
 		}
modifiedpallets/evm-coder-substrate/src/lib.rsdiffbeforeafterboth
--- a/pallets/evm-coder-substrate/src/lib.rs
+++ b/pallets/evm-coder-substrate/src/lib.rs
@@ -260,9 +260,9 @@
 			message: Some(msg), ..
 		}) => ExError::Revert(msg.into()),
 		DispatchError::Module(ModuleError { index, error, .. }) => {
-			ExError::Revert(format!("error {:?} in pallet {}", error, index))
+			ExError::Revert(format!("error {error:?} in pallet {index}"))
 		}
-		e => ExError::Revert(format!("substrate error: {:?}", e)),
+		e => ExError::Revert(format!("substrate error: {e:?}")),
 	}
 }
 
modifiedpallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth
--- a/pallets/evm-contract-helpers/src/eth.rs
+++ b/pallets/evm-contract-helpers/src/eth.rs
@@ -184,10 +184,9 @@
 	/// @param contractAddress The contract for which a sponsor is requested.
 	/// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
 	fn sponsor(&self, contract_address: Address) -> Result<Option<eth::CrossAddress>> {
-		Ok(match Pallet::<T>::get_sponsor(contract_address) {
-			Some(ref value) => Some(eth::CrossAddress::from_sub_cross_account::<T>(value)),
-			None => None,
-		})
+		Ok(Pallet::<T>::get_sponsor(contract_address)
+			.as_ref()
+			.map(eth::CrossAddress::from_sub_cross_account::<T>))
 	}
 
 	/// Check tat contract has confirmed sponsor.
@@ -275,7 +274,7 @@
 		self.recorder().consume_sstore()?;
 
 		<Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;
-		<Pallet<T>>::set_sponsoring_fee_limit(contract_address, fee_limit.into())
+		<Pallet<T>>::set_sponsoring_fee_limit(contract_address, fee_limit)
 			.map_err(dispatch_to_evm::<T>)?;
 		Ok(())
 	}
modifiedpallets/evm-contract-helpers/src/lib.rsdiffbeforeafterboth
--- a/pallets/evm-contract-helpers/src/lib.rs
+++ b/pallets/evm-contract-helpers/src/lib.rs
@@ -376,7 +376,7 @@
 			<SponsoringMode<T>>::get(contract)
 				.or_else(|| {
 					#[allow(deprecated)]
-					<SelfSponsoring<T>>::get(contract).then(|| SponsoringModeT::Allowlisted)
+					<SelfSponsoring<T>>::get(contract).then_some(SponsoringModeT::Allowlisted)
 				})
 				.unwrap_or_default()
 		}
@@ -410,7 +410,7 @@
 
 		/// Is user added to allowlist, or he is owner of specified contract
 		pub fn allowed(contract: H160, user: H160) -> bool {
-			<Allowlist<T>>::get(&contract, &user) || <Owner<T>>::get(&contract) == user
+			<Allowlist<T>>::get(contract, user) || <Owner<T>>::get(contract) == user
 		}
 
 		/// Toggle contract allowlist access
@@ -425,7 +425,7 @@
 
 		/// Throw error if user is not allowed to reconfigure target contract
 		pub fn ensure_owner(contract: H160, user: H160) -> DispatchResult {
-			ensure!(<Owner<T>>::get(&contract) == user, Error::<T>::NoPermission);
+			ensure!(<Owner<T>>::get(contract) == user, Error::<T>::NoPermission);
 			Ok(())
 		}
 	}
modifiedpallets/evm-migration/src/lib.rsdiffbeforeafterboth
--- a/pallets/evm-migration/src/lib.rs
+++ b/pallets/evm-migration/src/lib.rs
@@ -78,7 +78,7 @@
 		pub fn begin(origin: OriginFor<T>, address: H160) -> DispatchResult {
 			ensure_root(origin)?;
 			ensure!(
-				<PalletEvm<T>>::is_account_empty(&address) && !<MigrationPending<T>>::get(&address),
+				<PalletEvm<T>>::is_account_empty(&address) && !<MigrationPending<T>>::get(address),
 				<Error<T>>::AccountNotEmpty,
 			);
 
@@ -97,12 +97,12 @@
 		) -> DispatchResult {
 			ensure_root(origin)?;
 			ensure!(
-				<MigrationPending<T>>::get(&address),
+				<MigrationPending<T>>::get(address),
 				<Error<T>>::AccountIsNotMigrating,
 			);
 
 			for (k, v) in data {
-				<pallet_evm::AccountStorages<T>>::insert(&address, k, v);
+				<pallet_evm::AccountStorages<T>>::insert(address, k, v);
 			}
 			Ok(())
 		}
@@ -115,11 +115,11 @@
 		pub fn finish(origin: OriginFor<T>, address: H160, code: Vec<u8>) -> DispatchResult {
 			ensure_root(origin)?;
 			ensure!(
-				<MigrationPending<T>>::get(&address),
+				<MigrationPending<T>>::get(address),
 				<Error<T>>::AccountIsNotMigrating,
 			);
 
-			<pallet_evm::AccountCodes<T>>::insert(&address, code);
+			<pallet_evm::AccountCodes<T>>::insert(address, code);
 			<MigrationPending<T>>::remove(address);
 			Ok(())
 		}
@@ -166,7 +166,7 @@
 	pub struct OnMethodCall<T>(PhantomData<T>);
 	impl<T: Config> pallet_evm::OnMethodCall<T> for OnMethodCall<T> {
 		fn is_reserved(contract: &H160) -> bool {
-			<MigrationPending<T>>::get(&contract)
+			<MigrationPending<T>>::get(contract)
 		}
 
 		fn is_used(_contract: &H160) -> bool {
modifiedpallets/foreign-assets/src/impl_fungibles.rsdiffbeforeafterboth
--- a/pallets/foreign-assets/src/impl_fungibles.rs
+++ b/pallets/foreign-assets/src/impl_fungibles.rs
@@ -333,7 +333,7 @@
 					&Value::new(0),
 				)?;
 
-				Ok(amount.into())
+				Ok(amount)
 			}
 		}
 	}
modifiedpallets/foreign-assets/src/lib.rsdiffbeforeafterboth
--- a/pallets/foreign-assets/src/lib.rs
+++ b/pallets/foreign-assets/src/lib.rs
@@ -161,7 +161,7 @@
 
 	fn get_currency_id(multi_location: MultiLocation) -> Option<CurrencyId> {
 		log::trace!(target: "fassets::get_currency_id", "call");
-		Pallet::<T>::location_to_currency_ids(multi_location).map(|id| AssetIds::ForeignAssetId(id))
+		Pallet::<T>::location_to_currency_ids(multi_location).map(AssetIds::ForeignAssetId)
 	}
 }
 
@@ -378,7 +378,7 @@
 				foreign_asset_id,
 				|maybe_location| -> DispatchResult {
 					ensure!(maybe_location.is_none(), Error::<T>::MultiLocationExisted);
-					*maybe_location = Some(location.clone());
+					*maybe_location = Some(*location);
 
 					AssetMetadatas::<T>::try_mutate(
 						AssetIds::ForeignAssetId(foreign_asset_id),
@@ -422,7 +422,7 @@
 
 						// modify location
 						if location != old_multi_locations {
-							LocationToCurrencyIds::<T>::remove(old_multi_locations.clone());
+							LocationToCurrencyIds::<T>::remove(*old_multi_locations);
 							LocationToCurrencyIds::<T>::try_mutate(
 								location,
 								|maybe_currency_ids| -> DispatchResult {
@@ -437,7 +437,7 @@
 							)?;
 						}
 						*maybe_asset_metadatas = Some(metadata.clone());
-						*old_multi_locations = location.clone();
+						*old_multi_locations = *location;
 						Ok(())
 					},
 				)
modifiedpallets/identity/src/types.rsdiffbeforeafterboth
--- a/pallets/identity/src/types.rs
+++ b/pallets/identity/src/types.rs
@@ -104,7 +104,7 @@
 			Data::Raw(ref x) => {
 				let l = x.len().min(32);
 				let mut r = vec![l as u8 + 1; l + 1];
-				r[1..].copy_from_slice(&x[..l as usize]);
+				r[1..].copy_from_slice(&x[..l]);
 				r
 			}
 			Data::BlakeTwo256(ref h) => once(34u8).chain(h.iter().cloned()).collect(),
@@ -287,7 +287,7 @@
 	fn decode<I: codec::Input>(input: &mut I) -> sp_std::result::Result<Self, codec::Error> {
 		let field = u64::decode(input)?;
 		Ok(Self(
-			<BitFlags<IdentityField>>::from_bits(field as u64).map_err(|_| "invalid value")?,
+			<BitFlags<IdentityField>>::from_bits(field).map_err(|_| "invalid value")?,
 		))
 	}
 }
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -20,6 +20,8 @@
 //! Method implementations are mostly doing parameter conversion and calling Nonfungible Pallet methods.
 
 extern crate alloc;
+
+use alloc::string::ToString;
 use core::{
 	char::{REPLACEMENT_CHARACTER, decode_utf16},
 	convert::TryInto,
@@ -356,8 +358,7 @@
 				.transpose()
 				.map_err(|e| {
 					Error::Revert(alloc::format!(
-						"Can not convert value \"baseURI\" to string with error \"{}\"",
-						e
+						"Can not convert value \"baseURI\" to string with error \"{e}\""
 					))
 				})?;
 
@@ -675,7 +676,7 @@
 					.try_into()
 					.map_err(|_| "token uri is too long")?,
 			})
-			.map_err(|e| Error::Revert(alloc::format!("Can't add property: {:?}", e)))?;
+			.map_err(|e| Error::Revert(alloc::format!("Can't add property: {e:?}")))?;
 
 		<Pallet<T>>::create_item(
 			self,
@@ -717,7 +718,7 @@
 		.map(Clone::clone)
 		.ok_or_else(|| {
 			let key = String::from_utf8(key.clone().into_inner()).unwrap_or_default();
-			Error::Revert(alloc::format!("No permission for key {}", key))
+			Error::Revert(alloc::format!("No permission for key {key}"))
 		})?;
 	Ok(a)
 }
@@ -752,14 +753,14 @@
 	/// @param tokenId Id for the token.
 	#[solidity(hide)]
 	fn cross_owner_of(&self, token_id: U256) -> Result<eth::CrossAddress> {
-		Self::owner_of_cross(&self, token_id)
+		Self::owner_of_cross(self, token_id)
 	}
 
 	/// Returns the owner (in cross format) of the token.
 	///
 	/// @param tokenId Id for the token.
 	fn owner_of_cross(&self, token_id: U256) -> Result<eth::CrossAddress> {
-		Self::token_owner(&self, token_id.try_into()?)
+		Self::token_owner(self, token_id.try_into()?)
 			.map(|o| eth::CrossAddress::from_sub_cross_account::<T>(&o))
 			.map_err(|_| Error::Revert("token not found".into()))
 	}
@@ -789,7 +790,7 @@
 			.collect::<Result<Vec<_>>>()?;
 
 		<Self as CommonCollectionOperations<T>>::token_properties(
-			&self,
+			self,
 			token_id.try_into()?,
 			if keys.is_empty() { None } else { Some(keys) },
 		)
@@ -1021,7 +1022,7 @@
 						.try_into()
 						.map_err(|_| "token uri is too long")?,
 				})
-				.map_err(|e| Error::Revert(alloc::format!("Can't add property: {:?}", e)))?;
+				.map_err(|e| Error::Revert(alloc::format!("Can't add property: {e:?}")))?;
 
 			data.push(CreateItemData::<T> {
 				properties,
@@ -1056,7 +1057,7 @@
 			.map(eth::Property::try_into)
 			.collect::<Result<Vec<_>>>()?
 			.try_into()
-			.map_err(|_| Error::Revert(alloc::format!("too many properties")))?;
+			.map_err(|_| Error::Revert("too many properties".to_string()))?;
 
 		let caller = T::CrossAccountId::from_eth(caller);
 
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -166,10 +166,7 @@
 
 	#[pallet::config]
 	pub trait Config:
-		frame_system::Config
-		+ pallet_common::Config
-		+ pallet_structure::Config
-		+ pallet_evm::Config
+		frame_system::Config + pallet_common::Config + pallet_structure::Config + pallet_evm::Config
 	{
 		type WeightInfo: WeightInfo;
 	}
@@ -860,13 +857,7 @@
 
 		<PalletStructure<T>>::unnest_if_nested(&token_data.owner, collection.id, token);
 
-		<TokenData<T>>::insert(
-			(collection.id, token),
-			ItemData {
-				owner: to.clone(),
-				..token_data
-			},
-		);
+		<TokenData<T>>::insert((collection.id, token), ItemData { owner: to.clone() });
 
 		if let Some(balance_to) = balance_to {
 			// from != to
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -21,6 +21,7 @@
 
 extern crate alloc;
 
+use alloc::string::ToString;
 use core::{
 	char::{REPLACEMENT_CHARACTER, decode_utf16},
 	convert::TryInto,
@@ -353,8 +354,7 @@
 				.transpose()
 				.map_err(|e| {
 					Error::Revert(alloc::format!(
-						"Can not convert value \"baseURI\" to string with error \"{}\"",
-						e
+						"Can not convert value \"baseURI\" to string with error \"{e}\""
 					))
 				})?;
 
@@ -482,8 +482,8 @@
 			.recorder
 			.weight_calls_budget(<StructureWeight<T>>::find_parent());
 
-		let balance = balance(&self, token, &from)?;
-		ensure_single_owner(&self, token, balance)?;
+		let balance = balance(self, token, &from)?;
+		ensure_single_owner(self, token, balance)?;
 
 		<Pallet<T>>::transfer_from(self, &caller, &from, &to, token, balance, &budget)
 			.map_err(dispatch_to_evm::<T>)?;
@@ -575,8 +575,8 @@
 		let caller = T::CrossAccountId::from_eth(caller);
 		let token = token_id.try_into()?;
 
-		let balance = balance(&self, token, &caller)?;
-		ensure_single_owner(&self, token, balance)?;
+		let balance = balance(self, token, &caller)?;
+		ensure_single_owner(self, token, balance)?;
 
 		<Pallet<T>>::burn(self, &caller, token, balance).map_err(dispatch_to_evm::<T>)?;
 		Ok(())
@@ -622,7 +622,7 @@
 			return Err("item id should be next".into());
 		}
 
-		let users = [(to.clone(), 1)]
+		let users = [(to, 1)]
 			.into_iter()
 			.collect::<BTreeMap<_, _>>()
 			.try_into()
@@ -706,9 +706,9 @@
 					.try_into()
 					.map_err(|_| "token uri is too long")?,
 			})
-			.map_err(|e| Error::Revert(alloc::format!("Can't add property: {:?}", e)))?;
+			.map_err(|e| Error::Revert(alloc::format!("Can't add property: {e:?}")))?;
 
-		let users = [(to.clone(), 1)]
+		let users = [(to, 1)]
 			.into_iter()
 			.collect::<BTreeMap<_, _>>()
 			.try_into()
@@ -750,7 +750,7 @@
 		.map(Clone::clone)
 		.ok_or_else(|| {
 			let key = String::from_utf8(key.clone().into_inner()).unwrap_or_default();
-			Error::Revert(alloc::format!("No permission for key {}", key))
+			Error::Revert(alloc::format!("No permission for key {key}"))
 		})?;
 	Ok(a)
 }
@@ -785,14 +785,14 @@
 	/// @param tokenId Id for the token.
 	#[solidity(hide)]
 	fn cross_owner_of(&self, token_id: U256) -> Result<eth::CrossAddress> {
-		Self::owner_of_cross(&self, token_id)
+		Self::owner_of_cross(self, token_id)
 	}
 
 	/// Returns the owner (in cross format) of the token.
 	///
 	/// @param tokenId Id for the token.
 	fn owner_of_cross(&self, token_id: U256) -> Result<eth::CrossAddress> {
-		Self::token_owner(&self, token_id.try_into()?)
+		Self::token_owner(self, token_id.try_into()?)
 			.map(|o| eth::CrossAddress::from_sub_cross_account::<T>(&o))
 			.or_else(|err| match err {
 				TokenOwnerError::NotFound => Err(Error::Revert("token not found".into())),
@@ -827,7 +827,7 @@
 			.collect::<Result<Vec<_>>>()?;
 
 		<Self as CommonCollectionOperations<T>>::token_properties(
-			&self,
+			self,
 			token_id.try_into()?,
 			if keys.is_empty() { None } else { Some(keys) },
 		)
@@ -1004,7 +1004,7 @@
 			}
 			expected_index = expected_index.checked_add(1).ok_or("item id overflow")?;
 		}
-		let users = [(to.clone(), 1)]
+		let users = [(to, 1)]
 			.into_iter()
 			.collect::<BTreeMap<_, _>>()
 			.try_into()
@@ -1046,7 +1046,7 @@
 			.weight_calls_budget(<StructureWeight<T>>::find_parent());
 
 		let mut data = Vec::with_capacity(tokens.len());
-		let users: BoundedBTreeMap<_, _, _> = [(to.clone(), 1)]
+		let users: BoundedBTreeMap<_, _, _> = [(to, 1)]
 			.into_iter()
 			.collect::<BTreeMap<_, _>>()
 			.try_into()
@@ -1067,7 +1067,7 @@
 						.try_into()
 						.map_err(|_| "token uri is too long")?,
 				})
-				.map_err(|e| Error::Revert(alloc::format!("Can't add property: {:?}", e)))?;
+				.map_err(|e| Error::Revert(alloc::format!("Can't add property: {e:?}")))?;
 
 			let create_item_data = CreateItemData::<T> {
 				users: users.clone(),
@@ -1103,7 +1103,7 @@
 			.map(eth::Property::try_into)
 			.collect::<Result<Vec<_>>>()?
 			.try_into()
-			.map_err(|_| Error::Revert(alloc::format!("too many properties")))?;
+			.map_err(|_| Error::Revert("too many properties".to_string()))?;
 
 		let caller = T::CrossAccountId::from_eth(caller);
 
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -1124,7 +1124,7 @@
 
 		if collection.ignores_token_restrictions(spender) {
 			return Ok(Self::compute_allowance_decrease(
-				collection, token, from, &spender, amount,
+				collection, token, from, spender, amount,
 			));
 		}
 
@@ -1143,7 +1143,7 @@
 			return Ok(None);
 		}
 
-		let allowance = Self::compute_allowance_decrease(collection, token, from, &spender, amount);
+		let allowance = Self::compute_allowance_decrease(collection, token, from, spender, amount);
 		if allowance.is_some() {
 			return Ok(allowance);
 		}
modifiedpallets/scheduler-v2/src/lib.rsdiffbeforeafterboth
--- a/pallets/scheduler-v2/src/lib.rs
+++ b/pallets/scheduler-v2/src/lib.rs
@@ -969,7 +969,7 @@
 		call: ScheduledCall<T>,
 	) -> Result<TaskAddress<T::BlockNumber>, DispatchError> {
 		// ensure id it is unique
-		if Lookup::<T>::contains_key(&id) {
+		if Lookup::<T>::contains_key(id) {
 			return Err(Error::<T>::FailedToSchedule.into());
 		}
 
modifiedpallets/structure/src/lib.rsdiffbeforeafterboth
--- a/pallets/structure/src/lib.rs
+++ b/pallets/structure/src/lib.rs
@@ -280,7 +280,7 @@
 	) -> DispatchResultWithPostInfo {
 		let dispatch = T::CollectionDispatch::dispatch(collection)?;
 		let dispatch = dispatch.as_dyn();
-		dispatch.burn_item_recursively(from.clone(), token, self_budget, breadth_budget)
+		dispatch.burn_item_recursively(from, token, self_budget, breadth_budget)
 	}
 
 	/// Check if `token` indirectly owned by `user`
@@ -396,7 +396,7 @@
 		account: &T::CrossAccountId,
 		action: impl FnOnce(&dyn CommonCollectionOperations<T>, TokenId) -> DispatchResult,
 	) -> DispatchResult {
-		if is_collection(&account.as_eth()) {
+		if is_collection(account.as_eth()) {
 			fail!(<Error<T>>::CantNestTokenUnderCollection);
 		}
 		let Some((collection, token)) = T::CrossTokenAddressMapping::address_to_token(account) else {
modifiedpallets/unique/src/eth/mod.rsdiffbeforeafterboth
--- a/pallets/unique/src/eth/mod.rs
+++ b/pallets/unique/src/eth/mod.rs
@@ -113,13 +113,9 @@
 	let collection_helpers_address =
 		T::CrossAccountId::from_eth(<T as pallet_common::Config>::ContractAddress::get());
 
-	let collection_id = T::CollectionDispatch::create(
-		caller.clone(),
-		collection_helpers_address,
-		data,
-		Default::default(),
-	)
-	.map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;
+	let collection_id =
+		T::CollectionDispatch::create(caller, collection_helpers_address, data, Default::default())
+			.map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;
 	let address = pallet_common::eth::collection_id_to_address(collection_id);
 	Ok(address)
 }
@@ -132,8 +128,7 @@
 		.expect("Collection creation price should be convertible to u128");
 	if value != creation_price {
 		return Err(format!(
-			"Sent amount not equals to collection creation price ({0})",
-			creation_price
+			"Sent amount not equals to collection creation price ({creation_price})",
 		)
 		.into());
 	}
@@ -383,8 +378,7 @@
 		map_eth_to_id(&collection_address)
 			.map(|id| id.0)
 			.ok_or(Error::Revert(format!(
-				"failed to convert address {} into collectionId.",
-				collection_address
+				"failed to convert address {collection_address} into collectionId."
 			)))
 	}
 }
@@ -422,5 +416,5 @@
 generate_stubgen!(collection_helper_iface, CollectionHelpersCall<()>, false);
 
 fn error_field_too_long(feild: &str, bound: usize) -> Error {
-	Error::Revert(format!("{} is too long. Max length is {}.", feild, bound))
+	Error::Revert(format!("{feild} is too long. Max length is {bound}."))
 }
modifiedpallets/unique/src/lib.rsdiffbeforeafterboth
--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -507,7 +507,7 @@
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
 			let new_owner = T::CrossAccountId::from_sub(new_owner);
 			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
-			target_collection.change_owner(sender, new_owner.clone())
+			target_collection.change_owner(sender, new_owner)
 		}
 
 		/// Add an admin to a collection.
@@ -667,7 +667,7 @@
 		/// * `owner`: Address of the initial owner of the item.
 		/// * `data`: Token data describing the item to store on chain.
 		#[pallet::call_index(11)]
-		#[pallet::weight(T::CommonWeightInfo::create_item(&data))]
+		#[pallet::weight(T::CommonWeightInfo::create_item(data))]
 		pub fn create_item(
 			origin: OriginFor<T>,
 			collection_id: CollectionId,
@@ -701,7 +701,7 @@
 		/// * `owner`: Address of the initial owner of the tokens.
 		/// * `items_data`: Vector of data describing each item to be created.
 		#[pallet::call_index(12)]
-		#[pallet::weight(T::CommonWeightInfo::create_multiple_items(&items_data))]
+		#[pallet::weight(T::CommonWeightInfo::create_multiple_items(items_data))]
 		pub fn create_multiple_items(
 			origin: OriginFor<T>,
 			collection_id: CollectionId,
@@ -889,7 +889,7 @@
 		/// * `collection_id`: ID of the collection to which the tokens would belong.
 		/// * `data`: Explicit item creation data.
 		#[pallet::call_index(18)]
-		#[pallet::weight(T::CommonWeightInfo::create_multiple_items_ex(&data))]
+		#[pallet::weight(T::CommonWeightInfo::create_multiple_items_ex(data))]
 		pub fn create_multiple_items_ex(
 			origin: OriginFor<T>,
 			collection_id: CollectionId,
@@ -1313,7 +1313,7 @@
 			collection_id: CollectionId,
 		) -> DispatchResult {
 			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
-			target_collection.force_set_sponsor(sponsor.clone())
+			target_collection.force_set_sponsor(sponsor)
 		}
 
 		/// Force remove `sponsor` for `collection`.
modifiedprimitives/data-structs/src/bounded.rsdiffbeforeafterboth
--- a/primitives/data-structs/src/bounded.rs
+++ b/primitives/data-structs/src/bounded.rs
@@ -63,7 +63,7 @@
 	V: fmt::Debug,
 {
 	use core::fmt::Debug;
-	(&v as &Vec<V>).fmt(f)
+	(v as &Vec<V>).fmt(f)
 }
 
 #[cfg(feature = "serde1")]
@@ -114,7 +114,7 @@
 	V: fmt::Debug,
 {
 	use core::fmt::Debug;
-	(&v as &BTreeMap<K, V>).fmt(f)
+	(v as &BTreeMap<K, V>).fmt(f)
 }
 
 #[cfg(feature = "serde1")]
@@ -157,5 +157,5 @@
 	K: fmt::Debug + Ord,
 {
 	use core::fmt::Debug;
-	(&v as &BTreeSet<K>).fmt(f)
+	(v as &BTreeSet<K>).fmt(f)
 }
modifiedprimitives/data-structs/src/lib.rsdiffbeforeafterboth
before · primitives/data-structs/src/lib.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/>.1617//! # Primitives crate.18//!19//! This crate contains types, traits and constants.2021#![cfg_attr(not(feature = "std"), no_std)]2223use core::{24	convert::{TryFrom, TryInto},25	fmt,26	ops::Deref,27};28use frame_support::storage::{bounded_btree_map::BoundedBTreeMap, bounded_btree_set::BoundedBTreeSet};2930#[cfg(feature = "serde")]31use serde::{Serialize, Deserialize};3233use sp_core::U256;34use sp_runtime::{ArithmeticError, sp_std::prelude::Vec};35use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};36use bondrewd::Bitfields;37use frame_support::{BoundedVec, traits::ConstU32};38use derivative::Derivative;39use scale_info::TypeInfo;4041mod bondrewd_codec;42mod bounded;43pub mod budget;44pub mod mapping;45mod migration;4647/// Maximum of decimal points.48pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;4950/// Maximum pieces for refungible token.51pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;52pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;5354/// Maximum tokens for user.55pub const MAX_TOKEN_OWNERSHIP: u32 = if cfg!(not(feature = "limit-testing")) {56	100_00057} else {58	1059};6061/// Maximum for collections can be created.62pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {63	100_00064} else {65	1066};6768/// Maximum for various custom data of token.69pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {70	204871} else {72	1073};7475/// Maximum admins per collection.76pub const COLLECTION_ADMINS_LIMIT: u32 = 5;7778/// Maximum tokens per collection.79pub const COLLECTION_TOKEN_LIMIT: u32 = u32::MAX;8081/// Maximum tokens per account.82pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {83	1_000_00084} else {85	1086};8788/// Default timeout for transfer sponsoring NFT item.89pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;90/// Default timeout for transfer sponsoring fungible item.91pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;92/// Default timeout for transfer sponsoring refungible item.93pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;9495/// Default timeout for sponsored approving.96pub const SPONSOR_APPROVE_TIMEOUT: u32 = 5;9798// Schema limits99pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 8192;100pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 8192;101pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 32768;102103// TODO: not used. Delete?104pub const COLLECTION_FIELD_LIMIT: u32 = CONST_ON_CHAIN_SCHEMA_LIMIT;105106/// Maximal length of a collection name.107pub const MAX_COLLECTION_NAME_LENGTH: u32 = 64;108109/// Maximal length of a collection description.110pub const MAX_COLLECTION_DESCRIPTION_LENGTH: u32 = 256;111112/// Maximal length of a token prefix.113pub const MAX_TOKEN_PREFIX_LENGTH: u32 = 16;114115/// Maximal length of a property key.116pub const MAX_PROPERTY_KEY_LENGTH: u32 = 256;117118/// Maximal length of a property value.119pub const MAX_PROPERTY_VALUE_LENGTH: u32 = 32768;120121/// A maximum number of token properties.122pub const MAX_PROPERTIES_PER_ITEM: u32 = 64;123124/// Maximal lenght of extended property value.125pub const MAX_AUX_PROPERTY_VALUE_LENGTH: u32 = 2048;126127/// Maximum size for all collection properties.128pub const MAX_COLLECTION_PROPERTIES_SIZE: u32 = 40960;129130/// Maximum size of all token properties.131pub const MAX_TOKEN_PROPERTIES_SIZE: u32 = 32768;132133/// How much items can be created per single134/// create_many call.135pub const MAX_ITEMS_PER_BATCH: u32 = 200;136137/// Used for limit bounded types of token custom data.138pub type CustomDataLimit = ConstU32<CUSTOM_DATA_LIMIT>;139140/// Collection id.141#[derive(142	Encode,143	Decode,144	PartialEq,145	Eq,146	PartialOrd,147	Ord,148	Clone,149	Copy,150	Debug,151	Default,152	TypeInfo,153	MaxEncodedLen,154)]155#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]156pub struct CollectionId(pub u32);157impl EncodeLike<u32> for CollectionId {}158impl EncodeLike<CollectionId> for u32 {}159160impl From<u32> for CollectionId {161	fn from(value: u32) -> Self {162		Self(value)163	}164}165166/// Token id.167#[derive(168	Encode,169	Decode,170	PartialEq,171	Eq,172	PartialOrd,173	Ord,174	Clone,175	Copy,176	Debug,177	Default,178	TypeInfo,179	MaxEncodedLen,180)]181#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]182pub struct TokenId(pub u32);183impl EncodeLike<u32> for TokenId {}184impl EncodeLike<TokenId> for u32 {}185186impl TokenId {187	/// Try to get next token id.188	///189	/// If next id cause overflow, then [`ArithmeticError::Overflow`] returned.190	pub fn try_next(self) -> Result<TokenId, ArithmeticError> {191		self.0192			.checked_add(1)193			.ok_or(ArithmeticError::Overflow)194			.map(Self)195	}196}197198impl From<TokenId> for U256 {199	fn from(t: TokenId) -> Self {200		t.0.into()201	}202}203204impl TryFrom<U256> for TokenId {205	type Error = &'static str;206207	fn try_from(value: U256) -> Result<Self, Self::Error> {208		Ok(TokenId(value.try_into().map_err(|_| "too large token id")?))209	}210}211212/// Token data.213#[struct_versioning::versioned(version = 2, upper)]214#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]215#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]216pub struct TokenData<CrossAccountId> {217	/// Properties of token.218	pub properties: Vec<Property>,219220	/// Token owner.221	pub owner: Option<CrossAccountId>,222223	/// Token pieces.224	#[version(2.., upper(0))]225	pub pieces: u128,226}227228// TODO: unused type229pub struct OverflowError;230impl From<OverflowError> for &'static str {231	fn from(_: OverflowError) -> Self {232		"overflow occured"233	}234}235236/// Alias for decimal points type.237pub type DecimalPoints = u8;238239/// Collection mode.240///241/// Collection can represent various types of tokens.242/// Each collection can contain only one type of tokens at a time.243/// This type helps to understand which tokens the collection contains.244#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]245#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]246pub enum CollectionMode {247	/// Non fungible tokens.248	NFT,249	/// Fungible tokens.250	Fungible(DecimalPoints),251	/// Refungible tokens.252	ReFungible,253}254255impl CollectionMode {256	/// Get collection mod as number.257	pub fn id(&self) -> u8 {258		match self {259			CollectionMode::NFT => 1,260			CollectionMode::Fungible(_) => 2,261			CollectionMode::ReFungible => 3,262		}263	}264}265266// TODO: unused trait267pub trait SponsoringResolve<AccountId, Call> {268	fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;269}270271/// Access mode for some token operations.272#[derive(Encode, Decode, Eq, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]273#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]274pub enum AccessMode {275	/// Access grant for owner and admins. Used as default.276	Normal,277	/// Like a [`Normal`](AccessMode::Normal) but also users in allow list.278	AllowList,279}280impl Default for AccessMode {281	fn default() -> Self {282		Self::Normal283	}284}285286// TODO: remove in future.287#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]288#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]289pub enum SchemaVersion {290	ImageURL,291	Unique,292}293impl Default for SchemaVersion {294	fn default() -> Self {295		Self::ImageURL296	}297}298299// TODO: unused type300#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]301#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]302pub struct Ownership<AccountId> {303	pub owner: AccountId,304	pub fraction: u128,305}306307/// The state of collection sponsorship.308#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]309#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]310pub enum SponsorshipState<AccountId> {311	/// The fees are applied to the transaction sender.312	Disabled,313	/// The sponsor is under consideration. Until the sponsor gives his consent,314	/// the fee will still be charged to sender.315	Unconfirmed(AccountId),316	/// Transactions are sponsored by specified account.317	Confirmed(AccountId),318}319320impl<AccountId> SponsorshipState<AccountId> {321	/// Get a sponsor of the collection who has confirmed his status.322	pub fn sponsor(&self) -> Option<&AccountId> {323		match self {324			Self::Confirmed(sponsor) => Some(sponsor),325			_ => None,326		}327	}328329	/// Get a sponsor of the collection who has pending or confirmed status.330	pub fn pending_sponsor(&self) -> Option<&AccountId> {331		match self {332			Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),333			_ => None,334		}335	}336337	/// Whether the sponsorship is confirmed.338	pub fn confirmed(&self) -> bool {339		matches!(self, Self::Confirmed(_))340	}341}342343impl<T> Default for SponsorshipState<T> {344	fn default() -> Self {345		Self::Disabled346	}347}348349pub type CollectionName = BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>;350pub type CollectionDescription = BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>;351pub type CollectionTokenPrefix = BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>;352353#[derive(Bitfields, Clone, Copy, PartialEq, Eq, Debug, Default)]354#[bondrewd(enforce_bytes = 1)]355pub struct CollectionFlags {356	/// Tokens in foreign collections can be transferred, but not burnt357	#[bondrewd(bits = "0..1")]358	pub foreign: bool,359	/// Supports ERC721Metadata360	#[bondrewd(bits = "1..2")]361	pub erc721metadata: bool,362	/// External collections can't be managed using `unique` api363	#[bondrewd(bits = "7..8")]364	pub external: bool,365366	#[bondrewd(reserve, bits = "2..7")]367	pub reserved: u8,368}369bondrewd_codec!(CollectionFlags);370371/// Base structure for represent collection.372///373/// Used to provide basic functionality for all types of collections.374///375/// #### Note376/// Collection parameters, used in storage (see [`RpcCollection`] for the RPC version).377#[struct_versioning::versioned(version = 2, upper)]378#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen)]379pub struct Collection<AccountId> {380	/// Collection owner account.381	pub owner: AccountId,382383	/// Collection mode.384	pub mode: CollectionMode,385386	/// Access mode.387	#[version(..2)]388	pub access: AccessMode,389390	/// Collection name.391	pub name: CollectionName,392393	/// Collection description.394	pub description: CollectionDescription,395396	/// Token prefix.397	pub token_prefix: CollectionTokenPrefix,398399	#[version(..2)]400	pub mint_mode: bool,401402	#[version(..2)]403	pub offchain_schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,404405	#[version(..2)]406	pub schema_version: SchemaVersion,407408	/// The state of sponsorship of the collection.409	pub sponsorship: SponsorshipState<AccountId>,410411	/// Collection limits.412	pub limits: CollectionLimits,413414	/// Collection permissions.415	#[version(2.., upper(Default::default()))]416	pub permissions: CollectionPermissions,417418	#[version(2.., upper(Default::default()))]419	pub flags: CollectionFlags,420421	#[version(..2)]422	pub variable_on_chain_schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>,423424	#[version(..2)]425	pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,426427	#[version(..2)]428	pub meta_update_permission: MetaUpdatePermission,429}430431#[derive(Debug, Encode, Decode, Clone, PartialEq, TypeInfo)]432#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]433pub struct RpcCollectionFlags {434	/// Is collection is foreign.435	pub foreign: bool,436	/// Collection supports ERC721Metadata.437	pub erc721metadata: bool,438}439440/// Collection parameters, used in RPC calls (see [`Collection`] for the storage version).441#[struct_versioning::versioned(version = 2, upper)]442#[derive(Debug, Encode, Decode, Clone, PartialEq, TypeInfo)]443#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]444pub struct RpcCollection<AccountId> {445	/// Collection owner account.446	pub owner: AccountId,447448	/// Collection mode.449	pub mode: CollectionMode,450451	/// Collection name.452	pub name: Vec<u16>,453454	/// Collection description.455	pub description: Vec<u16>,456457	/// Token prefix.458	pub token_prefix: Vec<u8>,459460	/// The state of sponsorship of the collection.461	pub sponsorship: SponsorshipState<AccountId>,462463	/// Collection limits.464	pub limits: CollectionLimits,465466	/// Collection permissions.467	pub permissions: CollectionPermissions,468469	/// Token property permissions.470	pub token_property_permissions: Vec<PropertyKeyPermission>,471472	/// Collection properties.473	pub properties: Vec<Property>,474475	/// Is collection read only.476	pub read_only: bool,477478	/// Extra collection flags479	#[version(2.., upper(RpcCollectionFlags {foreign: false, erc721metadata: false}))]480	pub flags: RpcCollectionFlags,481}482483impl<AccountId> From<CollectionVersion1<AccountId>> for RpcCollection<AccountId> {484	fn from(value: CollectionVersion1<AccountId>) -> Self {485		let CollectionVersion1 {486			name,487			description,488			owner,489			mode,490			access,491			token_prefix,492			mint_mode,493			sponsorship,494			limits,495			..496		} = value;497498		RpcCollection {499			name: name.into_inner(),500			description: description.into_inner(),501			owner,502			mode,503			token_prefix: token_prefix.into_inner(),504			sponsorship,505			limits,506			permissions: CollectionPermissions {507				access: Some(access),508				mint_mode: Some(mint_mode),509				nesting: None,510			},511			token_property_permissions: Vec::default(),512			properties: Vec::default(),513			read_only: true,514515			flags: RpcCollectionFlags {516				foreign: false,517				erc721metadata: false,518			},519		}520	}521}522523pub struct RawEncoded(Vec<u8>);524525impl codec::Decode for RawEncoded {526	fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {527		let mut out = Vec::new();528		while let Ok(v) = input.read_byte() {529			out.push(v);530		}531		Ok(Self(out))532	}533}534535impl Deref for RawEncoded {536	type Target = Vec<u8>;537538	fn deref(&self) -> &Self::Target {539		return &self.0;540	}541}542543/// Data used for create collection.544///545/// All fields are wrapped in [`Option`], where `None` means chain default.546#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, Derivative, MaxEncodedLen)]547#[derivative(Debug, Default(bound = ""))]548pub struct CreateCollectionData<AccountId> {549	/// Collection mode.550	#[derivative(Default(value = "CollectionMode::NFT"))]551	pub mode: CollectionMode,552553	/// Access mode.554	pub access: Option<AccessMode>,555556	/// Collection name.557	pub name: CollectionName,558559	/// Collection description.560	pub description: CollectionDescription,561562	/// Token prefix.563	pub token_prefix: CollectionTokenPrefix,564565	/// Pending collection sponsor.566	pub pending_sponsor: Option<AccountId>,567568	/// Collection limits.569	pub limits: Option<CollectionLimits>,570571	/// Collection permissions.572	pub permissions: Option<CollectionPermissions>,573574	/// Token property permissions.575	pub token_property_permissions: CollectionPropertiesPermissionsVec,576577	/// Collection properties.578	pub properties: CollectionPropertiesVec,579}580581/// Bounded vector of properties permissions. Max length is [`MAX_PROPERTIES_PER_ITEM`].582// TODO: maybe rename to PropertiesPermissionsVec583pub type CollectionPropertiesPermissionsVec =584	BoundedVec<PropertyKeyPermission, ConstU32<MAX_PROPERTIES_PER_ITEM>>;585586/// Bounded vector of properties. Max length is [`MAX_PROPERTIES_PER_ITEM`].587pub type CollectionPropertiesVec = BoundedVec<Property, ConstU32<MAX_PROPERTIES_PER_ITEM>>;588589/// Limits and restrictions of a collection.590///591/// All fields are wrapped in [`Option`], where `None` means chain default.592///593/// Update with `pallet_common::Pallet::clamp_limits`.594// IMPORTANT: When adding/removing fields from this struct - don't forget to also595#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]596#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]597// When adding/removing fields from this struct - don't forget to also update with `pallet_common::Pallet::clamp_limits`.598// TODO: move `pallet_common::Pallet::clamp_limits` into `impl CollectionLimits`.599// TODO: may be remove [`Option`] and **pub** from fields and create struct with default values.600pub struct CollectionLimits {601	/// How many tokens can a user have on one account.602	/// * Default - [`ACCOUNT_TOKEN_OWNERSHIP_LIMIT`].603	/// * Limit - [`MAX_TOKEN_OWNERSHIP`].604	pub account_token_ownership_limit: Option<u32>,605606	/// How many bytes of data are available for sponsorship.607	/// * Default - [`CUSTOM_DATA_LIMIT`].608	/// * Limit - [`CUSTOM_DATA_LIMIT`].609	pub sponsored_data_size: Option<u32>,610611	// FIXME should we delete this or repurpose it?612	/// Times in how many blocks we sponsor data.613	///614	/// If is `Some(v)` then **setVariableMetadata** is sponsored if there is `v` block between transactions.615	///616	/// * Default - [`SponsoringDisabled`](SponsoringRateLimit::SponsoringDisabled).617	/// * Limit - [`MAX_SPONSOR_TIMEOUT`].618	///619	/// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]620	pub sponsored_data_rate_limit: Option<SponsoringRateLimit>,621	/// Maximum amount of tokens inside the collection. Chain default: [`COLLECTION_TOKEN_LIMIT`]622623	/// How many tokens can be mined into this collection.624	///625	/// * Default - [`COLLECTION_TOKEN_LIMIT`].626	/// * Limit - [`COLLECTION_TOKEN_LIMIT`].627	pub token_limit: Option<u32>,628629	/// Timeouts for transfer sponsoring.630	///631	/// * Default632	///   - **Fungible** - [`FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT`]633	///   - **NFT** - [`NFT_SPONSOR_TRANSFER_TIMEOUT`]634	///   - **Refungible** - [`REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT`]635	/// * Limit - [`MAX_SPONSOR_TIMEOUT`].636	pub sponsor_transfer_timeout: Option<u32>,637638	/// Timeout for sponsoring an approval in passed blocks.639	///640	/// * Default - [`SPONSOR_APPROVE_TIMEOUT`].641	/// * Limit - [`MAX_SPONSOR_TIMEOUT`].642	pub sponsor_approve_timeout: Option<u32>,643644	/// Whether the collection owner of the collection can send tokens (which belong to other users).645	///646	/// * Default - **false**.647	pub owner_can_transfer: Option<bool>,648649	/// Can the collection owner burn other people's tokens.650	///651	/// * Default - **true**.652	pub owner_can_destroy: Option<bool>,653654	/// Is it possible to send tokens from this collection between users.655	///656	/// * Default - **true**.657	pub transfers_enabled: Option<bool>,658}659660impl CollectionLimits {661	pub fn with_default_limits(collection_type: CollectionMode) -> Self {662		CollectionLimits {663			account_token_ownership_limit: Some(ACCOUNT_TOKEN_OWNERSHIP_LIMIT),664			sponsored_data_size: Some(CUSTOM_DATA_LIMIT),665			sponsored_data_rate_limit: Some(SponsoringRateLimit::SponsoringDisabled),666			token_limit: Some(COLLECTION_TOKEN_LIMIT),667			sponsor_transfer_timeout: match collection_type {668				CollectionMode::NFT => Some(NFT_SPONSOR_TRANSFER_TIMEOUT),669				CollectionMode::ReFungible => Some(REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT),670				CollectionMode::Fungible(_) => Some(FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT),671			},672			sponsor_approve_timeout: Some(SPONSOR_APPROVE_TIMEOUT),673			owner_can_transfer: Some(false),674			owner_can_destroy: Some(true),675			transfers_enabled: Some(true),676		}677	}678679	/// Get effective value for [`account_token_ownership_limit`](self.account_token_ownership_limit).680	pub fn account_token_ownership_limit(&self) -> u32 {681		self.account_token_ownership_limit682			.unwrap_or(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)683			.min(MAX_TOKEN_OWNERSHIP)684	}685686	/// Get effective value for [`sponsored_data_size`](self.sponsored_data_size).687	pub fn sponsored_data_size(&self) -> u32 {688		self.sponsored_data_size689			.unwrap_or(CUSTOM_DATA_LIMIT)690			.min(CUSTOM_DATA_LIMIT)691	}692693	/// Get effective value for [`token_limit`](self.token_limit).694	pub fn token_limit(&self) -> u32 {695		self.token_limit696			.unwrap_or(COLLECTION_TOKEN_LIMIT)697			.min(COLLECTION_TOKEN_LIMIT)698	}699700	// TODO: may be replace u32 to mode?701	/// Get effective value for [`sponsor_transfer_timeout`](self.sponsor_transfer_timeout).702	pub fn sponsor_transfer_timeout(&self, default: u32) -> u32 {703		self.sponsor_transfer_timeout704			.unwrap_or(default)705			.min(MAX_SPONSOR_TIMEOUT)706	}707708	/// Get effective value for [`sponsor_approve_timeout`](self.sponsor_approve_timeout).709	pub fn sponsor_approve_timeout(&self) -> u32 {710		self.sponsor_approve_timeout711			.unwrap_or(SPONSOR_APPROVE_TIMEOUT)712			.min(MAX_SPONSOR_TIMEOUT)713	}714715	/// Get effective value for [`owner_can_transfer`](self.owner_can_transfer).716	pub fn owner_can_transfer(&self) -> bool {717		self.owner_can_transfer.unwrap_or(false)718	}719720	/// Get effective value for [`owner_can_transfer_instaled`](self.owner_can_transfer_instaled).721	pub fn owner_can_transfer_instaled(&self) -> bool {722		self.owner_can_transfer.is_some()723	}724725	/// Get effective value for [`owner_can_destroy`](self.owner_can_destroy).726	pub fn owner_can_destroy(&self) -> bool {727		self.owner_can_destroy.unwrap_or(true)728	}729730	/// Get effective value for [`transfers_enabled`](self.transfers_enabled).731	pub fn transfers_enabled(&self) -> bool {732		self.transfers_enabled.unwrap_or(true)733	}734735	/// Get effective value for [`sponsored_data_rate_limit`](self.sponsored_data_rate_limit).736	pub fn sponsored_data_rate_limit(&self) -> Option<u32> {737		match self738			.sponsored_data_rate_limit739			.unwrap_or(SponsoringRateLimit::SponsoringDisabled)740		{741			SponsoringRateLimit::SponsoringDisabled => None,742			SponsoringRateLimit::Blocks(v) => Some(v.min(MAX_SPONSOR_TIMEOUT)),743		}744	}745}746747/// Permissions on certain operations within a collection.748///749/// Some fields are wrapped in [`Option`], where `None` means chain default.750///751/// Update with `pallet_common::Pallet::clamp_permissions`.752#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]753#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]754// When adding/removing fields from this struct - don't forget to also update `pallet_common::Pallet::clamp_permissions`.755// TODO: move `pallet_common::Pallet::clamp_permissions` into `impl CollectionPermissions`.756pub struct CollectionPermissions {757	/// Access mode.758	///759	/// * Default - [`AccessMode::Normal`].760	pub access: Option<AccessMode>,761762	/// Minting allowance.763	///764	/// * Default - **false**.765	pub mint_mode: Option<bool>,766767	/// Permissions for nesting.768	///769	/// * Default770	///   - `token_owner` - **false**771	///   - `collection_admin` - **false**772	///   - `restricted` - **None**773	pub nesting: Option<NestingPermissions>,774}775776impl CollectionPermissions {777	/// Get effective value for [`access`](self.access).778	pub fn access(&self) -> AccessMode {779		self.access.unwrap_or(AccessMode::Normal)780	}781782	/// Get effective value for [`mint_mode`](self.mint_mode).783	pub fn mint_mode(&self) -> bool {784		self.mint_mode.unwrap_or(false)785	}786787	/// Get effective value for [`nesting`](self.nesting).788	pub fn nesting(&self) -> &NestingPermissions {789		static DEFAULT: NestingPermissions = NestingPermissions {790			token_owner: false,791			collection_admin: false,792			restricted: None,793			#[cfg(feature = "runtime-benchmarks")]794			permissive: false,795		};796		self.nesting.as_ref().unwrap_or(&DEFAULT)797	}798}799800/// Inner set for collections allowed to nest.801type OwnerRestrictedSetInner = BoundedBTreeSet<CollectionId, ConstU32<16>>;802803/// Wraper for collections set allowing nest.804#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]805#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]806#[derivative(Debug)]807pub struct OwnerRestrictedSet(808	#[cfg_attr(feature = "serde1", serde(with = "bounded::set_serde"))]809	#[derivative(Debug(format_with = "bounded::set_debug"))]810	pub OwnerRestrictedSetInner,811);812813impl OwnerRestrictedSet {814	/// Create new set.815	pub fn new() -> Self {816		Self(Default::default())817	}818}819impl core::ops::Deref for OwnerRestrictedSet {820	type Target = OwnerRestrictedSetInner;821	fn deref(&self) -> &Self::Target {822		&self.0823	}824}825impl core::ops::DerefMut for OwnerRestrictedSet {826	fn deref_mut(&mut self) -> &mut Self::Target {827		&mut self.0828	}829}830831/// Part of collection permissions, if set, defines who is able to nest tokens into other tokens.832#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]833#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]834#[derivative(Debug)]835pub struct NestingPermissions {836	/// Owner of token can nest tokens under it.837	pub token_owner: bool,838	/// Admin of token collection can nest tokens under token.839	pub collection_admin: bool,840	/// If set - only tokens from specified collections can be nested.841	pub restricted: Option<OwnerRestrictedSet>,842843	#[cfg(feature = "runtime-benchmarks")]844	/// Anyone can nest tokens, mutually exclusive with `token_owner`, `admin`.845	pub permissive: bool,846}847848/// Enum denominating how often can sponsoring occur if it is enabled.849///850/// Used for [`collection limits`](CollectionLimits).851#[derive(Encode, Decode, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]852#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]853pub enum SponsoringRateLimit {854	/// Sponsoring is disabled, and the collection sponsor will not pay for transactions855	SponsoringDisabled,856	/// Once per how many blocks can sponsorship of a transaction type occur857	Blocks(u32),858}859860/// Data used to describe an NFT at creation.861#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]862#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]863#[derivative(Debug)]864pub struct CreateNftData {865	/// Key-value pairs used to describe the token as metadata866	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]867	#[derivative(Debug(format_with = "bounded::vec_debug"))]868	/// Properties that wil be assignet to created item.869	pub properties: CollectionPropertiesVec,870}871872/// Data used to describe a Fungible token at creation.873#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq, TypeInfo)]874#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]875pub struct CreateFungibleData {876	/// Number of fungible coins minted877	pub value: u128,878}879880/// Data used to describe a Refungible token at creation.881#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]882#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]883#[derivative(Debug)]884pub struct CreateReFungibleData {885	/// Number of pieces the RFT is split into886	pub pieces: u128,887888	/// Key-value pairs used to describe the token as metadata889	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]890	#[derivative(Debug(format_with = "bounded::vec_debug"))]891	pub properties: CollectionPropertiesVec,892}893894// TODO: remove this.895#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]896#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]897pub enum MetaUpdatePermission {898	ItemOwner,899	Admin,900	None,901}902903/// Enum holding data used for creation of all three item types.904/// Unified data for create item.905#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]906#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]907pub enum CreateItemData {908	/// Data for create NFT.909	NFT(CreateNftData),910	/// Data for create Fungible item.911	Fungible(CreateFungibleData),912	/// Data for create ReFungible item.913	ReFungible(CreateReFungibleData),914}915916/// Extended data for create NFT.917#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]918#[derivative(Debug)]919pub struct CreateNftExData<CrossAccountId> {920	/// Properties that wil be assignet to created item.921	#[derivative(Debug(format_with = "bounded::vec_debug"))]922	pub properties: CollectionPropertiesVec,923924	/// Owner of creating item.925	pub owner: CrossAccountId,926}927928/// Extended data for create ReFungible item.929#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]930#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]931pub struct CreateRefungibleExMultipleOwners<CrossAccountId> {932	#[derivative(Debug(format_with = "bounded::map_debug"))]933	pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,934	#[derivative(Debug(format_with = "bounded::vec_debug"))]935	pub properties: CollectionPropertiesVec,936}937938/// Extended data for create ReFungible item.939#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]940#[derivative(Debug(bound = "CrossAccountId: fmt::Debug"))]941pub struct CreateRefungibleExSingleOwner<CrossAccountId> {942	pub user: CrossAccountId,943	pub pieces: u128,944	#[derivative(Debug(format_with = "bounded::vec_debug"))]945	pub properties: CollectionPropertiesVec,946}947948/// Unified extended data for creating item.949#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]950#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]951pub enum CreateItemExData<CrossAccountId> {952	/// Extended data for create NFT.953	NFT(954		#[derivative(Debug(format_with = "bounded::vec_debug"))]955		BoundedVec<CreateNftExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,956	),957958	/// Extended data for create Fungible item.959	Fungible(960		#[derivative(Debug(format_with = "bounded::map_debug"))]961		BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,962	),963964	/// Extended data for create ReFungible item in case of965	/// many tokens, each may have only one owner966	RefungibleMultipleItems(967		#[derivative(Debug(format_with = "bounded::vec_debug"))]968		BoundedVec<CreateRefungibleExSingleOwner<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,969	),970971	/// Extended data for create ReFungible item in case of972	/// single token, which may have many owners973	RefungibleMultipleOwners(CreateRefungibleExMultipleOwners<CrossAccountId>),974}975976impl From<CreateNftData> for CreateItemData {977	fn from(item: CreateNftData) -> Self {978		CreateItemData::NFT(item)979	}980}981982impl From<CreateReFungibleData> for CreateItemData {983	fn from(item: CreateReFungibleData) -> Self {984		CreateItemData::ReFungible(item)985	}986}987988impl From<CreateFungibleData> for CreateItemData {989	fn from(item: CreateFungibleData) -> Self {990		CreateItemData::Fungible(item)991	}992}993994/// Token's address, dictated by its collection and token IDs.995#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]996#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]997// todo possibly rename to be used generally as an address pair998pub struct TokenChild {999	/// Token id.1000	pub token: TokenId,10011002	/// Collection id.1003	pub collection: CollectionId,1004}10051006/// Collection statistics.1007#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]1008#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1009pub struct CollectionStats {1010	/// Number of created items.1011	pub created: u32,10121013	/// Number of burned items.1014	pub destroyed: u32,10151016	/// Number of current items.1017	pub alive: u32,1018}10191020/// This type works like [`PhantomData`] but supports generating _scale-info_ descriptions to generate node metadata.1021#[derive(Encode, Decode, Clone, Debug)]1022#[cfg_attr(feature = "std", derive(PartialEq))]1023pub struct PhantomType<T>(core::marker::PhantomData<T>);10241025impl<T: TypeInfo + 'static> TypeInfo for PhantomType<T> {1026	type Identity = PhantomType<T>;10271028	fn type_info() -> scale_info::Type {1029		use scale_info::{1030			Type, Path,1031			build::{FieldsBuilder, UnnamedFields},1032			form::MetaForm,1033			type_params,1034		};1035		Type::builder()1036			.path(Path::new("up_data_structs", "PhantomType"))1037			.type_params(type_params!(T))1038			.composite(1039				<FieldsBuilder<MetaForm, UnnamedFields>>::default().field(|b| b.ty::<[T; 0]>()),1040			)1041	}1042}1043impl<T> MaxEncodedLen for PhantomType<T> {1044	fn max_encoded_len() -> usize {1045		01046	}1047}10481049/// Bounded vector of bytes.1050pub type BoundedBytes<S> = BoundedVec<u8, S>;10511052/// Extra properties for external collections.1053pub type AuxPropertyValue = BoundedBytes<ConstU32<MAX_AUX_PROPERTY_VALUE_LENGTH>>;10541055/// Property key.1056pub type PropertyKey = BoundedBytes<ConstU32<MAX_PROPERTY_KEY_LENGTH>>;10571058/// Property value.1059pub type PropertyValue = BoundedBytes<ConstU32<MAX_PROPERTY_VALUE_LENGTH>>;10601061/// Property permission.1062#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone, Default)]1063#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1064pub struct PropertyPermission {1065	/// Permission to change the property and property permission.1066	///1067	/// If it **false** then you can not change corresponding property even if [`collection_admin`] and [`token_owner`] are **true**.1068	pub mutable: bool,10691070	/// Change permission for the collection administrator.1071	pub collection_admin: bool,10721073	/// Permission to change the property for the owner of the token.1074	pub token_owner: bool,1075}10761077impl PropertyPermission {1078	/// Creates mutable property permission but changes restricted for collection admin and token owner.1079	pub fn none() -> Self {1080		Self {1081			mutable: true,1082			collection_admin: false,1083			token_owner: false,1084		}1085	}1086}10871088/// Property is simpl key-value record.1089#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, MaxEncodedLen)]1090#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1091pub struct Property {1092	/// Property key.1093	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1094	pub key: PropertyKey,10951096	/// Property value.1097	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1098	pub value: PropertyValue,1099}11001101impl Into<(PropertyKey, PropertyValue)> for Property {1102	fn into(self) -> (PropertyKey, PropertyValue) {1103		(self.key, self.value)1104	}1105}11061107/// Record for proprty key permission.1108#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]1109#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1110pub struct PropertyKeyPermission {1111	/// Key.1112	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1113	pub key: PropertyKey,11141115	/// Permission.1116	pub permission: PropertyPermission,1117}11181119impl Into<(PropertyKey, PropertyPermission)> for PropertyKeyPermission {1120	fn into(self) -> (PropertyKey, PropertyPermission) {1121		(self.key, self.permission)1122	}1123}11241125/// Errors for properties actions.1126#[derive(Debug)]1127pub enum PropertiesError {1128	/// The space allocated for properties has run out.1129	///1130	/// * Limit for colection - [`MAX_COLLECTION_PROPERTIES_SIZE`].1131	/// * Limit for token - [`MAX_TOKEN_PROPERTIES_SIZE`].1132	NoSpaceForProperty,11331134	/// The property limit has been reached.1135	///1136	/// * Limit - [`MAX_PROPERTIES_PER_ITEM`].1137	PropertyLimitReached,11381139	/// Property key contains not allowed character.1140	InvalidCharacterInPropertyKey,11411142	/// Property key length is too long.1143	///1144	/// * Limit - [`MAX_PROPERTY_KEY_LENGTH`].1145	PropertyKeyIsTooLong,11461147	/// Property key is empty.1148	EmptyPropertyKey,1149}11501151/// Token owner error: it could be either `NotFound` ot `MultipleOwners`.1152#[derive(Debug)]1153pub enum TokenOwnerError {1154	NotFound,1155	MultipleOwners,1156}11571158/// Marker for scope of property.1159///1160/// Scoped property can't be changed by user. Used for external collections.1161#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Clone, Copy)]1162pub enum PropertyScope {1163	None,1164	Rmrk,1165}11661167impl PropertyScope {1168	pub fn prefix(&self) -> &'static [u8] {1169		match self {1170			Self::None => b"",1171			Self::Rmrk => b"rmrk:",1172		}1173	}1174	/// Apply scope to property key.1175	pub fn apply(self, key: PropertyKey) -> Result<PropertyKey, PropertiesError> {1176		let prefix = self.prefix();1177		if prefix == b"" {1178			return Ok(key);1179		}1180		[prefix, key.as_slice()]1181			.concat()1182			.try_into()1183			.map_err(|_| PropertiesError::PropertyKeyIsTooLong)1184	}1185}11861187/// Trait for operate with properties.1188pub trait TrySetProperty: Sized {1189	type Value;11901191	/// Try to set property with scope.1192	fn try_scoped_set(1193		&mut self,1194		scope: PropertyScope,1195		key: PropertyKey,1196		value: Self::Value,1197	) -> Result<Option<Self::Value>, PropertiesError>;11981199	/// Try to set property with scope from iterator.1200	fn try_scoped_set_from_iter<I, KV>(1201		&mut self,1202		scope: PropertyScope,1203		iter: I,1204	) -> Result<(), PropertiesError>1205	where1206		I: Iterator<Item = KV>,1207		KV: Into<(PropertyKey, Self::Value)>,1208	{1209		for kv in iter {1210			let (key, value) = kv.into();1211			self.try_scoped_set(scope, key, value)?;1212		}12131214		Ok(())1215	}12161217	/// Try to set property.1218	fn try_set(1219		&mut self,1220		key: PropertyKey,1221		value: Self::Value,1222	) -> Result<Option<Self::Value>, PropertiesError> {1223		self.try_scoped_set(PropertyScope::None, key, value)1224	}12251226	/// Try to set property from iterator.1227	fn try_set_from_iter<I, KV>(&mut self, iter: I) -> Result<(), PropertiesError>1228	where1229		I: Iterator<Item = KV>,1230		KV: Into<(PropertyKey, Self::Value)>,1231	{1232		self.try_scoped_set_from_iter(PropertyScope::None, iter)1233	}1234}12351236/// Wrapped map for storing properties.1237#[derive(Encode, Decode, TypeInfo, Derivative, Clone, PartialEq, MaxEncodedLen)]1238#[derivative(Default(bound = ""))]1239pub struct PropertiesMap<Value>(1240	BoundedBTreeMap<PropertyKey, Value, ConstU32<MAX_PROPERTIES_PER_ITEM>>,1241);12421243impl<Value> PropertiesMap<Value> {1244	/// Create new property map.1245	pub fn new() -> Self {1246		Self(BoundedBTreeMap::new())1247	}12481249	/// Remove property from map.1250	pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<Value>, PropertiesError> {1251		Self::check_property_key(key)?;12521253		Ok(self.0.remove(key))1254	}12551256	/// Get property with appropriate key from map.1257	pub fn get(&self, key: &PropertyKey) -> Option<&Value> {1258		self.0.get(key)1259	}12601261	/// Check if map contains key.1262	pub fn contains_key(&self, key: &PropertyKey) -> bool {1263		self.0.contains_key(key)1264	}12651266	/// Check if map contains key with key validation.1267	fn check_property_key(key: &PropertyKey) -> Result<(), PropertiesError> {1268		if key.is_empty() {1269			return Err(PropertiesError::EmptyPropertyKey);1270		}12711272		for byte in key.as_slice().iter() {1273			let byte = *byte;12741275			if !byte.is_ascii_alphanumeric() && byte != b'_' && byte != b'-' && byte != b'.' {1276				return Err(PropertiesError::InvalidCharacterInPropertyKey);1277			}1278		}12791280		Ok(())1281	}12821283	pub fn values(&self) -> impl Iterator<Item = &Value> {1284		self.0.values()1285	}12861287	pub fn iter(&self) -> impl Iterator<Item = (&PropertyKey, &Value)> {1288		self.0.iter()1289	}1290}12911292impl<Value> IntoIterator for PropertiesMap<Value> {1293	type Item = (PropertyKey, Value);1294	type IntoIter = <1295		BoundedBTreeMap<1296			PropertyKey,1297			Value,1298			ConstU32<MAX_PROPERTIES_PER_ITEM>1299		> as IntoIterator1300	>::IntoIter;13011302	fn into_iter(self) -> Self::IntoIter {1303		self.0.into_iter()1304	}1305}13061307impl<Value> TrySetProperty for PropertiesMap<Value> {1308	type Value = Value;13091310	fn try_scoped_set(1311		&mut self,1312		scope: PropertyScope,1313		key: PropertyKey,1314		value: Self::Value,1315	) -> Result<Option<Self::Value>, PropertiesError> {1316		Self::check_property_key(&key)?;13171318		let key = scope.apply(key)?;1319		self.01320			.try_insert(key, value)1321			.map_err(|_| PropertiesError::PropertyLimitReached)1322	}1323}13241325/// Alias for property permissions map.1326pub type PropertiesPermissionMap = PropertiesMap<PropertyPermission>;13271328fn slice_size(data: &[u8]) -> u32 {1329	scoped_slice_size(PropertyScope::None, data)1330}1331fn scoped_slice_size(scope: PropertyScope, data: &[u8]) -> u32 {1332	use codec::Compact;1333	let prefix = scope.prefix();1334	<Compact<u32>>::encoded_size(&Compact(data.len() as u32 + prefix.len() as u32)) as u321335		+ data.len() as u321336		+ prefix.len() as u321337}13381339/// Wrapper for properties map with consumed space control.1340#[derive(Encode, Decode, TypeInfo, Clone, PartialEq)]1341pub struct Properties<const S: u32> {1342	map: PropertiesMap<PropertyValue>,1343	consumed_space: u32,1344	// May be not zero, previously served as a current S generic1345	_reserved: u32,1346}13471348impl<const S: u32> MaxEncodedLen for Properties<S> {1349	fn max_encoded_len() -> usize {1350		// len of map + len of consumed_space + len of space_limit1351		u32::max_encoded_len() * 3 + S as usize1352	}1353}13541355impl<const S: u32> Default for Properties<S> {1356	fn default() -> Self {1357		Self::new()1358	}1359}13601361impl<const S: u32> Properties<S> {1362	/// Create new properies container.1363	pub fn new() -> Self {1364		Self {1365			map: PropertiesMap::new(),1366			consumed_space: 0,1367			_reserved: 0,1368		}1369	}13701371	/// Remove propery with appropiate key.1372	pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<PropertyValue>, PropertiesError> {1373		let value = self.map.remove(key)?;13741375		if let Some(ref value) = value {1376			let kv_len = slice_size(key) + slice_size(value);1377			self.consumed_space = self.consumed_space.saturating_sub(kv_len);1378		}13791380		Ok(value)1381	}13821383	/// Get property with appropriate key.1384	pub fn get(&self, key: &PropertyKey) -> Option<&PropertyValue> {1385		self.map.get(key)1386	}13871388	/// Recomputes the consumed space for the current properties state.1389	/// Needed to repair a token due to a bug fixed in the [PR #733](https://github.com/UniqueNetwork/unique-chain/pull/773).1390	pub fn recompute_consumed_space(&mut self) {1391		self.consumed_space = self1392			.map1393			.iter()1394			.map(|(key, value)| slice_size(key) + slice_size(value))1395			.sum();1396	}1397}13981399impl<const S: u32> IntoIterator for Properties<S> {1400	type Item = (PropertyKey, PropertyValue);1401	type IntoIter = <PropertiesMap<PropertyValue> as IntoIterator>::IntoIter;14021403	fn into_iter(self) -> Self::IntoIter {1404		self.map.into_iter()1405	}1406}14071408impl<const S: u32> TrySetProperty for Properties<S> {1409	type Value = PropertyValue;14101411	fn try_scoped_set(1412		&mut self,1413		scope: PropertyScope,1414		key: PropertyKey,1415		value: Self::Value,1416	) -> Result<Option<Self::Value>, PropertiesError> {1417		let key_size = scoped_slice_size(scope, &key);1418		let value_size = slice_size(&value) as u32;14191420		if self.consumed_space + value_size + key_size > S && !cfg!(feature = "runtime-benchmarks")1421		{1422			return Err(PropertiesError::NoSpaceForProperty);1423		}14241425		let old_value = self.map.try_scoped_set(scope, key, value)?;14261427		if let Some(old_value) = old_value.as_ref() {1428			let old_value_size = slice_size(&old_value);1429			self.consumed_space = self.consumed_space.saturating_sub(old_value_size) + value_size;1430		} else {1431			self.consumed_space += key_size + value_size;1432		}14331434		Ok(old_value)1435	}1436}14371438pub type CollectionProperties = Properties<MAX_COLLECTION_PROPERTIES_SIZE>;1439pub type TokenProperties = Properties<MAX_TOKEN_PROPERTIES_SIZE>;
after · primitives/data-structs/src/lib.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/>.1617//! # Primitives crate.18//!19//! This crate contains types, traits and constants.2021#![cfg_attr(not(feature = "std"), no_std)]2223use core::{24	convert::{TryFrom, TryInto},25	fmt,26	ops::Deref,27};28use frame_support::storage::{bounded_btree_map::BoundedBTreeMap, bounded_btree_set::BoundedBTreeSet};2930#[cfg(feature = "serde")]31use serde::{Serialize, Deserialize};3233use sp_core::U256;34use sp_runtime::{ArithmeticError, sp_std::prelude::Vec};35use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};36use bondrewd::Bitfields;37use frame_support::{BoundedVec, traits::ConstU32};38use derivative::Derivative;39use scale_info::TypeInfo;4041mod bondrewd_codec;42mod bounded;43pub mod budget;44pub mod mapping;45mod migration;4647/// Maximum of decimal points.48pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;4950/// Maximum pieces for refungible token.51pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;52pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;5354/// Maximum tokens for user.55pub const MAX_TOKEN_OWNERSHIP: u32 = if cfg!(not(feature = "limit-testing")) {56	100_00057} else {58	1059};6061/// Maximum for collections can be created.62pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {63	100_00064} else {65	1066};6768/// Maximum for various custom data of token.69pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {70	204871} else {72	1073};7475/// Maximum admins per collection.76pub const COLLECTION_ADMINS_LIMIT: u32 = 5;7778/// Maximum tokens per collection.79pub const COLLECTION_TOKEN_LIMIT: u32 = u32::MAX;8081/// Maximum tokens per account.82pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {83	1_000_00084} else {85	1086};8788/// Default timeout for transfer sponsoring NFT item.89pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;90/// Default timeout for transfer sponsoring fungible item.91pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;92/// Default timeout for transfer sponsoring refungible item.93pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;9495/// Default timeout for sponsored approving.96pub const SPONSOR_APPROVE_TIMEOUT: u32 = 5;9798// Schema limits99pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 8192;100pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 8192;101pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 32768;102103// TODO: not used. Delete?104pub const COLLECTION_FIELD_LIMIT: u32 = CONST_ON_CHAIN_SCHEMA_LIMIT;105106/// Maximal length of a collection name.107pub const MAX_COLLECTION_NAME_LENGTH: u32 = 64;108109/// Maximal length of a collection description.110pub const MAX_COLLECTION_DESCRIPTION_LENGTH: u32 = 256;111112/// Maximal length of a token prefix.113pub const MAX_TOKEN_PREFIX_LENGTH: u32 = 16;114115/// Maximal length of a property key.116pub const MAX_PROPERTY_KEY_LENGTH: u32 = 256;117118/// Maximal length of a property value.119pub const MAX_PROPERTY_VALUE_LENGTH: u32 = 32768;120121/// A maximum number of token properties.122pub const MAX_PROPERTIES_PER_ITEM: u32 = 64;123124/// Maximal lenght of extended property value.125pub const MAX_AUX_PROPERTY_VALUE_LENGTH: u32 = 2048;126127/// Maximum size for all collection properties.128pub const MAX_COLLECTION_PROPERTIES_SIZE: u32 = 40960;129130/// Maximum size of all token properties.131pub const MAX_TOKEN_PROPERTIES_SIZE: u32 = 32768;132133/// How much items can be created per single134/// create_many call.135pub const MAX_ITEMS_PER_BATCH: u32 = 200;136137/// Used for limit bounded types of token custom data.138pub type CustomDataLimit = ConstU32<CUSTOM_DATA_LIMIT>;139140/// Collection id.141#[derive(142	Encode,143	Decode,144	PartialEq,145	Eq,146	PartialOrd,147	Ord,148	Clone,149	Copy,150	Debug,151	Default,152	TypeInfo,153	MaxEncodedLen,154)]155#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]156pub struct CollectionId(pub u32);157impl EncodeLike<u32> for CollectionId {}158impl EncodeLike<CollectionId> for u32 {}159160impl From<u32> for CollectionId {161	fn from(value: u32) -> Self {162		Self(value)163	}164}165166/// Token id.167#[derive(168	Encode,169	Decode,170	PartialEq,171	Eq,172	PartialOrd,173	Ord,174	Clone,175	Copy,176	Debug,177	Default,178	TypeInfo,179	MaxEncodedLen,180)]181#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]182pub struct TokenId(pub u32);183impl EncodeLike<u32> for TokenId {}184impl EncodeLike<TokenId> for u32 {}185186impl TokenId {187	/// Try to get next token id.188	///189	/// If next id cause overflow, then [`ArithmeticError::Overflow`] returned.190	pub fn try_next(self) -> Result<TokenId, ArithmeticError> {191		self.0192			.checked_add(1)193			.ok_or(ArithmeticError::Overflow)194			.map(Self)195	}196}197198impl From<TokenId> for U256 {199	fn from(t: TokenId) -> Self {200		t.0.into()201	}202}203204impl TryFrom<U256> for TokenId {205	type Error = &'static str;206207	fn try_from(value: U256) -> Result<Self, Self::Error> {208		Ok(TokenId(value.try_into().map_err(|_| "too large token id")?))209	}210}211212/// Token data.213#[struct_versioning::versioned(version = 2, upper)]214#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]215#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]216pub struct TokenData<CrossAccountId> {217	/// Properties of token.218	pub properties: Vec<Property>,219220	/// Token owner.221	pub owner: Option<CrossAccountId>,222223	/// Token pieces.224	#[version(2.., upper(0))]225	pub pieces: u128,226}227228// TODO: unused type229pub struct OverflowError;230impl From<OverflowError> for &'static str {231	fn from(_: OverflowError) -> Self {232		"overflow occured"233	}234}235236/// Alias for decimal points type.237pub type DecimalPoints = u8;238239/// Collection mode.240///241/// Collection can represent various types of tokens.242/// Each collection can contain only one type of tokens at a time.243/// This type helps to understand which tokens the collection contains.244#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]245#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]246pub enum CollectionMode {247	/// Non fungible tokens.248	NFT,249	/// Fungible tokens.250	Fungible(DecimalPoints),251	/// Refungible tokens.252	ReFungible,253}254255impl CollectionMode {256	/// Get collection mod as number.257	pub fn id(&self) -> u8 {258		match self {259			CollectionMode::NFT => 1,260			CollectionMode::Fungible(_) => 2,261			CollectionMode::ReFungible => 3,262		}263	}264}265266// TODO: unused trait267pub trait SponsoringResolve<AccountId, Call> {268	fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;269}270271/// Access mode for some token operations.272#[derive(Encode, Decode, Eq, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]273#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]274pub enum AccessMode {275	/// Access grant for owner and admins. Used as default.276	Normal,277	/// Like a [`Normal`](AccessMode::Normal) but also users in allow list.278	AllowList,279}280impl Default for AccessMode {281	fn default() -> Self {282		Self::Normal283	}284}285286// TODO: remove in future.287#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]288#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]289pub enum SchemaVersion {290	ImageURL,291	Unique,292}293impl Default for SchemaVersion {294	fn default() -> Self {295		Self::ImageURL296	}297}298299// TODO: unused type300#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]301#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]302pub struct Ownership<AccountId> {303	pub owner: AccountId,304	pub fraction: u128,305}306307/// The state of collection sponsorship.308#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]309#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]310pub enum SponsorshipState<AccountId> {311	/// The fees are applied to the transaction sender.312	Disabled,313	/// The sponsor is under consideration. Until the sponsor gives his consent,314	/// the fee will still be charged to sender.315	Unconfirmed(AccountId),316	/// Transactions are sponsored by specified account.317	Confirmed(AccountId),318}319320impl<AccountId> SponsorshipState<AccountId> {321	/// Get a sponsor of the collection who has confirmed his status.322	pub fn sponsor(&self) -> Option<&AccountId> {323		match self {324			Self::Confirmed(sponsor) => Some(sponsor),325			_ => None,326		}327	}328329	/// Get a sponsor of the collection who has pending or confirmed status.330	pub fn pending_sponsor(&self) -> Option<&AccountId> {331		match self {332			Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),333			_ => None,334		}335	}336337	/// Whether the sponsorship is confirmed.338	pub fn confirmed(&self) -> bool {339		matches!(self, Self::Confirmed(_))340	}341}342343impl<T> Default for SponsorshipState<T> {344	fn default() -> Self {345		Self::Disabled346	}347}348349pub type CollectionName = BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>;350pub type CollectionDescription = BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>;351pub type CollectionTokenPrefix = BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>;352353#[derive(Bitfields, Clone, Copy, PartialEq, Eq, Debug, Default)]354#[bondrewd(enforce_bytes = 1)]355pub struct CollectionFlags {356	/// Tokens in foreign collections can be transferred, but not burnt357	#[bondrewd(bits = "0..1")]358	pub foreign: bool,359	/// Supports ERC721Metadata360	#[bondrewd(bits = "1..2")]361	pub erc721metadata: bool,362	/// External collections can't be managed using `unique` api363	#[bondrewd(bits = "7..8")]364	pub external: bool,365366	#[bondrewd(reserve, bits = "2..7")]367	pub reserved: u8,368}369bondrewd_codec!(CollectionFlags);370371/// Base structure for represent collection.372///373/// Used to provide basic functionality for all types of collections.374///375/// #### Note376/// Collection parameters, used in storage (see [`RpcCollection`] for the RPC version).377#[struct_versioning::versioned(version = 2, upper)]378#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen)]379pub struct Collection<AccountId> {380	/// Collection owner account.381	pub owner: AccountId,382383	/// Collection mode.384	pub mode: CollectionMode,385386	/// Access mode.387	#[version(..2)]388	pub access: AccessMode,389390	/// Collection name.391	pub name: CollectionName,392393	/// Collection description.394	pub description: CollectionDescription,395396	/// Token prefix.397	pub token_prefix: CollectionTokenPrefix,398399	#[version(..2)]400	pub mint_mode: bool,401402	#[version(..2)]403	pub offchain_schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,404405	#[version(..2)]406	pub schema_version: SchemaVersion,407408	/// The state of sponsorship of the collection.409	pub sponsorship: SponsorshipState<AccountId>,410411	/// Collection limits.412	pub limits: CollectionLimits,413414	/// Collection permissions.415	#[version(2.., upper(Default::default()))]416	pub permissions: CollectionPermissions,417418	#[version(2.., upper(Default::default()))]419	pub flags: CollectionFlags,420421	#[version(..2)]422	pub variable_on_chain_schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>,423424	#[version(..2)]425	pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,426427	#[version(..2)]428	pub meta_update_permission: MetaUpdatePermission,429}430431#[derive(Debug, Encode, Decode, Clone, PartialEq, TypeInfo)]432#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]433pub struct RpcCollectionFlags {434	/// Is collection is foreign.435	pub foreign: bool,436	/// Collection supports ERC721Metadata.437	pub erc721metadata: bool,438}439440/// Collection parameters, used in RPC calls (see [`Collection`] for the storage version).441#[struct_versioning::versioned(version = 2, upper)]442#[derive(Debug, Encode, Decode, Clone, PartialEq, TypeInfo)]443#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]444pub struct RpcCollection<AccountId> {445	/// Collection owner account.446	pub owner: AccountId,447448	/// Collection mode.449	pub mode: CollectionMode,450451	/// Collection name.452	pub name: Vec<u16>,453454	/// Collection description.455	pub description: Vec<u16>,456457	/// Token prefix.458	pub token_prefix: Vec<u8>,459460	/// The state of sponsorship of the collection.461	pub sponsorship: SponsorshipState<AccountId>,462463	/// Collection limits.464	pub limits: CollectionLimits,465466	/// Collection permissions.467	pub permissions: CollectionPermissions,468469	/// Token property permissions.470	pub token_property_permissions: Vec<PropertyKeyPermission>,471472	/// Collection properties.473	pub properties: Vec<Property>,474475	/// Is collection read only.476	pub read_only: bool,477478	/// Extra collection flags479	#[version(2.., upper(RpcCollectionFlags {foreign: false, erc721metadata: false}))]480	pub flags: RpcCollectionFlags,481}482483impl<AccountId> From<CollectionVersion1<AccountId>> for RpcCollection<AccountId> {484	fn from(value: CollectionVersion1<AccountId>) -> Self {485		let CollectionVersion1 {486			name,487			description,488			owner,489			mode,490			access,491			token_prefix,492			mint_mode,493			sponsorship,494			limits,495			..496		} = value;497498		RpcCollection {499			name: name.into_inner(),500			description: description.into_inner(),501			owner,502			mode,503			token_prefix: token_prefix.into_inner(),504			sponsorship,505			limits,506			permissions: CollectionPermissions {507				access: Some(access),508				mint_mode: Some(mint_mode),509				nesting: None,510			},511			token_property_permissions: Vec::default(),512			properties: Vec::default(),513			read_only: true,514515			flags: RpcCollectionFlags {516				foreign: false,517				erc721metadata: false,518			},519		}520	}521}522523pub struct RawEncoded(Vec<u8>);524525impl codec::Decode for RawEncoded {526	fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {527		let mut out = Vec::new();528		while let Ok(v) = input.read_byte() {529			out.push(v);530		}531		Ok(Self(out))532	}533}534535impl Deref for RawEncoded {536	type Target = Vec<u8>;537538	fn deref(&self) -> &Self::Target {539		&self.0540	}541}542543/// Data used for create collection.544///545/// All fields are wrapped in [`Option`], where `None` means chain default.546#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, Derivative, MaxEncodedLen)]547#[derivative(Debug, Default(bound = ""))]548pub struct CreateCollectionData<AccountId> {549	/// Collection mode.550	#[derivative(Default(value = "CollectionMode::NFT"))]551	pub mode: CollectionMode,552553	/// Access mode.554	pub access: Option<AccessMode>,555556	/// Collection name.557	pub name: CollectionName,558559	/// Collection description.560	pub description: CollectionDescription,561562	/// Token prefix.563	pub token_prefix: CollectionTokenPrefix,564565	/// Pending collection sponsor.566	pub pending_sponsor: Option<AccountId>,567568	/// Collection limits.569	pub limits: Option<CollectionLimits>,570571	/// Collection permissions.572	pub permissions: Option<CollectionPermissions>,573574	/// Token property permissions.575	pub token_property_permissions: CollectionPropertiesPermissionsVec,576577	/// Collection properties.578	pub properties: CollectionPropertiesVec,579}580581/// Bounded vector of properties permissions. Max length is [`MAX_PROPERTIES_PER_ITEM`].582// TODO: maybe rename to PropertiesPermissionsVec583pub type CollectionPropertiesPermissionsVec =584	BoundedVec<PropertyKeyPermission, ConstU32<MAX_PROPERTIES_PER_ITEM>>;585586/// Bounded vector of properties. Max length is [`MAX_PROPERTIES_PER_ITEM`].587pub type CollectionPropertiesVec = BoundedVec<Property, ConstU32<MAX_PROPERTIES_PER_ITEM>>;588589/// Limits and restrictions of a collection.590///591/// All fields are wrapped in [`Option`], where `None` means chain default.592///593/// Update with `pallet_common::Pallet::clamp_limits`.594// IMPORTANT: When adding/removing fields from this struct - don't forget to also595#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]596#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]597// When adding/removing fields from this struct - don't forget to also update with `pallet_common::Pallet::clamp_limits`.598// TODO: move `pallet_common::Pallet::clamp_limits` into `impl CollectionLimits`.599// TODO: may be remove [`Option`] and **pub** from fields and create struct with default values.600pub struct CollectionLimits {601	/// How many tokens can a user have on one account.602	/// * Default - [`ACCOUNT_TOKEN_OWNERSHIP_LIMIT`].603	/// * Limit - [`MAX_TOKEN_OWNERSHIP`].604	pub account_token_ownership_limit: Option<u32>,605606	/// How many bytes of data are available for sponsorship.607	/// * Default - [`CUSTOM_DATA_LIMIT`].608	/// * Limit - [`CUSTOM_DATA_LIMIT`].609	pub sponsored_data_size: Option<u32>,610611	// FIXME should we delete this or repurpose it?612	/// Times in how many blocks we sponsor data.613	///614	/// If is `Some(v)` then **setVariableMetadata** is sponsored if there is `v` block between transactions.615	///616	/// * Default - [`SponsoringDisabled`](SponsoringRateLimit::SponsoringDisabled).617	/// * Limit - [`MAX_SPONSOR_TIMEOUT`].618	///619	/// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]620	pub sponsored_data_rate_limit: Option<SponsoringRateLimit>,621	/// Maximum amount of tokens inside the collection. Chain default: [`COLLECTION_TOKEN_LIMIT`]622623	/// How many tokens can be mined into this collection.624	///625	/// * Default - [`COLLECTION_TOKEN_LIMIT`].626	/// * Limit - [`COLLECTION_TOKEN_LIMIT`].627	pub token_limit: Option<u32>,628629	/// Timeouts for transfer sponsoring.630	///631	/// * Default632	///   - **Fungible** - [`FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT`]633	///   - **NFT** - [`NFT_SPONSOR_TRANSFER_TIMEOUT`]634	///   - **Refungible** - [`REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT`]635	/// * Limit - [`MAX_SPONSOR_TIMEOUT`].636	pub sponsor_transfer_timeout: Option<u32>,637638	/// Timeout for sponsoring an approval in passed blocks.639	///640	/// * Default - [`SPONSOR_APPROVE_TIMEOUT`].641	/// * Limit - [`MAX_SPONSOR_TIMEOUT`].642	pub sponsor_approve_timeout: Option<u32>,643644	/// Whether the collection owner of the collection can send tokens (which belong to other users).645	///646	/// * Default - **false**.647	pub owner_can_transfer: Option<bool>,648649	/// Can the collection owner burn other people's tokens.650	///651	/// * Default - **true**.652	pub owner_can_destroy: Option<bool>,653654	/// Is it possible to send tokens from this collection between users.655	///656	/// * Default - **true**.657	pub transfers_enabled: Option<bool>,658}659660impl CollectionLimits {661	pub fn with_default_limits(collection_type: CollectionMode) -> Self {662		CollectionLimits {663			account_token_ownership_limit: Some(ACCOUNT_TOKEN_OWNERSHIP_LIMIT),664			sponsored_data_size: Some(CUSTOM_DATA_LIMIT),665			sponsored_data_rate_limit: Some(SponsoringRateLimit::SponsoringDisabled),666			token_limit: Some(COLLECTION_TOKEN_LIMIT),667			sponsor_transfer_timeout: match collection_type {668				CollectionMode::NFT => Some(NFT_SPONSOR_TRANSFER_TIMEOUT),669				CollectionMode::ReFungible => Some(REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT),670				CollectionMode::Fungible(_) => Some(FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT),671			},672			sponsor_approve_timeout: Some(SPONSOR_APPROVE_TIMEOUT),673			owner_can_transfer: Some(false),674			owner_can_destroy: Some(true),675			transfers_enabled: Some(true),676		}677	}678679	/// Get effective value for [`account_token_ownership_limit`](self.account_token_ownership_limit).680	pub fn account_token_ownership_limit(&self) -> u32 {681		self.account_token_ownership_limit682			.unwrap_or(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)683			.min(MAX_TOKEN_OWNERSHIP)684	}685686	/// Get effective value for [`sponsored_data_size`](self.sponsored_data_size).687	pub fn sponsored_data_size(&self) -> u32 {688		self.sponsored_data_size689			.unwrap_or(CUSTOM_DATA_LIMIT)690			.min(CUSTOM_DATA_LIMIT)691	}692693	/// Get effective value for [`token_limit`](self.token_limit).694	pub fn token_limit(&self) -> u32 {695		self.token_limit696			.unwrap_or(COLLECTION_TOKEN_LIMIT)697			.min(COLLECTION_TOKEN_LIMIT)698	}699700	// TODO: may be replace u32 to mode?701	/// Get effective value for [`sponsor_transfer_timeout`](self.sponsor_transfer_timeout).702	pub fn sponsor_transfer_timeout(&self, default: u32) -> u32 {703		self.sponsor_transfer_timeout704			.unwrap_or(default)705			.min(MAX_SPONSOR_TIMEOUT)706	}707708	/// Get effective value for [`sponsor_approve_timeout`](self.sponsor_approve_timeout).709	pub fn sponsor_approve_timeout(&self) -> u32 {710		self.sponsor_approve_timeout711			.unwrap_or(SPONSOR_APPROVE_TIMEOUT)712			.min(MAX_SPONSOR_TIMEOUT)713	}714715	/// Get effective value for [`owner_can_transfer`](self.owner_can_transfer).716	pub fn owner_can_transfer(&self) -> bool {717		self.owner_can_transfer.unwrap_or(false)718	}719720	/// Get effective value for [`owner_can_transfer_instaled`](self.owner_can_transfer_instaled).721	pub fn owner_can_transfer_instaled(&self) -> bool {722		self.owner_can_transfer.is_some()723	}724725	/// Get effective value for [`owner_can_destroy`](self.owner_can_destroy).726	pub fn owner_can_destroy(&self) -> bool {727		self.owner_can_destroy.unwrap_or(true)728	}729730	/// Get effective value for [`transfers_enabled`](self.transfers_enabled).731	pub fn transfers_enabled(&self) -> bool {732		self.transfers_enabled.unwrap_or(true)733	}734735	/// Get effective value for [`sponsored_data_rate_limit`](self.sponsored_data_rate_limit).736	pub fn sponsored_data_rate_limit(&self) -> Option<u32> {737		match self738			.sponsored_data_rate_limit739			.unwrap_or(SponsoringRateLimit::SponsoringDisabled)740		{741			SponsoringRateLimit::SponsoringDisabled => None,742			SponsoringRateLimit::Blocks(v) => Some(v.min(MAX_SPONSOR_TIMEOUT)),743		}744	}745}746747/// Permissions on certain operations within a collection.748///749/// Some fields are wrapped in [`Option`], where `None` means chain default.750///751/// Update with `pallet_common::Pallet::clamp_permissions`.752#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]753#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]754// When adding/removing fields from this struct - don't forget to also update `pallet_common::Pallet::clamp_permissions`.755// TODO: move `pallet_common::Pallet::clamp_permissions` into `impl CollectionPermissions`.756pub struct CollectionPermissions {757	/// Access mode.758	///759	/// * Default - [`AccessMode::Normal`].760	pub access: Option<AccessMode>,761762	/// Minting allowance.763	///764	/// * Default - **false**.765	pub mint_mode: Option<bool>,766767	/// Permissions for nesting.768	///769	/// * Default770	///   - `token_owner` - **false**771	///   - `collection_admin` - **false**772	///   - `restricted` - **None**773	pub nesting: Option<NestingPermissions>,774}775776impl CollectionPermissions {777	/// Get effective value for [`access`](self.access).778	pub fn access(&self) -> AccessMode {779		self.access.unwrap_or(AccessMode::Normal)780	}781782	/// Get effective value for [`mint_mode`](self.mint_mode).783	pub fn mint_mode(&self) -> bool {784		self.mint_mode.unwrap_or(false)785	}786787	/// Get effective value for [`nesting`](self.nesting).788	pub fn nesting(&self) -> &NestingPermissions {789		static DEFAULT: NestingPermissions = NestingPermissions {790			token_owner: false,791			collection_admin: false,792			restricted: None,793			#[cfg(feature = "runtime-benchmarks")]794			permissive: false,795		};796		self.nesting.as_ref().unwrap_or(&DEFAULT)797	}798}799800/// Inner set for collections allowed to nest.801type OwnerRestrictedSetInner = BoundedBTreeSet<CollectionId, ConstU32<16>>;802803/// Wraper for collections set allowing nest.804#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]805#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]806#[derivative(Debug)]807pub struct OwnerRestrictedSet(808	#[cfg_attr(feature = "serde1", serde(with = "bounded::set_serde"))]809	#[derivative(Debug(format_with = "bounded::set_debug"))]810	pub OwnerRestrictedSetInner,811);812813impl OwnerRestrictedSet {814	/// Create new set.815	pub fn new() -> Self {816		Self(Default::default())817	}818}819impl Default for OwnerRestrictedSet {820	fn default() -> Self {821		Self::new()822	}823}824impl core::ops::Deref for OwnerRestrictedSet {825	type Target = OwnerRestrictedSetInner;826	fn deref(&self) -> &Self::Target {827		&self.0828	}829}830impl core::ops::DerefMut for OwnerRestrictedSet {831	fn deref_mut(&mut self) -> &mut Self::Target {832		&mut self.0833	}834}835836/// Part of collection permissions, if set, defines who is able to nest tokens into other tokens.837#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]838#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]839#[derivative(Debug)]840pub struct NestingPermissions {841	/// Owner of token can nest tokens under it.842	pub token_owner: bool,843	/// Admin of token collection can nest tokens under token.844	pub collection_admin: bool,845	/// If set - only tokens from specified collections can be nested.846	pub restricted: Option<OwnerRestrictedSet>,847848	#[cfg(feature = "runtime-benchmarks")]849	/// Anyone can nest tokens, mutually exclusive with `token_owner`, `admin`.850	pub permissive: bool,851}852853/// Enum denominating how often can sponsoring occur if it is enabled.854///855/// Used for [`collection limits`](CollectionLimits).856#[derive(Encode, Decode, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]857#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]858pub enum SponsoringRateLimit {859	/// Sponsoring is disabled, and the collection sponsor will not pay for transactions860	SponsoringDisabled,861	/// Once per how many blocks can sponsorship of a transaction type occur862	Blocks(u32),863}864865/// Data used to describe an NFT at creation.866#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]867#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]868#[derivative(Debug)]869pub struct CreateNftData {870	/// Key-value pairs used to describe the token as metadata871	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]872	#[derivative(Debug(format_with = "bounded::vec_debug"))]873	/// Properties that wil be assignet to created item.874	pub properties: CollectionPropertiesVec,875}876877/// Data used to describe a Fungible token at creation.878#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq, TypeInfo)]879#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]880pub struct CreateFungibleData {881	/// Number of fungible coins minted882	pub value: u128,883}884885/// Data used to describe a Refungible token at creation.886#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]887#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]888#[derivative(Debug)]889pub struct CreateReFungibleData {890	/// Number of pieces the RFT is split into891	pub pieces: u128,892893	/// Key-value pairs used to describe the token as metadata894	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]895	#[derivative(Debug(format_with = "bounded::vec_debug"))]896	pub properties: CollectionPropertiesVec,897}898899// TODO: remove this.900#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]901#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]902pub enum MetaUpdatePermission {903	ItemOwner,904	Admin,905	None,906}907908/// Enum holding data used for creation of all three item types.909/// Unified data for create item.910#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]911#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]912pub enum CreateItemData {913	/// Data for create NFT.914	NFT(CreateNftData),915	/// Data for create Fungible item.916	Fungible(CreateFungibleData),917	/// Data for create ReFungible item.918	ReFungible(CreateReFungibleData),919}920921/// Extended data for create NFT.922#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]923#[derivative(Debug)]924pub struct CreateNftExData<CrossAccountId> {925	/// Properties that wil be assignet to created item.926	#[derivative(Debug(format_with = "bounded::vec_debug"))]927	pub properties: CollectionPropertiesVec,928929	/// Owner of creating item.930	pub owner: CrossAccountId,931}932933/// Extended data for create ReFungible item.934#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]935#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]936pub struct CreateRefungibleExMultipleOwners<CrossAccountId> {937	#[derivative(Debug(format_with = "bounded::map_debug"))]938	pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,939	#[derivative(Debug(format_with = "bounded::vec_debug"))]940	pub properties: CollectionPropertiesVec,941}942943/// Extended data for create ReFungible item.944#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]945#[derivative(Debug(bound = "CrossAccountId: fmt::Debug"))]946pub struct CreateRefungibleExSingleOwner<CrossAccountId> {947	pub user: CrossAccountId,948	pub pieces: u128,949	#[derivative(Debug(format_with = "bounded::vec_debug"))]950	pub properties: CollectionPropertiesVec,951}952953/// Unified extended data for creating item.954#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]955#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]956pub enum CreateItemExData<CrossAccountId> {957	/// Extended data for create NFT.958	NFT(959		#[derivative(Debug(format_with = "bounded::vec_debug"))]960		BoundedVec<CreateNftExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,961	),962963	/// Extended data for create Fungible item.964	Fungible(965		#[derivative(Debug(format_with = "bounded::map_debug"))]966		BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,967	),968969	/// Extended data for create ReFungible item in case of970	/// many tokens, each may have only one owner971	RefungibleMultipleItems(972		#[derivative(Debug(format_with = "bounded::vec_debug"))]973		BoundedVec<CreateRefungibleExSingleOwner<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,974	),975976	/// Extended data for create ReFungible item in case of977	/// single token, which may have many owners978	RefungibleMultipleOwners(CreateRefungibleExMultipleOwners<CrossAccountId>),979}980981impl From<CreateNftData> for CreateItemData {982	fn from(item: CreateNftData) -> Self {983		CreateItemData::NFT(item)984	}985}986987impl From<CreateReFungibleData> for CreateItemData {988	fn from(item: CreateReFungibleData) -> Self {989		CreateItemData::ReFungible(item)990	}991}992993impl From<CreateFungibleData> for CreateItemData {994	fn from(item: CreateFungibleData) -> Self {995		CreateItemData::Fungible(item)996	}997}998999/// Token's address, dictated by its collection and token IDs.1000#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]1001#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1002// todo possibly rename to be used generally as an address pair1003pub struct TokenChild {1004	/// Token id.1005	pub token: TokenId,10061007	/// Collection id.1008	pub collection: CollectionId,1009}10101011/// Collection statistics.1012#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]1013#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1014pub struct CollectionStats {1015	/// Number of created items.1016	pub created: u32,10171018	/// Number of burned items.1019	pub destroyed: u32,10201021	/// Number of current items.1022	pub alive: u32,1023}10241025/// This type works like [`PhantomData`] but supports generating _scale-info_ descriptions to generate node metadata.1026#[derive(Encode, Decode, Clone, Debug)]1027#[cfg_attr(feature = "std", derive(PartialEq))]1028pub struct PhantomType<T>(core::marker::PhantomData<T>);10291030impl<T: TypeInfo + 'static> TypeInfo for PhantomType<T> {1031	type Identity = PhantomType<T>;10321033	fn type_info() -> scale_info::Type {1034		use scale_info::{1035			Type, Path,1036			build::{FieldsBuilder, UnnamedFields},1037			form::MetaForm,1038			type_params,1039		};1040		Type::builder()1041			.path(Path::new("up_data_structs", "PhantomType"))1042			.type_params(type_params!(T))1043			.composite(1044				<FieldsBuilder<MetaForm, UnnamedFields>>::default().field(|b| b.ty::<[T; 0]>()),1045			)1046	}1047}1048impl<T> MaxEncodedLen for PhantomType<T> {1049	fn max_encoded_len() -> usize {1050		01051	}1052}10531054/// Bounded vector of bytes.1055pub type BoundedBytes<S> = BoundedVec<u8, S>;10561057/// Extra properties for external collections.1058pub type AuxPropertyValue = BoundedBytes<ConstU32<MAX_AUX_PROPERTY_VALUE_LENGTH>>;10591060/// Property key.1061pub type PropertyKey = BoundedBytes<ConstU32<MAX_PROPERTY_KEY_LENGTH>>;10621063/// Property value.1064pub type PropertyValue = BoundedBytes<ConstU32<MAX_PROPERTY_VALUE_LENGTH>>;10651066/// Property permission.1067#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone, Default)]1068#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1069pub struct PropertyPermission {1070	/// Permission to change the property and property permission.1071	///1072	/// If it **false** then you can not change corresponding property even if [`collection_admin`] and [`token_owner`] are **true**.1073	pub mutable: bool,10741075	/// Change permission for the collection administrator.1076	pub collection_admin: bool,10771078	/// Permission to change the property for the owner of the token.1079	pub token_owner: bool,1080}10811082impl PropertyPermission {1083	/// Creates mutable property permission but changes restricted for collection admin and token owner.1084	pub fn none() -> Self {1085		Self {1086			mutable: true,1087			collection_admin: false,1088			token_owner: false,1089		}1090	}1091}10921093/// Property is simpl key-value record.1094#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, MaxEncodedLen)]1095#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1096pub struct Property {1097	/// Property key.1098	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1099	pub key: PropertyKey,11001101	/// Property value.1102	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1103	pub value: PropertyValue,1104}11051106impl From<Property> for (PropertyKey, PropertyValue) {1107	fn from(value: Property) -> Self {1108		(value.key, value.value)1109	}1110}11111112/// Record for proprty key permission.1113#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]1114#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1115pub struct PropertyKeyPermission {1116	/// Key.1117	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1118	pub key: PropertyKey,11191120	/// Permission.1121	pub permission: PropertyPermission,1122}11231124impl From<PropertyKeyPermission> for (PropertyKey, PropertyPermission) {1125	fn from(value: PropertyKeyPermission) -> Self {1126		(value.key, value.permission)1127	}1128}11291130/// Errors for properties actions.1131#[derive(Debug)]1132pub enum PropertiesError {1133	/// The space allocated for properties has run out.1134	///1135	/// * Limit for colection - [`MAX_COLLECTION_PROPERTIES_SIZE`].1136	/// * Limit for token - [`MAX_TOKEN_PROPERTIES_SIZE`].1137	NoSpaceForProperty,11381139	/// The property limit has been reached.1140	///1141	/// * Limit - [`MAX_PROPERTIES_PER_ITEM`].1142	PropertyLimitReached,11431144	/// Property key contains not allowed character.1145	InvalidCharacterInPropertyKey,11461147	/// Property key length is too long.1148	///1149	/// * Limit - [`MAX_PROPERTY_KEY_LENGTH`].1150	PropertyKeyIsTooLong,11511152	/// Property key is empty.1153	EmptyPropertyKey,1154}11551156/// Token owner error: it could be either `NotFound` ot `MultipleOwners`.1157#[derive(Debug)]1158pub enum TokenOwnerError {1159	NotFound,1160	MultipleOwners,1161}11621163/// Marker for scope of property.1164///1165/// Scoped property can't be changed by user. Used for external collections.1166#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Clone, Copy)]1167pub enum PropertyScope {1168	None,1169	Rmrk,1170}11711172impl PropertyScope {1173	pub fn prefix(&self) -> &'static [u8] {1174		match self {1175			Self::None => b"",1176			Self::Rmrk => b"rmrk:",1177		}1178	}1179	/// Apply scope to property key.1180	pub fn apply(self, key: PropertyKey) -> Result<PropertyKey, PropertiesError> {1181		let prefix = self.prefix();1182		if prefix == b"" {1183			return Ok(key);1184		}1185		[prefix, key.as_slice()]1186			.concat()1187			.try_into()1188			.map_err(|_| PropertiesError::PropertyKeyIsTooLong)1189	}1190}11911192/// Trait for operate with properties.1193pub trait TrySetProperty: Sized {1194	type Value;11951196	/// Try to set property with scope.1197	fn try_scoped_set(1198		&mut self,1199		scope: PropertyScope,1200		key: PropertyKey,1201		value: Self::Value,1202	) -> Result<Option<Self::Value>, PropertiesError>;12031204	/// Try to set property with scope from iterator.1205	fn try_scoped_set_from_iter<I, KV>(1206		&mut self,1207		scope: PropertyScope,1208		iter: I,1209	) -> Result<(), PropertiesError>1210	where1211		I: Iterator<Item = KV>,1212		KV: Into<(PropertyKey, Self::Value)>,1213	{1214		for kv in iter {1215			let (key, value) = kv.into();1216			self.try_scoped_set(scope, key, value)?;1217		}12181219		Ok(())1220	}12211222	/// Try to set property.1223	fn try_set(1224		&mut self,1225		key: PropertyKey,1226		value: Self::Value,1227	) -> Result<Option<Self::Value>, PropertiesError> {1228		self.try_scoped_set(PropertyScope::None, key, value)1229	}12301231	/// Try to set property from iterator.1232	fn try_set_from_iter<I, KV>(&mut self, iter: I) -> Result<(), PropertiesError>1233	where1234		I: Iterator<Item = KV>,1235		KV: Into<(PropertyKey, Self::Value)>,1236	{1237		self.try_scoped_set_from_iter(PropertyScope::None, iter)1238	}1239}12401241/// Wrapped map for storing properties.1242#[derive(Encode, Decode, TypeInfo, Derivative, Clone, PartialEq, MaxEncodedLen)]1243#[derivative(Default(bound = ""))]1244pub struct PropertiesMap<Value>(1245	BoundedBTreeMap<PropertyKey, Value, ConstU32<MAX_PROPERTIES_PER_ITEM>>,1246);12471248impl<Value> PropertiesMap<Value> {1249	/// Create new property map.1250	pub fn new() -> Self {1251		Self(BoundedBTreeMap::new())1252	}12531254	/// Remove property from map.1255	pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<Value>, PropertiesError> {1256		Self::check_property_key(key)?;12571258		Ok(self.0.remove(key))1259	}12601261	/// Get property with appropriate key from map.1262	pub fn get(&self, key: &PropertyKey) -> Option<&Value> {1263		self.0.get(key)1264	}12651266	/// Check if map contains key.1267	pub fn contains_key(&self, key: &PropertyKey) -> bool {1268		self.0.contains_key(key)1269	}12701271	/// Check if map contains key with key validation.1272	fn check_property_key(key: &PropertyKey) -> Result<(), PropertiesError> {1273		if key.is_empty() {1274			return Err(PropertiesError::EmptyPropertyKey);1275		}12761277		for byte in key.as_slice().iter() {1278			let byte = *byte;12791280			if !byte.is_ascii_alphanumeric() && byte != b'_' && byte != b'-' && byte != b'.' {1281				return Err(PropertiesError::InvalidCharacterInPropertyKey);1282			}1283		}12841285		Ok(())1286	}12871288	pub fn values(&self) -> impl Iterator<Item = &Value> {1289		self.0.values()1290	}12911292	pub fn iter(&self) -> impl Iterator<Item = (&PropertyKey, &Value)> {1293		self.0.iter()1294	}1295}12961297impl<Value> IntoIterator for PropertiesMap<Value> {1298	type Item = (PropertyKey, Value);1299	type IntoIter = <1300		BoundedBTreeMap<1301			PropertyKey,1302			Value,1303			ConstU32<MAX_PROPERTIES_PER_ITEM>1304		> as IntoIterator1305	>::IntoIter;13061307	fn into_iter(self) -> Self::IntoIter {1308		self.0.into_iter()1309	}1310}13111312impl<Value> TrySetProperty for PropertiesMap<Value> {1313	type Value = Value;13141315	fn try_scoped_set(1316		&mut self,1317		scope: PropertyScope,1318		key: PropertyKey,1319		value: Self::Value,1320	) -> Result<Option<Self::Value>, PropertiesError> {1321		Self::check_property_key(&key)?;13221323		let key = scope.apply(key)?;1324		self.01325			.try_insert(key, value)1326			.map_err(|_| PropertiesError::PropertyLimitReached)1327	}1328}13291330/// Alias for property permissions map.1331pub type PropertiesPermissionMap = PropertiesMap<PropertyPermission>;13321333fn slice_size(data: &[u8]) -> u32 {1334	scoped_slice_size(PropertyScope::None, data)1335}1336fn scoped_slice_size(scope: PropertyScope, data: &[u8]) -> u32 {1337	use codec::Compact;1338	let prefix = scope.prefix();1339	<Compact<u32>>::encoded_size(&Compact(data.len() as u32 + prefix.len() as u32)) as u321340		+ data.len() as u321341		+ prefix.len() as u321342}13431344/// Wrapper for properties map with consumed space control.1345#[derive(Encode, Decode, TypeInfo, Clone, PartialEq)]1346pub struct Properties<const S: u32> {1347	map: PropertiesMap<PropertyValue>,1348	consumed_space: u32,1349	// May be not zero, previously served as a current S generic1350	_reserved: u32,1351}13521353impl<const S: u32> MaxEncodedLen for Properties<S> {1354	fn max_encoded_len() -> usize {1355		// len of map + len of consumed_space + len of space_limit1356		u32::max_encoded_len() * 3 + S as usize1357	}1358}13591360impl<const S: u32> Default for Properties<S> {1361	fn default() -> Self {1362		Self::new()1363	}1364}13651366impl<const S: u32> Properties<S> {1367	/// Create new properies container.1368	pub fn new() -> Self {1369		Self {1370			map: PropertiesMap::new(),1371			consumed_space: 0,1372			_reserved: 0,1373		}1374	}13751376	/// Remove propery with appropiate key.1377	pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<PropertyValue>, PropertiesError> {1378		let value = self.map.remove(key)?;13791380		if let Some(ref value) = value {1381			let kv_len = slice_size(key) + slice_size(value);1382			self.consumed_space = self.consumed_space.saturating_sub(kv_len);1383		}13841385		Ok(value)1386	}13871388	/// Get property with appropriate key.1389	pub fn get(&self, key: &PropertyKey) -> Option<&PropertyValue> {1390		self.map.get(key)1391	}13921393	/// Recomputes the consumed space for the current properties state.1394	/// Needed to repair a token due to a bug fixed in the [PR #733](https://github.com/UniqueNetwork/unique-chain/pull/773).1395	pub fn recompute_consumed_space(&mut self) {1396		self.consumed_space = self1397			.map1398			.iter()1399			.map(|(key, value)| slice_size(key) + slice_size(value))1400			.sum();1401	}1402}14031404impl<const S: u32> IntoIterator for Properties<S> {1405	type Item = (PropertyKey, PropertyValue);1406	type IntoIter = <PropertiesMap<PropertyValue> as IntoIterator>::IntoIter;14071408	fn into_iter(self) -> Self::IntoIter {1409		self.map.into_iter()1410	}1411}14121413impl<const S: u32> TrySetProperty for Properties<S> {1414	type Value = PropertyValue;14151416	fn try_scoped_set(1417		&mut self,1418		scope: PropertyScope,1419		key: PropertyKey,1420		value: Self::Value,1421	) -> Result<Option<Self::Value>, PropertiesError> {1422		let key_size = scoped_slice_size(scope, &key);1423		let value_size = slice_size(&value);14241425		if self.consumed_space + value_size + key_size > S && !cfg!(feature = "runtime-benchmarks")1426		{1427			return Err(PropertiesError::NoSpaceForProperty);1428		}14291430		let old_value = self.map.try_scoped_set(scope, key, value)?;14311432		if let Some(old_value) = old_value.as_ref() {1433			let old_value_size = slice_size(old_value);1434			self.consumed_space = self.consumed_space.saturating_sub(old_value_size) + value_size;1435		} else {1436			self.consumed_space += key_size + value_size;1437		}14381439		Ok(old_value)1440	}1441}14421443pub type CollectionProperties = Properties<MAX_COLLECTION_PROPERTIES_SIZE>;1444pub type TokenProperties = Properties<MAX_TOKEN_PROPERTIES_SIZE>;
modifiedruntime/common/config/xcm/foreignassets.rsdiffbeforeafterboth
--- a/runtime/common/config/xcm/foreignassets.rs
+++ b/runtime/common/config/xcm/foreignassets.rs
@@ -65,7 +65,7 @@
 			return ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Here));
 		}
 
-		match XcmForeignAssetIdMapping::<Runtime>::get_currency_id(id.clone()) {
+		match XcmForeignAssetIdMapping::<Runtime>::get_currency_id(*id) {
 			Some(AssetIds::ForeignAssetId(foreign_asset_id)) => {
 				ConvertAssetId::convert_ref(AssetIds::ForeignAssetId(foreign_asset_id))
 			}
@@ -206,9 +206,7 @@
 			return Some(AssetIds::NativeAssetId(NativeCurrency::Parent));
 		}
 
-		if let Some(currency_id) =
-			XcmForeignAssetIdMapping::<Runtime>::get_currency_id(location.clone())
-		{
+		if let Some(currency_id) = XcmForeignAssetIdMapping::<Runtime>::get_currency_id(location) {
 			return Some(currency_id);
 		}
 
modifiedruntime/common/ethereum/precompiles/mod.rsdiffbeforeafterboth
--- a/runtime/common/ethereum/precompiles/mod.rs
+++ b/runtime/common/ethereum/precompiles/mod.rs
@@ -37,6 +37,16 @@
 		[hash(1), hash(20482)]
 	}
 }
+
+impl<R> Default for UniquePrecompiles<R>
+where
+	R: pallet_evm::Config,
+{
+	fn default() -> Self {
+		Self::new()
+	}
+}
+
 impl<R> PrecompileSet for UniquePrecompiles<R>
 where
 	R: pallet_evm::Config,
modifiedruntime/common/ethereum/precompiles/sr25519.rsdiffbeforeafterboth
--- a/runtime/common/ethereum/precompiles/sr25519.rs
+++ b/runtime/common/ethereum/precompiles/sr25519.rs
@@ -64,7 +64,7 @@
 
 		// Parse arguments
 		let public: sr25519::Public =
-			sr25519::Public::unchecked_from(input.read::<H256>(gasometer)?).into();
+			sr25519::Public::unchecked_from(input.read::<H256>(gasometer)?);
 		let signature_bytes: Vec<u8> = input.read::<Bytes>(gasometer)?.into();
 		let message: Vec<u8> = input.read::<Bytes>(gasometer)?.into();
 
modifiedruntime/common/ethereum/precompiles/utils/data.rsdiffbeforeafterboth
--- a/runtime/common/ethereum/precompiles/utils/data.rs
+++ b/runtime/common/ethereum/precompiles/utils/data.rs
@@ -60,7 +60,7 @@
 }
 
 impl Into<Vec<u8>> for Bytes {
-	fn into(self: Self) -> Vec<u8> {
+	fn into(self) -> Vec<u8> {
 		self.0
 	}
 }
modifiedruntime/common/ethereum/precompiles/utils/mod.rsdiffbeforeafterboth
--- a/runtime/common/ethereum/precompiles/utils/mod.rs
+++ b/runtime/common/ethereum/precompiles/utils/mod.rs
@@ -73,7 +73,6 @@
 		}
 	}
 
-	#[must_use]
 	/// Check that a function call is compatible with the context it is
 	/// called into.
 	pub fn check_function_modifier(
modifiedruntime/common/ethereum/sponsoring.rsdiffbeforeafterboth
--- a/runtime/common/ethereum/sponsoring.rs
+++ b/runtime/common/ethereum/sponsoring.rs
@@ -78,7 +78,7 @@
 							let token_id: TokenId = token_id.try_into().ok()?;
 							withdraw_set_token_property::<T>(
 								&collection,
-								&who,
+								who,
 								&token_id,
 								key.len() + value.len(),
 							)
@@ -88,7 +88,7 @@
 							ERC721UniqueExtensionsCall::Transfer { token_id, .. },
 						) => {
 							let token_id: TokenId = token_id.try_into().ok()?;
-							withdraw_transfer::<T>(&collection, &who, &token_id).map(|()| sponsor)
+							withdraw_transfer::<T>(&collection, who, &token_id).map(|()| sponsor)
 						}
 						UniqueNFTCall::ERC721UniqueMintable(
 							ERC721UniqueMintableCall::Mint { .. }
@@ -97,7 +97,7 @@
 							| ERC721UniqueMintableCall::MintWithTokenUriCheckId { .. },
 						) => withdraw_create_item::<T>(
 							&collection,
-							&who,
+							who,
 							&CreateItemData::NFT(CreateNftData::default()),
 						)
 						.map(|()| sponsor),
modifiedruntime/common/ethereum/sponsoring/refungible.rsdiffbeforeafterboth
--- a/runtime/common/ethereum/sponsoring/refungible.rs
+++ b/runtime/common/ethereum/sponsoring/refungible.rs
@@ -16,7 +16,6 @@
 
 //! Implements EVM sponsoring logic via TransactionValidityHack
 
-use core::convert::TryInto;
 use pallet_common::CollectionHandle;
 use pallet_evm::account::CrossAccountId;
 use pallet_fungible::Config as FungibleConfig;
@@ -95,7 +94,7 @@
 			..
 		} => {
 			let token_id = TokenId::try_from(token_id).ok()?;
-			withdraw_set_token_property::<T>(&collection, &who, &token_id, key.len() + value.len())
+			withdraw_set_token_property::<T>(&collection, who, &token_id, key.len() + value.len())
 		}
 	}
 }
@@ -242,7 +241,7 @@
 
 			MintCross { .. } => withdraw_create_item::<T>(
 				&collection,
-				&who,
+				who,
 				&CreateItemData::NFT(CreateNftData::default()),
 			),
 
@@ -250,7 +249,7 @@
 			| TransferFromCross { token_id, .. }
 			| Transfer { token_id, .. } => {
 				let token_id = TokenId::try_from(token_id).ok()?;
-				withdraw_transfer::<T>(&collection, &who, &token_id)
+				withdraw_transfer::<T>(&collection, who, &token_id)
 			}
 		}
 	}
@@ -275,7 +274,7 @@
 			| MintWithTokenUri { .. }
 			| MintWithTokenUriCheckId { .. } => withdraw_create_item::<T>(
 				&collection,
-				&who,
+				who,
 				&CreateItemData::NFT(CreateNftData::default()),
 			),
 		}
@@ -311,18 +310,15 @@
 
 			Transfer { .. } => {
 				let RefungibleTokenHandle(handle, token_id) = token;
-				let token_id = token_id.try_into().ok()?;
-				withdraw_transfer::<T>(&handle, &who, &token_id)
+				withdraw_transfer::<T>(&handle, who, &token_id)
 			}
 			TransferFrom { from, .. } => {
 				let RefungibleTokenHandle(handle, token_id) = token;
-				let token_id = token_id.try_into().ok()?;
 				let from = T::CrossAccountId::from_eth(from);
 				withdraw_transfer::<T>(&handle, &from, &token_id)
 			}
 			Approve { .. } => {
 				let RefungibleTokenHandle(handle, token_id) = token;
-				let token_id = token_id.try_into().ok()?;
 				withdraw_approve::<T>(&handle, who.as_sub(), &token_id)
 			}
 		}
@@ -351,13 +347,11 @@
 
 			TransferCross { .. } | TransferFromCross { .. } => {
 				let RefungibleTokenHandle(handle, token_id) = token;
-				let token_id = token_id.try_into().ok()?;
-				withdraw_transfer::<T>(&handle, &who, &token_id)
+				withdraw_transfer::<T>(&handle, who, &token_id)
 			}
 
 			ApproveCross { .. } => {
 				let RefungibleTokenHandle(handle, token_id) = token;
-				let token_id = token_id.try_into().ok()?;
 				withdraw_approve::<T>(&handle, who.as_sub(), &token_id)
 			}
 		}
modifiedruntime/common/mod.rsdiffbeforeafterboth
--- a/runtime/common/mod.rs
+++ b/runtime/common/mod.rs
@@ -204,10 +204,7 @@
 				&[],
 			);
 
-			let should_upgrade = match version {
-				None => true,
-				Some(_) => false,
-			};
+			let should_upgrade = version.is_none();
 
 			if should_upgrade {
 				log::info!(
@@ -220,7 +217,7 @@
 					.cloned()
 					.filter_map(|authority_id| {
 						weight.saturating_accrue(<Runtime as frame_system::Config>::DbWeight::get().reads_writes(1, 1));
-						let vec = authority_id.clone().to_raw_vec();
+						let vec = authority_id.to_raw_vec();
 						let slice = vec.as_slice();
 						let array: Option<[u8; 32]> = match slice.try_into() {
 							Ok(a) => Some(a),
@@ -248,20 +245,20 @@
 					.into_iter()
 					.map(|(acc, aura)| {
 						(
-							acc.clone(),                        // account id
-							acc,                                // validator id
-							SessionKeys { aura: aura.clone() }, // session keys
+							acc.clone(),          // account id
+							acc,                  // validator id
+							SessionKeys { aura }, // session keys
 						)
 					})
 					.collect::<Vec<_>>();
 
-				for (account, val, keys) in keys.iter().cloned() {
+				for (account, val, keys) in keys.iter() {
 					for id in <Runtime as pallet_session::Config>::Keys::key_ids() {
-						<pallet_session::KeyOwner<Runtime>>::insert((*id, keys.get_raw(*id)), &val)
+						<pallet_session::KeyOwner<Runtime>>::insert((*id, keys.get_raw(*id)), val)
 					}
-					<pallet_session::NextKeys<Runtime>>::insert(&val, &keys);
+					<pallet_session::NextKeys<Runtime>>::insert(val, keys);
 					// todo exercise caution, the following is taken from genesis
-					if frame_system::Pallet::<Runtime>::inc_consumers_without_limit(&account)
+					if frame_system::Pallet::<Runtime>::inc_consumers_without_limit(account)
 						.is_err()
 					{
 						log::warn!(
@@ -271,7 +268,7 @@
 						// genesis) so it's really not a big deal and we assume that the user wants to
 						// do this since it's the only way a non-endowed account can contain a session
 						// key.
-						frame_system::Pallet::<Runtime>::inc_providers(&account);
+						frame_system::Pallet::<Runtime>::inc_providers(account);
 					}
 				}
 
modifiedruntime/common/runtime_apis.rsdiffbeforeafterboth
--- a/runtime/common/runtime_apis.rs
+++ b/runtime/common/runtime_apis.rs
@@ -84,7 +84,7 @@
                 fn topmost_token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>, DispatchError> {
                     let budget = up_data_structs::budget::Value::new(10);
 
-                    Ok(<pallet_structure::Pallet<Runtime>>::find_topmost_owner(collection, token, &budget)?)
+                    <pallet_structure::Pallet<Runtime>>::find_topmost_owner(collection, token, &budget)
                 }
                 fn token_children(collection: CollectionId, token: TokenId) -> Result<Vec<TokenChild>, DispatchError> {
                     Ok(<pallet_nonfungible::Pallet<Runtime>>::token_children_ids(collection, token))
modifiedruntime/common/sponsoring.rsdiffbeforeafterboth
--- a/runtime/common/sponsoring.rs
+++ b/runtime/common/sponsoring.rs
@@ -240,7 +240,7 @@
 				withdraw_set_token_property(
 					&collection,
 					&T::CrossAccountId::from_sub(who.clone()),
-					&token_id,
+					token_id,
 					// No overflow may happen, as data larger than usize can't reach here
 					properties.iter().map(|p| p.key.len() + p.value.len()).sum(),
 				)
modifiedtest-pallets/utils/src/lib.rsdiffbeforeafterboth
--- a/test-pallets/utils/src/lib.rs
+++ b/test-pallets/utils/src/lib.rs
@@ -170,7 +170,7 @@
 	fn ensure_origin_and_enabled(origin: OriginFor<T>) -> DispatchResult {
 		ensure_signed(origin)?;
 		<Enabled<T>>::get()
-			.then(|| ())
+			.then_some(())
 			.ok_or(<Error<T>>::TestPalletDisabled.into())
 	}
 }