git.delta.rocks / unique-network / refs/commits / 00b9fd625e6d

difftreelog

feat initial rmrk send impl

Daniel Shiposha2022-06-03parent: #70623cc.patch.diff
in: master

10 files changed

modifiedpallets/common/src/lib.rsdiffbeforeafterboth
--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -1298,6 +1298,7 @@
 		spender: T::CrossAccountId,
 		token: TokenId,
 		amount: u128,
+		nesting_budget: &dyn Budget,
 	) -> DispatchResultWithPostInfo;
 	fn transfer_from(
 		&self,
modifiedpallets/fungible/src/common.rsdiffbeforeafterboth
--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -226,6 +226,7 @@
 		spender: T::CrossAccountId,
 		token: TokenId,
 		amount: u128,
+		_nesting_budget: &dyn Budget,
 	) -> DispatchResultWithPostInfo {
 		ensure!(
 			token == TokenId::default(),
modifiedpallets/nonfungible/src/common.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -308,14 +308,15 @@
 		spender: T::CrossAccountId,
 		token: TokenId,
 		amount: u128,
+		nesting_budget: &dyn Budget,
 	) -> DispatchResultWithPostInfo {
 		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);
 
 		with_weight(
 			if amount == 1 {
-				<Pallet<T>>::set_allowance(self, &sender, token, Some(&spender))
+				<Pallet<T>>::set_allowance(self, &sender, token, Some(&spender), nesting_budget)
 			} else {
-				<Pallet<T>>::set_allowance(self, &sender, token, None)
+				<Pallet<T>>::set_allowance(self, &sender, token, None, nesting_budget)
 			},
 			<CommonWeights<T>>::approve(),
 		)
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -269,8 +269,11 @@
 		let caller = T::CrossAccountId::from_eth(caller);
 		let approved = T::CrossAccountId::from_eth(approved);
 		let token = token_id.try_into()?;
+		let budget = self
+			.recorder
+			.weight_calls_budget(<StructureWeight<T>>::find_parent());
 
-		<Pallet<T>>::set_allowance(self, &caller, token, Some(&approved))
+		<Pallet<T>>::set_allowance(self, &caller, token, Some(&approved), &budget)
 			.map_err(dispatch_to_evm::<T>)?;
 		Ok(())
 	}
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -878,6 +878,7 @@
 		sender: &T::CrossAccountId,
 		token: TokenId,
 		spender: Option<&T::CrossAccountId>,
+		nesting_budget: &dyn Budget,
 	) -> DispatchResult {
 		if collection.permissions.access() == AccessMode::AllowList {
 			collection.check_allowlist(sender)?;
@@ -889,9 +890,16 @@
 		if let Some(spender) = spender {
 			<PalletCommon<T>>::ensure_correct_receiver(spender)?;
 		}
-		let token_data =
-			<TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;
-		if &token_data.owner != sender {
+
+		let is_owned = <PalletStructure<T>>::check_indirectly_owned(
+			sender.clone(),
+			collection.id,
+			token,
+			None,
+			nesting_budget
+		)?;
+
+		if !is_owned {
 			ensure!(
 				collection.ignores_owned_amount(sender),
 				<CommonError<T>>::CantApproveMoreThanOwned
@@ -918,6 +926,9 @@
 			// `from`, `to` checked in [`transfer`]
 			collection.check_allowlist(spender)?;
 		}
+		if <Allowance<T>>::get((collection.id, token)).as_ref() == Some(spender) {
+			return Ok(());
+		}
 		if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {
 			// TODO: should collection owner be allowed to perform this transfer?
 			ensure!(
@@ -930,9 +941,6 @@
 				)?,
 				<CommonError<T>>::ApprovedValueTooLow,
 			);
-			return Ok(());
-		}
-		if <Allowance<T>>::get((collection.id, token)).as_ref() == Some(spender) {
 			return Ok(());
 		}
 		ensure!(
modifiedpallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth
20use frame_system::{pallet_prelude::*, ensure_signed};20use frame_system::{pallet_prelude::*, ensure_signed};
21use sp_runtime::{DispatchError, Permill, traits::StaticLookup};21use sp_runtime::{DispatchError, Permill, traits::StaticLookup};
22use sp_std::vec::Vec;22use sp_std::vec::Vec;
23use up_data_structs::*;23use up_data_structs::{*, mapping::TokenAddressMapping};
24use pallet_common::{24use pallet_common::{
25 Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,25 Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,
26};26};
3939
40use RmrkProperty::*;40use RmrkProperty::*;
41
42const NESTING_BUDGET: u32 = 5;
4143
42#[frame_support::pallet]44#[frame_support::pallet]
43pub mod pallet {45pub mod pallet {
56 pub type CollectionIndex<T: Config> = StorageValue<_, RmrkCollectionId, ValueQuery>;58 pub type CollectionIndex<T: Config> = StorageValue<_, RmrkCollectionId, ValueQuery>;
5759
58 #[pallet::storage]60 #[pallet::storage]
59 #[pallet::getter(fn collection_index_map)]
60 pub type CollectionIndexMap<T: Config> =61 pub type UniqueCollectionId<T: Config> =
61 StorageMap<_, Twox64Concat, RmrkCollectionId, CollectionId, ValueQuery>;62 StorageMap<_, Twox64Concat, RmrkCollectionId, CollectionId, ValueQuery>;
63
64 #[pallet::storage]
65 pub type RmrkInernalCollectionId<T: Config> =
66 StorageMap<_, Twox64Concat, CollectionId, RmrkCollectionId, ValueQuery>;
6267
63 #[pallet::pallet]68 #[pallet::pallet]
64 #[pallet::generate_store(pub(super) trait Store)]69 #[pallet::generate_store(pub(super) trait Store)]
151 .into_inner()156 .into_inner()
152 .try_into()157 .try_into()
153 .map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,158 .map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,
159 permissions: Some(CollectionPermissions {
160 nesting: Some(NestingRule::Owner),
161 ..Default::default()
162 }),
154 ..Default::default()163 ..Default::default()
155 };164 };
156
157 <CollectionIndex<T>>::mutate(|n| *n += 1);
158165
159 let unique_collection_id = Self::init_collection(166 let unique_collection_id = Self::init_collection(
160 T::CrossAccountId::from_sub(sender.clone()),167 T::CrossAccountId::from_sub(sender.clone()),
167 )?;174 )?;
168 let rmrk_collection_id = <CollectionIndex<T>>::get();175 let rmrk_collection_id = <CollectionIndex<T>>::get();
169176
170 <CollectionIndexMap<T>>::insert(rmrk_collection_id, unique_collection_id);177 <UniqueCollectionId<T>>::insert(rmrk_collection_id, unique_collection_id);
178 <RmrkInernalCollectionId<T>>::insert(unique_collection_id, rmrk_collection_id);
179
180 <CollectionIndex<T>>::mutate(|n| *n += 1);
171181
172 Self::deposit_event(Event::CollectionCreated {182 Self::deposit_event(Event::CollectionCreated {
173 issuer: sender,183 issuer: sender,
354 Ok(())364 Ok(())
355 }365 }
366
367 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
368 #[transactional]
369 pub fn send(
370 origin: OriginFor<T>,
371 rmrk_collection_id: RmrkCollectionId,
372 rmrk_nft_id: RmrkNftId,
373 new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,
374 ) -> DispatchResult {
375 let sender = ensure_signed(origin.clone())?;
376 let cross_sender = T::CrossAccountId::from_sub(sender.clone());
377
378 let collection_id = Self::unique_collection_id(rmrk_collection_id)?;
379 let nft_id = rmrk_nft_id.into();
380
381 let token_data = <TokenData<T>>::get((collection_id, nft_id))
382 .ok_or(<Error<T>>::NoAvailableNftId)?;
383
384 let from = token_data.owner;
385
386 let collection = Self::get_typed_nft_collection(
387 collection_id,
388 misc::CollectionType::Regular,
389 )?;
390
391 let budget = budget::Value::new(NESTING_BUDGET);
392
393 let target_owner;
394
395 match new_owner {
396 RmrkAccountIdOrCollectionNftTuple::AccountId(account_id) => {
397 target_owner = T::CrossAccountId::from_sub(account_id);
398 },
399 RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(target_collection_id, target_nft_id) => {
400 let target_collection_id = Self::unique_collection_id(target_collection_id)?;
401
402 target_owner = T::CrossTokenAddressMapping::token_to_address(
403 target_collection_id,
404 target_nft_id.into(),
405 );
406
407 let spender = <PalletStructure<T>>::get_indirect_owner(
408 target_collection_id,
409 target_nft_id.into(),
410 Some((collection_id, nft_id)),
411 &budget,
412 )?;
413
414 let is_approval_required = cross_sender != spender;
415
416 if is_approval_required {
417 <PalletNft<T>>::set_allowance(
418 &collection,
419 &cross_sender,
420 nft_id,
421 Some(&spender),
422 &budget
423 ).map_err(Self::map_common_err_to_proxy)?;
424
425 return Ok(());
426 }
427 }
428 }
429
430 <PalletNft<T>>::transfer_from(
431 &collection,
432 &cross_sender,
433 &from,
434 &target_owner,
435 nft_id,
436 &budget
437 ).map_err(Self::map_common_err_to_proxy)?;
438
439 Ok(())
440 }
356441
357 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]442 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
358 #[transactional]443 #[transactional]
367 let sender = T::CrossAccountId::from_sub(sender);452 let sender = T::CrossAccountId::from_sub(sender);
368453
369 let collection_id = Self::unique_collection_id(rmrk_collection_id)?;454 let collection_id = Self::unique_collection_id(rmrk_collection_id)?;
455 let budget = budget::Value::new(NESTING_BUDGET);
370456
371 match maybe_nft_id {457 match maybe_nft_id {
372 Some(nft_id) => {458 Some(nft_id) => {
373 let token_id: TokenId = nft_id.into();459 let token_id: TokenId = nft_id.into();
374460
375 Self::ensure_nft_owner(collection_id, token_id, &sender)?;461 Self::ensure_nft_owner(collection_id, token_id, &sender, &budget)?;
376 Self::ensure_nft_type(collection_id, token_id, NftType::Regular)?;462 Self::ensure_nft_type(collection_id, token_id, NftType::Regular)?;
377463
378 <PalletNft<T>>::set_scoped_token_property(464 <PalletNft<T>>::set_scoped_token_property(
607 owner: owner.clone(),693 owner: owner.clone(),
608 };694 };
609695
610 let budget = budget::Value::new(2);696 let budget = budget::Value::new(NESTING_BUDGET);
611697
612 <PalletNft<T>>::create_item(collection, sender, data, &budget)?;698 <PalletNft<T>>::create_item(collection, sender, data, &budget)?;
613699
651 //ensure!(!Pallet::<T>::is_locked(collection_id, nft_id), pallet_uniques::Error::<T>::Locked);737 //ensure!(!Pallet::<T>::is_locked(collection_id, nft_id), pallet_uniques::Error::<T>::Locked);
652738
653 let sender = T::CrossAccountId::from_sub(sender);739 let sender = T::CrossAccountId::from_sub(sender);
654 let budget = budget::Value::new(10);740 let budget = budget::Value::new(NESTING_BUDGET);
655 let pending = !<PalletStructure<T>>::check_indirectly_owned(741 let pending = Self::ensure_nft_owner(collection_id, token_id, &sender, &budget).is_err();
656 sender.clone(),
657 collection_id,
658 token_id,
659 None,
660 &budget,
661 )?;
662742
663 let resource_collection_id: CollectionId =743 let resource_collection_id: CollectionId =
664 Self::get_nft_property_decoded(collection_id, token_id, ResourceCollection)?;744 Self::get_nft_property_decoded(collection_id, token_id, ResourceCollection)?;
757 pub fn unique_collection_id(837 pub fn unique_collection_id(
758 rmrk_collection_id: RmrkCollectionId,838 rmrk_collection_id: RmrkCollectionId,
759 ) -> Result<CollectionId, DispatchError> {839 ) -> Result<CollectionId, DispatchError> {
760 <CollectionIndexMap<T>>::try_get(rmrk_collection_id)840 <UniqueCollectionId<T>>::try_get(rmrk_collection_id)
761 .map_err(|_| <Error<T>>::CollectionUnknown.into())841 .map_err(|_| <Error<T>>::CollectionUnknown.into())
762 }842 }
843
844 pub fn rmrk_collection_id(
845 unique_collection_id: CollectionId
846 ) -> Result<RmrkCollectionId, DispatchError> {
847 <RmrkInernalCollectionId<T>>::try_get(unique_collection_id)
848 .map_err(|_| <Error<T>>::CollectionUnknown.into())
849 }
763850
764 pub fn get_nft_collection(851 pub fn get_nft_collection(
765 collection_id: CollectionId,852 collection_id: CollectionId,
873 collection_id: CollectionId,960 collection_id: CollectionId,
874 token_id: TokenId,961 token_id: TokenId,
875 possible_owner: &T::CrossAccountId,962 possible_owner: &T::CrossAccountId,
963 nesting_budget: &dyn budget::Budget
876 ) -> DispatchResult {964 ) -> DispatchResult {
877 let token_data =965 let is_owned = <PalletStructure<T>>::check_indirectly_owned(
966 possible_owner.clone(),
967 collection_id,
968 token_id,
969 None,
970 nesting_budget,
878 <TokenData<T>>::get((collection_id, token_id)).ok_or(<Error<T>>::NoAvailableNftId)?;971 )?;
879972
880 ensure!(973 ensure!(
881 token_data.owner == *possible_owner,974 is_owned,
882 <Error<T>>::NoPermission975 <Error<T>>::NoPermission
883 );976 );
884977
965 NoPermission => NoPermission,1058 NoPermission => NoPermission,
966 CollectionTokenLimitExceeded => CollectionFullOrLocked,1059 CollectionTokenLimitExceeded => CollectionFullOrLocked,
967 PublicMintingNotAllowed => NoPermission,1060 PublicMintingNotAllowed => NoPermission,
968 TokenNotFound => NoAvailableNftId1061 TokenNotFound => NoAvailableNftId,
1062 ApprovedValueTooLow => NoPermission
969 }1063 }
970 }1064 }
971 }1065 }
modifiedpallets/refungible/src/common.rsdiffbeforeafterboth
--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -254,6 +254,7 @@
 		spender: T::CrossAccountId,
 		token: TokenId,
 		amount: u128,
+		_nesting_budget: &dyn Budget,
 	) -> DispatchResultWithPostInfo {
 		with_weight(
 			<Pallet<T>>::set_allowance(self, &sender, &spender, token, amount),
modifiedpallets/structure/src/lib.rsdiffbeforeafterboth
--- a/pallets/structure/src/lib.rs
+++ b/pallets/structure/src/lib.rs
@@ -149,19 +149,12 @@
 		})
 	}
 
-	/// Check if token indirectly owned by specified user
-	pub fn check_indirectly_owned(
-		user: T::CrossAccountId,
+	pub fn get_indirect_owner(
 		collection: CollectionId,
 		token: TokenId,
 		for_nest: Option<(CollectionId, TokenId)>,
 		budget: &dyn Budget,
-	) -> Result<bool, DispatchError> {
-		let target_parent = match T::CrossTokenAddressMapping::address_to_token(&user) {
-			Some((collection, token)) => Self::find_topmost_owner(collection, token, budget)?,
-			None => user,
-		};
-
+	) -> Result<T::CrossAccountId, DispatchError> {
 		// Tried to nest token in itself
 		if Some((collection, token)) == for_nest {
 			return Err(<Error<T>>::OuroborosDetected.into());
@@ -173,10 +166,8 @@
 				Parent::Token(collection, token) if Some((collection, token)) == for_nest => {
 					return Err(<Error<T>>::OuroborosDetected.into())
 				}
-				// Found needed parent, token is indirecty owned
-				Parent::User(user) if user == target_parent => return Ok(true),
 				// Token is owned by other user
-				Parent::User(_) => return Ok(false),
+				Parent::User(user) => return Ok(user),
 				Parent::TokenNotFound => return Err(<Error<T>>::TokenNotFound.into()),
 				// Continue parent chain
 				Parent::Token(_, _) => {}
@@ -199,6 +190,27 @@
 		dispatch.burn_item_recursively(from.clone(), token, self_budget, breadth_budget)
 	}
 
+	/// Check if token indirectly owned by specified user
+	pub fn check_indirectly_owned(
+		user: T::CrossAccountId,
+		collection: CollectionId,
+		token: TokenId,
+		for_nest: Option<(CollectionId, TokenId)>,
+		budget: &dyn Budget,
+	) -> Result<bool, DispatchError> {
+		let target_parent = match T::CrossTokenAddressMapping::address_to_token(&user) {
+			Some((collection, token)) => Self::find_topmost_owner(collection, token, budget)?,
+			None => user,
+		};
+
+		Self::get_indirect_owner(
+			collection,
+			token,
+			for_nest,
+			budget
+		).map(|indirect_owner| indirect_owner == target_parent)
+	}
+
 	pub fn check_nesting(
 		from: T::CrossAccountId,
 		under: &T::CrossAccountId,
modifiedpallets/unique/src/lib.rsdiffbeforeafterboth
--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -815,8 +815,9 @@
 		#[transactional]
 		pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+			let budget = budget::Value::new(NESTING_BUDGET);
 
-			dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))
+			dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount, &budget))
 		}
 
 		/// Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.
modifiedruntime/common/src/runtime_apis.rsdiffbeforeafterboth
--- a/runtime/common/src/runtime_apis.rs
+++ b/runtime/common/src/runtime_apis.rs
@@ -147,7 +147,11 @@
                     use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};
                     use pallet_common::CommonCollectionOperations;
 
-                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;
+                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {
+                        Ok(id) => id,
+                        Err(_) => return Ok(None)
+                    };
+
                     let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {
                         Ok(c) => c,
                         Err(_) => return Ok(None),
@@ -169,7 +173,10 @@
                     use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};
                     use pallet_common::CommonCollectionOperations;
 
-                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;
+                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {
+                        Ok(id) => id,
+                        Err(_) => return Ok(None)
+                    };
                     let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {
                         Ok(c) => c,
                         Err(_) => return Ok(None),
@@ -180,7 +187,11 @@
 
                     let owner = match collection.token_owner(nft_id) {
                         Some(owner) => match <Runtime as pallet_common::Config>::CrossTokenAddressMapping::address_to_token(&owner) {
-                            Some((col, tok)) => RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(col.0, tok.0),
+                            Some((col, tok)) => {
+                                let rmrk_collection = RmrkCore::rmrk_collection_id(col)?;
+
+                                RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(rmrk_collection, tok.0)
+                            }
                             None => RmrkAccountIdOrCollectionNftTuple::AccountId(owner.as_sub().clone())
                         },
                         None => return Ok(None)
@@ -202,11 +213,11 @@
                     use pallet_common::CommonCollectionOperations;
 
                     let cross_account_id = CrossAccountId::from_sub(account_id);
-                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;
-                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {
-                        Ok(c) => c,
-                        Err(_) => return Ok(Vec::new()),
+                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {
+                        Ok(id) => id,
+                        Err(_) => return Ok(Vec::new())
                     };
+                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }
 
                     Ok(
                         collection.account_tokens(cross_account_id)
@@ -217,28 +228,35 @@
                 }
 
                 fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {
-                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;
+                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {
+                        Ok(id) => id,
+                        Err(_) => return Ok(Vec::new())
+                    };
                     let nft_id = TokenId(nft_id);
                     if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(Vec::new()); }
 
                     Ok(
                         pallet_nonfungible::TokenChildren::<Runtime>::iter_prefix((collection_id, nft_id))
-                            .filter_map(|(child_id, is_child)|
-                                match is_child {
-                                    true => Some(RmrkNftChild {
-                                        collection_id: child_id.0.0,
-                                        nft_id: child_id.1.0,
-                                    }),
-                                    false => None,
-                                }
-                            ).collect()
+                            .filter_map(|((child_collection, child_token), _)| {
+                                let rmrk_child_collection = RmrkCore::rmrk_collection_id(
+                                    child_collection
+                                ).ok()?;
+
+                                Some(RmrkNftChild {
+                                    collection_id: rmrk_child_collection,
+                                    nft_id: child_token.0,
+                                })
+                            }).collect()
                     )
                 }
 
                 fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
                     use pallet_proxy_rmrk_core::misc::CollectionType;
 
-                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;
+                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {
+                        Ok(id) => id,
+                        Err(_) => return Ok(Vec::new())
+                    };
                     if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() {
                         return Ok(Vec::new());
                     }
@@ -259,7 +277,10 @@
                 fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
                     use pallet_proxy_rmrk_core::misc::NftType;
 
-                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;
+                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {
+                        Ok(id) => id,
+                        Err(_) => return Ok(Vec::new())
+                    };
                     let token_id = TokenId(nft_id);
 
                     if RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Regular).is_err() {
@@ -283,7 +304,10 @@
                     use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, ResourceType}};
                     use pallet_common::CommonCollectionOperations;
 
-                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;
+                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {
+                        Ok(id) => id,
+                        Err(_) => return Ok(Vec::new())
+                    };
                     if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }
 
                     let nft_id = TokenId(nft_id);
@@ -332,7 +356,10 @@
                 fn nft_resource_priorities(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceId>, DispatchError> {
                     use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};
 
-                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;
+                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {
+                        Ok(id) => id,
+                        Err(_) => return Ok(Vec::new())
+                    };
                     if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }
 
                     let nft_id = TokenId(nft_id);
@@ -360,7 +387,10 @@
                         RmrkProperty, misc::{CollectionType},
                     };
 
-                    let collection_id = RmrkCore::unique_collection_id(base_id)?;
+                    let collection_id = match RmrkCore::unique_collection_id(base_id) {
+                        Ok(id) => id,
+                        Err(_) => return Ok(None)
+                    };
                     let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {
                         Ok(c) => c,
                         Err(_) => return Ok(None),
@@ -377,12 +407,11 @@
                     use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};
                     use pallet_common::CommonCollectionOperations;
 
-                    let collection_id = RmrkCore::unique_collection_id(base_id)?;
-                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {
-                        Ok(c) => c,
-                        Err(_) => return Ok(Vec::new()),
+                    let collection_id = match RmrkCore::unique_collection_id(base_id) {
+                        Ok(id) => id,
+                        Err(_) => return Ok(Vec::new())
                     };
-
+                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() { return Ok(Vec::new()); }
 
                     let parts = collection.collection_tokens()
                         .into_iter()
@@ -413,11 +442,13 @@
                     use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};
                     use pallet_common::CommonCollectionOperations;
 
-                    let collection_id = RmrkCore::unique_collection_id(base_id)?;
-                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {
-                        Ok(c) => c,
-                        Err(_) => return Ok(Vec::new()),
+                    let collection_id = match RmrkCore::unique_collection_id(base_id) {
+                        Ok(id) => id,
+                        Err(_) => return Ok(Vec::new())
                     };
+                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() {
+                        return Ok(Vec::new());
+                    }
 
 
                     let theme_names = collection.collection_tokens()
@@ -444,11 +475,13 @@
                     };
                     use pallet_common::CommonCollectionOperations;
 
-                    let collection_id = RmrkCore::unique_collection_id(base_id)?;
-                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {
-                        Ok(c) => c,
-                        Err(_) => return Ok(None),
+                    let collection_id = match RmrkCore::unique_collection_id(base_id) {
+                        Ok(id) => id,
+                        Err(_) => return Ok(None)
                     };
+                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() {
+                        return Ok(None);
+                    }
 
                     let theme_info = collection.collection_tokens()
                         .into_iter()