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
--- a/pallets/proxy-rmrk-core/src/lib.rs
+++ b/pallets/proxy-rmrk-core/src/lib.rs
@@ -20,7 +20,7 @@
 use frame_system::{pallet_prelude::*, ensure_signed};
 use sp_runtime::{DispatchError, Permill, traits::StaticLookup};
 use sp_std::vec::Vec;
-use up_data_structs::*;
+use up_data_structs::{*, mapping::TokenAddressMapping};
 use pallet_common::{
 	Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,
 };
@@ -39,6 +39,8 @@
 
 use RmrkProperty::*;
 
+const NESTING_BUDGET: u32 = 5;
+
 #[frame_support::pallet]
 pub mod pallet {
 	use super::*;
@@ -56,10 +58,13 @@
 	pub type CollectionIndex<T: Config> = StorageValue<_, RmrkCollectionId, ValueQuery>;
 
 	#[pallet::storage]
-	#[pallet::getter(fn collection_index_map)]
-	pub type CollectionIndexMap<T: Config> =
+	pub type UniqueCollectionId<T: Config> =
 		StorageMap<_, Twox64Concat, RmrkCollectionId, CollectionId, ValueQuery>;
 
+	#[pallet::storage]
+	pub type RmrkInernalCollectionId<T: Config> =
+		StorageMap<_, Twox64Concat, CollectionId, RmrkCollectionId, ValueQuery>;
+
 	#[pallet::pallet]
 	#[pallet::generate_store(pub(super) trait Store)]
 	pub struct Pallet<T>(_);
@@ -151,10 +156,12 @@
 					.into_inner()
 					.try_into()
 					.map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,
+				permissions: Some(CollectionPermissions {
+					nesting: Some(NestingRule::Owner),
+					..Default::default()
+				}),
 				..Default::default()
 			};
-
-			<CollectionIndex<T>>::mutate(|n| *n += 1);
 
 			let unique_collection_id = Self::init_collection(
 				T::CrossAccountId::from_sub(sender.clone()),
@@ -167,7 +174,10 @@
 			)?;
 			let rmrk_collection_id = <CollectionIndex<T>>::get();
 
-			<CollectionIndexMap<T>>::insert(rmrk_collection_id, unique_collection_id);
+			<UniqueCollectionId<T>>::insert(rmrk_collection_id, unique_collection_id);
+			<RmrkInernalCollectionId<T>>::insert(unique_collection_id, rmrk_collection_id);
+
+			<CollectionIndex<T>>::mutate(|n| *n += 1);
 
 			Self::deposit_event(Event::CollectionCreated {
 				issuer: sender,
@@ -356,6 +366,81 @@
 
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
+		pub fn send(
+			origin: OriginFor<T>,
+			rmrk_collection_id: RmrkCollectionId,
+			rmrk_nft_id: RmrkNftId,
+			new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,
+		) -> DispatchResult {
+			let sender = ensure_signed(origin.clone())?;
+			let cross_sender = T::CrossAccountId::from_sub(sender.clone());
+
+			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;
+			let nft_id = rmrk_nft_id.into();
+
+			let token_data = <TokenData<T>>::get((collection_id, nft_id))
+				.ok_or(<Error<T>>::NoAvailableNftId)?;
+
+			let from = token_data.owner;
+
+			let collection = Self::get_typed_nft_collection(
+				collection_id,
+				misc::CollectionType::Regular,
+			)?;
+
+			let budget = budget::Value::new(NESTING_BUDGET);
+
+			let target_owner;
+
+			match new_owner {
+				RmrkAccountIdOrCollectionNftTuple::AccountId(account_id) => {
+					target_owner = T::CrossAccountId::from_sub(account_id);
+				},
+				RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(target_collection_id, target_nft_id) => {
+					let target_collection_id = Self::unique_collection_id(target_collection_id)?;
+
+					target_owner = T::CrossTokenAddressMapping::token_to_address(
+						target_collection_id,
+						target_nft_id.into(),
+					);
+
+					let spender = <PalletStructure<T>>::get_indirect_owner(
+						target_collection_id,
+						target_nft_id.into(),
+						Some((collection_id, nft_id)),
+						&budget,
+					)?;
+
+					let is_approval_required = cross_sender != spender;
+
+					if is_approval_required {
+						<PalletNft<T>>::set_allowance(
+							&collection,
+							&cross_sender,
+							nft_id,
+							Some(&spender),
+							&budget
+						).map_err(Self::map_common_err_to_proxy)?;
+
+						return Ok(());
+					}
+				}
+			}
+
+			<PalletNft<T>>::transfer_from(
+				&collection,
+				&cross_sender,
+				&from,
+				&target_owner,
+				nft_id,
+				&budget
+			).map_err(Self::map_common_err_to_proxy)?;
+
+			Ok(())
+		}
+
+		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+		#[transactional]
 		pub fn set_property(
 			origin: OriginFor<T>,
 			#[pallet::compact] rmrk_collection_id: RmrkCollectionId,
@@ -367,12 +452,13 @@
 			let sender = T::CrossAccountId::from_sub(sender);
 
 			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;
+			let budget = budget::Value::new(NESTING_BUDGET);
 
 			match maybe_nft_id {
 				Some(nft_id) => {
 					let token_id: TokenId = nft_id.into();
 
-					Self::ensure_nft_owner(collection_id, token_id, &sender)?;
+					Self::ensure_nft_owner(collection_id, token_id, &sender, &budget)?;
 					Self::ensure_nft_type(collection_id, token_id, NftType::Regular)?;
 
 					<PalletNft<T>>::set_scoped_token_property(
@@ -607,7 +693,7 @@
 			owner: owner.clone(),
 		};
 
-		let budget = budget::Value::new(2);
+		let budget = budget::Value::new(NESTING_BUDGET);
 
 		<PalletNft<T>>::create_item(collection, sender, data, &budget)?;
 
@@ -651,14 +737,8 @@
 		//ensure!(!Pallet::<T>::is_locked(collection_id, nft_id), pallet_uniques::Error::<T>::Locked);
 
 		let sender = T::CrossAccountId::from_sub(sender);
-		let budget = budget::Value::new(10);
-		let pending = !<PalletStructure<T>>::check_indirectly_owned(
-			sender.clone(),
-			collection_id,
-			token_id,
-			None,
-			&budget,
-		)?;
+		let budget = budget::Value::new(NESTING_BUDGET);
+		let pending = Self::ensure_nft_owner(collection_id, token_id, &sender, &budget).is_err();
 
 		let resource_collection_id: CollectionId =
 			Self::get_nft_property_decoded(collection_id, token_id, ResourceCollection)?;
@@ -757,7 +837,14 @@
 	pub fn unique_collection_id(
 		rmrk_collection_id: RmrkCollectionId,
 	) -> Result<CollectionId, DispatchError> {
-		<CollectionIndexMap<T>>::try_get(rmrk_collection_id)
+		<UniqueCollectionId<T>>::try_get(rmrk_collection_id)
+			.map_err(|_| <Error<T>>::CollectionUnknown.into())
+	}
+
+	pub fn rmrk_collection_id(
+		unique_collection_id: CollectionId
+	) -> Result<RmrkCollectionId, DispatchError> {
+		<RmrkInernalCollectionId<T>>::try_get(unique_collection_id)
 			.map_err(|_| <Error<T>>::CollectionUnknown.into())
 	}
 
@@ -873,12 +960,18 @@
 		collection_id: CollectionId,
 		token_id: TokenId,
 		possible_owner: &T::CrossAccountId,
+		nesting_budget: &dyn budget::Budget
 	) -> DispatchResult {
-		let token_data =
-			<TokenData<T>>::get((collection_id, token_id)).ok_or(<Error<T>>::NoAvailableNftId)?;
+		let is_owned = <PalletStructure<T>>::check_indirectly_owned(
+			possible_owner.clone(),
+			collection_id,
+			token_id,
+			None,
+			nesting_budget,
+		)?;
 
 		ensure!(
-			token_data.owner == *possible_owner,
+			is_owned,
 			<Error<T>>::NoPermission
 		);
 
@@ -965,7 +1058,8 @@
 				NoPermission => NoPermission,
 				CollectionTokenLimitExceeded => CollectionFullOrLocked,
 				PublicMintingNotAllowed => NoPermission,
-				TokenNotFound => NoAvailableNftId
+				TokenNotFound => NoAvailableNftId,
+				ApprovedValueTooLow => NoPermission
 			}
 		}
 	}
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
after · runtime/common/src/runtime_apis.rs
1#[macro_export]2macro_rules! impl_common_runtime_apis {3    (4        $(5            #![custom_apis]67            $($custom_apis:tt)+8        )?9    ) => {10        impl_runtime_apis! {11            $($($custom_apis)+)?1213            impl up_rpc::UniqueApi<Block, CrossAccountId, AccountId> for Runtime {14                fn account_tokens(collection: CollectionId, account: CrossAccountId) -> Result<Vec<TokenId>, DispatchError> {15                    dispatch_unique_runtime!(collection.account_tokens(account))16                }17                fn collection_tokens(collection: CollectionId) -> Result<Vec<TokenId>, DispatchError> {18                    dispatch_unique_runtime!(collection.collection_tokens())19                }20                fn token_exists(collection: CollectionId, token: TokenId) -> Result<bool, DispatchError> {21                    dispatch_unique_runtime!(collection.token_exists(token))22                }2324                fn token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>, DispatchError> {25                    dispatch_unique_runtime!(collection.token_owner(token))26                }27                fn topmost_token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>, DispatchError> {28                    let budget = up_data_structs::budget::Value::new(10);2930                    Ok(Some(<pallet_structure::Pallet<Runtime>>::find_topmost_owner(collection, token, &budget)?))31                }32                fn token_children(collection: CollectionId, token: TokenId) -> Result<Vec<TokenChild>, DispatchError> {33                    Ok(<pallet_nonfungible::Pallet<Runtime>>::token_children_ids(collection, token))34                }35                fn collection_properties(36                    collection: CollectionId,37                    keys: Option<Vec<Vec<u8>>>38                ) -> Result<Vec<Property>, DispatchError> {39                    let keys = keys.map(40                        |keys| Common::bytes_keys_to_property_keys(keys)41                    ).transpose()?;4243                    Common::filter_collection_properties(collection, keys)44                }4546                fn token_properties(47                    collection: CollectionId,48                    token_id: TokenId,49                    keys: Option<Vec<Vec<u8>>>50                ) -> Result<Vec<Property>, DispatchError> {51                    let keys = keys.map(52                        |keys| Common::bytes_keys_to_property_keys(keys)53                    ).transpose()?;5455                    dispatch_unique_runtime!(collection.token_properties(token_id, keys))56                }5758                fn property_permissions(59                    collection: CollectionId,60                    keys: Option<Vec<Vec<u8>>>61                ) -> Result<Vec<PropertyKeyPermission>, DispatchError> {62                    let keys = keys.map(63                        |keys| Common::bytes_keys_to_property_keys(keys)64                    ).transpose()?;6566                    Common::filter_property_permissions(collection, keys)67                }6869                fn token_data(70                    collection: CollectionId,71                    token_id: TokenId,72                    keys: Option<Vec<Vec<u8>>>73                ) -> Result<TokenData<CrossAccountId>, DispatchError> {74                    let token_data = TokenData {75                        properties: Self::token_properties(collection, token_id, keys)?,76                        owner: Self::token_owner(collection, token_id)?77                    };7879                    Ok(token_data)80                }8182                fn total_supply(collection: CollectionId) -> Result<u32, DispatchError> {83                    dispatch_unique_runtime!(collection.total_supply())84                }85                fn account_balance(collection: CollectionId, account: CrossAccountId) -> Result<u32, DispatchError> {86                    dispatch_unique_runtime!(collection.account_balance(account))87                }88                fn balance(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<u128, DispatchError> {89                    dispatch_unique_runtime!(collection.balance(account, token))90                }91                fn allowance(92                    collection: CollectionId,93                    sender: CrossAccountId,94                    spender: CrossAccountId,95                    token: TokenId,96                ) -> Result<u128, DispatchError> {97                    dispatch_unique_runtime!(collection.allowance(sender, spender, token))98                }99100                fn adminlist(collection: CollectionId) -> Result<Vec<CrossAccountId>, DispatchError> {101                    Ok(<pallet_common::Pallet<Runtime>>::adminlist(collection))102                }103                fn allowlist(collection: CollectionId) -> Result<Vec<CrossAccountId>, DispatchError> {104                    Ok(<pallet_common::Pallet<Runtime>>::allowlist(collection))105                }106                fn allowed(collection: CollectionId, user: CrossAccountId) -> Result<bool, DispatchError> {107                    Ok(<pallet_common::Pallet<Runtime>>::allowed(collection, user))108                }109                fn last_token_id(collection: CollectionId) -> Result<TokenId, DispatchError> {110                    dispatch_unique_runtime!(collection.last_token_id())111                }112                fn collection_by_id(collection: CollectionId) -> Result<Option<RpcCollection<AccountId>>, DispatchError> {113                    Ok(<pallet_common::Pallet<Runtime>>::rpc_collection(collection))114                }115                fn collection_stats() -> Result<CollectionStats, DispatchError> {116                    Ok(<pallet_common::Pallet<Runtime>>::collection_stats())117                }118                fn next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<Option<u64>, DispatchError> {119                    Ok(<$crate::sponsoring::UniqueSponsorshipPredict<Runtime> as120                            $crate::sponsoring::SponsorshipPredict<Runtime>>::predict(121                        collection,122                        account,123                        token))124                }125126                fn effective_collection_limits(collection: CollectionId) -> Result<Option<CollectionLimits>, DispatchError> {127                    Ok(<pallet_common::Pallet<Runtime>>::effective_collection_limits(collection))128                }129            }130131            impl rmrk_rpc::RmrkApi<132                Block,133                AccountId,134                RmrkCollectionInfo<AccountId>,135                RmrkInstanceInfo<AccountId>,136                RmrkResourceInfo,137                RmrkPropertyInfo,138                RmrkBaseInfo<AccountId>,139                RmrkPartType,140                RmrkTheme141            > for Runtime {142                fn last_collection_idx() -> Result<RmrkCollectionId, DispatchError> {143                    Ok(RmrkCore::last_collection_idx())144                }145146                fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {147                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};148                    use pallet_common::CommonCollectionOperations;149150                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {151                        Ok(id) => id,152                        Err(_) => return Ok(None)153                    };154155                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {156                        Ok(c) => c,157                        Err(_) => return Ok(None),158                    };159160                    let nfts_count = collection.total_supply();161162                    Ok(Some(RmrkCollectionInfo {163                        issuer: collection.owner.clone(),164                        metadata: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::Metadata)?,165                        max: collection.limits.token_limit,166                        symbol: RmrkCore::rebind(&collection.token_prefix)?,167                        nfts_count168                    }))169                }170171                fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {172                    use up_data_structs::mapping::TokenAddressMapping;173                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};174                    use pallet_common::CommonCollectionOperations;175176                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {177                        Ok(id) => id,178                        Err(_) => return Ok(None)179                    };180                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {181                        Ok(c) => c,182                        Err(_) => return Ok(None),183                    };184185                    let nft_id = TokenId(nft_by_id);186                    if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(None); }187188                    let owner = match collection.token_owner(nft_id) {189                        Some(owner) => match <Runtime as pallet_common::Config>::CrossTokenAddressMapping::address_to_token(&owner) {190                            Some((col, tok)) => {191                                let rmrk_collection = RmrkCore::rmrk_collection_id(col)?;192193                                RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(rmrk_collection, tok.0)194                            }195                            None => RmrkAccountIdOrCollectionNftTuple::AccountId(owner.as_sub().clone())196                        },197                        None => return Ok(None)198                    };199200                    let allowance = pallet_nonfungible::Allowance::<Runtime>::get((collection_id, nft_id));201202                    Ok(Some(RmrkInstanceInfo {203                        owner: owner,204                        royalty: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::RoyaltyInfo)?,205                        metadata: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Metadata)?,206                        equipped: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Equipped)?,207                        pending: allowance.is_some(),208                    }))209                }210211                fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {212                    use pallet_proxy_rmrk_core::misc::CollectionType;213                    use pallet_common::CommonCollectionOperations;214215                    let cross_account_id = CrossAccountId::from_sub(account_id);216                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {217                        Ok(id) => id,218                        Err(_) => return Ok(Vec::new())219                    };220                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }221222                    Ok(223                        collection.account_tokens(cross_account_id)224                            .into_iter()225                            .map(|token| token.0)226                            .collect()227                    )228                }229230                fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {231                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {232                        Ok(id) => id,233                        Err(_) => return Ok(Vec::new())234                    };235                    let nft_id = TokenId(nft_id);236                    if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(Vec::new()); }237238                    Ok(239                        pallet_nonfungible::TokenChildren::<Runtime>::iter_prefix((collection_id, nft_id))240                            .filter_map(|((child_collection, child_token), _)| {241                                let rmrk_child_collection = RmrkCore::rmrk_collection_id(242                                    child_collection243                                ).ok()?;244245                                Some(RmrkNftChild {246                                    collection_id: rmrk_child_collection,247                                    nft_id: child_token.0,248                                })249                            }).collect()250                    )251                }252253                fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {254                    use pallet_proxy_rmrk_core::misc::CollectionType;255256                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {257                        Ok(id) => id,258                        Err(_) => return Ok(Vec::new())259                    };260                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() {261                        return Ok(Vec::new());262                    }263264                    let properties = RmrkCore::filter_user_properties(265                        collection_id,266                        /* token_id = */ None,267                        filter_keys,268                        |key, value| RmrkPropertyInfo {269                            key,270                            value271                        }272                    )?;273274                    Ok(properties)275                }276277                fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {278                    use pallet_proxy_rmrk_core::misc::NftType;279280                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {281                        Ok(id) => id,282                        Err(_) => return Ok(Vec::new())283                    };284                    let token_id = TokenId(nft_id);285286                    if RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Regular).is_err() {287                        return Ok(Vec::new());288                    }289290		            let properties = RmrkCore::filter_user_properties(291                        collection_id,292                        Some(token_id),293                        filter_keys,294                        |key, value| RmrkPropertyInfo {295                            key,296                            value297                        }298                    )?;299300                    Ok(properties)301                }302303                fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {304                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, ResourceType}};305                    use pallet_common::CommonCollectionOperations;306307                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {308                        Ok(id) => id,309                        Err(_) => return Ok(Vec::new())310                    };311                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }312313                    let nft_id = TokenId(nft_id);314                    if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(Vec::new()); }315316                    let res_collection_id: CollectionId = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourceCollection)?;317                    let resource_collection = RmrkCore::get_typed_nft_collection(res_collection_id, CollectionType::Resource)?;318319                    let resources = resource_collection320                        .collection_tokens()321                        .iter()322                        .filter_map(|(res_id)| Some(RmrkResourceInfo {323                            id: res_id.0,324                            pending: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceAccept).unwrap(),325                            pending_removal: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceRemoval).unwrap(),326                            resource: match RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::ResourceType).unwrap() {327                                ResourceType::Basic => RmrkResourceTypes::Basic(RmrkBasicResource {328                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),329                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),330                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),331                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),332                                }),333                                ResourceType::Composable => RmrkResourceTypes::Composable(RmrkComposableResource {334                                    parts: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Parts).unwrap(),335                                    base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).unwrap(),336                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),337                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),338                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),339                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),340                                }),341                                ResourceType::Slot => RmrkResourceTypes::Slot(RmrkSlotResource {342                                    base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).unwrap(),343                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),344                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),345                                    slot: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Slot).unwrap(),346                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),347                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),348                                }),349                            },350                        }))351                        .collect();352353                    Ok(resources)354                }355356                fn nft_resource_priorities(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceId>, DispatchError> {357                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};358359                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {360                        Ok(id) => id,361                        Err(_) => return Ok(Vec::new())362                    };363                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }364365                    let nft_id = TokenId(nft_id);366                    if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(Vec::new()); }367368                    /*let resource_collection_id: CollectionId = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourceCollection)369                        .unwrap();370                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Resource).is_err() { return Ok(Vec::new()); }371372                    let resources = pallet_nonfungible::TokenProperties::<Runtime>::iter_prefix((resource_collection_id,))373                        .filter_map(|(resource_id, properties)| Some((374                            resource_id, // ResourceId property375                            RmrkCore::get_nft_property_decoded(resource_collection_id, resource_id, RmrkProperty::Priority).unwrap(),376                        )))377                        .collect()378                        .sort_by_key(|(_, index)| *index)379                        .into_iter().map(|(resource_id, _)| resource_id)*/380                    let priorities = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourcePriorities)?;381382                    Ok(priorities)383                }384385                fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {386                    use pallet_proxy_rmrk_core::{387                        RmrkProperty, misc::{CollectionType},388                    };389390                    let collection_id = match RmrkCore::unique_collection_id(base_id) {391                        Ok(id) => id,392                        Err(_) => return Ok(None)393                    };394                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {395                        Ok(c) => c,396                        Err(_) => return Ok(None),397                    };398399                    Ok(Some(RmrkBaseInfo {400                        issuer: collection.owner.clone(),401                        base_type: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::BaseType)?,402                        symbol: RmrkCore::rebind(&collection.token_prefix)?,403                    }))404                }405406                fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {407                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};408                    use pallet_common::CommonCollectionOperations;409410                    let collection_id = match RmrkCore::unique_collection_id(base_id) {411                        Ok(id) => id,412                        Err(_) => return Ok(Vec::new())413                    };414                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() { return Ok(Vec::new()); }415416                    let parts = collection.collection_tokens()417                        .into_iter()418                        .filter_map(|token_id| {419                            let nft_type = RmrkCore::get_nft_type(collection_id, token_id).ok()?;420421                            match nft_type {422                                NftType::FixedPart => Some(RmrkPartType::FixedPart(RmrkFixedPart {423                                    id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?,424                                    src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?,425                                    z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?,426                                })),427                                NftType::SlotPart => Some(RmrkPartType::SlotPart(RmrkSlotPart {428                                    id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?,429                                    src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?,430                                    z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?,431                                    equippable: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::EquippableList).ok()?,432                                })),433                                _ => None434                            }435                        })436                        .collect();437438                    Ok(parts)439                }440441                fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {442                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};443                    use pallet_common::CommonCollectionOperations;444445                    let collection_id = match RmrkCore::unique_collection_id(base_id) {446                        Ok(id) => id,447                        Err(_) => return Ok(Vec::new())448                    };449                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() {450                        return Ok(Vec::new());451                    }452453454                    let theme_names = collection.collection_tokens()455                        .iter()456                        .filter_map(|token_id| {457                            let nft_type = RmrkCore::get_nft_type(collection_id, *token_id).unwrap();458459                            match nft_type {460                                Theme => Some(461                                    RmrkCore::get_nft_property_decoded(collection_id, *token_id, RmrkProperty::ThemeName).unwrap()462                                ),463                                _ => None464                            }465                        })466                        .collect();467468                    Ok(theme_names)469                }470471                fn theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {472                    use pallet_proxy_rmrk_core::{473                        RmrkProperty,474                        misc::{CollectionType, NftType}475                    };476                    use pallet_common::CommonCollectionOperations;477478                    let collection_id = match RmrkCore::unique_collection_id(base_id) {479                        Ok(id) => id,480                        Err(_) => return Ok(None)481                    };482                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() {483                        return Ok(None);484                    }485486                    let theme_info = collection.collection_tokens()487                        .into_iter()488                        .find_map(|token_id| {489                            RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Theme).ok()?;490491                            let name: RmrkString = RmrkCore::get_nft_property_decoded(492                                collection_id, token_id, RmrkProperty::ThemeName493                            ).ok()?;494495                            if name == theme_name {496                                Some((name, token_id))497                            } else {498                                None499                            }500                        });501502                    let (name, theme_id) = match theme_info {503                        Some((name, theme_id)) => (name, theme_id),504                        None => return Ok(None)505                    };506507                    let properties = RmrkCore::filter_user_properties(508                        collection_id,509                        Some(theme_id),510                        filter_keys,511                        |key, value| RmrkThemeProperty {512                            key,513                            value514                        }515                    )?;516517                    let inherit = RmrkCore::get_nft_property_decoded(518                        collection_id,519                        theme_id,520                        RmrkProperty::ThemeInherit521                    )?;522523                    let theme = RmrkTheme {524                        name,525                        properties,526                        inherit,527                    };528529                    Ok(Some(theme))530                }531            }532533            impl sp_api::Core<Block> for Runtime {534                fn version() -> RuntimeVersion {535                    VERSION536                }537538                fn execute_block(block: Block) {539                    Executive::execute_block(block)540                }541542                fn initialize_block(header: &<Block as BlockT>::Header) {543                    Executive::initialize_block(header)544                }545            }546547            impl sp_api::Metadata<Block> for Runtime {548                fn metadata() -> OpaqueMetadata {549                    OpaqueMetadata::new(Runtime::metadata().into())550                }551            }552553            impl sp_block_builder::BlockBuilder<Block> for Runtime {554                fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {555                    Executive::apply_extrinsic(extrinsic)556                }557558                fn finalize_block() -> <Block as BlockT>::Header {559                    Executive::finalize_block()560                }561562                fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {563                    data.create_extrinsics()564                }565566                fn check_inherents(567                    block: Block,568                    data: sp_inherents::InherentData,569                ) -> sp_inherents::CheckInherentsResult {570                    data.check_extrinsics(&block)571                }572573                // fn random_seed() -> <Block as BlockT>::Hash {574                //     RandomnessCollectiveFlip::random_seed().0575                // }576            }577578            impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {579                fn validate_transaction(580                    source: TransactionSource,581                    tx: <Block as BlockT>::Extrinsic,582                    hash: <Block as BlockT>::Hash,583                ) -> TransactionValidity {584                    Executive::validate_transaction(source, tx, hash)585                }586            }587588            impl sp_offchain::OffchainWorkerApi<Block> for Runtime {589                fn offchain_worker(header: &<Block as BlockT>::Header) {590                    Executive::offchain_worker(header)591                }592            }593594            impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {595                fn chain_id() -> u64 {596                    <Runtime as pallet_evm::Config>::ChainId::get()597                }598599                fn account_basic(address: H160) -> EVMAccount {600                    let (account, _) = EVM::account_basic(&address);601                    account602                }603604                fn gas_price() -> U256 {605                    let (price, _) = <Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price();606                    price607                }608609                fn account_code_at(address: H160) -> Vec<u8> {610                    EVM::account_codes(address)611                }612613                fn author() -> H160 {614                    <pallet_evm::Pallet<Runtime>>::find_author()615                }616617                fn storage_at(address: H160, index: U256) -> H256 {618                    let mut tmp = [0u8; 32];619                    index.to_big_endian(&mut tmp);620                    EVM::account_storages(address, H256::from_slice(&tmp[..]))621                }622623                #[allow(clippy::redundant_closure)]624                fn call(625                    from: H160,626                    to: H160,627                    data: Vec<u8>,628                    value: U256,629                    gas_limit: U256,630                    max_fee_per_gas: Option<U256>,631                    max_priority_fee_per_gas: Option<U256>,632                    nonce: Option<U256>,633                    estimate: bool,634                    access_list: Option<Vec<(H160, Vec<H256>)>>,635                ) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {636                    let config = if estimate {637                        let mut config = <Runtime as pallet_evm::Config>::config().clone();638                        config.estimate = true;639                        Some(config)640                    } else {641                        None642                    };643644                    let is_transactional = false;645                    <Runtime as pallet_evm::Config>::Runner::call(646                        CrossAccountId::from_eth(from),647                        to,648                        data,649                        value,650                        gas_limit.low_u64(),651                        max_fee_per_gas,652                        max_priority_fee_per_gas,653                        nonce,654                        access_list.unwrap_or_default(),655                        is_transactional,656                        config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),657                    ).map_err(|err| err.error.into())658                }659660                #[allow(clippy::redundant_closure)]661                fn create(662                    from: H160,663                    data: Vec<u8>,664                    value: U256,665                    gas_limit: U256,666                    max_fee_per_gas: Option<U256>,667                    max_priority_fee_per_gas: Option<U256>,668                    nonce: Option<U256>,669                    estimate: bool,670                    access_list: Option<Vec<(H160, Vec<H256>)>>,671                ) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {672                    let config = if estimate {673                        let mut config = <Runtime as pallet_evm::Config>::config().clone();674                        config.estimate = true;675                        Some(config)676                    } else {677                        None678                    };679680                    let is_transactional = false;681                    <Runtime as pallet_evm::Config>::Runner::create(682                        CrossAccountId::from_eth(from),683                        data,684                        value,685                        gas_limit.low_u64(),686                        max_fee_per_gas,687                        max_priority_fee_per_gas,688                        nonce,689                        access_list.unwrap_or_default(),690                        is_transactional,691                        config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),692                    ).map_err(|err| err.error.into())693                }694695                fn current_transaction_statuses() -> Option<Vec<TransactionStatus>> {696                    Ethereum::current_transaction_statuses()697                }698699                fn current_block() -> Option<pallet_ethereum::Block> {700                    Ethereum::current_block()701                }702703                fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {704                    Ethereum::current_receipts()705                }706707                fn current_all() -> (708                    Option<pallet_ethereum::Block>,709                    Option<Vec<pallet_ethereum::Receipt>>,710                    Option<Vec<TransactionStatus>>711                ) {712                    (713                        Ethereum::current_block(),714                        Ethereum::current_receipts(),715                        Ethereum::current_transaction_statuses()716                    )717                }718719                fn extrinsic_filter(xts: Vec<<Block as sp_api::BlockT>::Extrinsic>) -> Vec<pallet_ethereum::Transaction> {720                    xts.into_iter().filter_map(|xt| match xt.0.function {721                        Call::Ethereum(pallet_ethereum::Call::transact { transaction }) => Some(transaction),722                        _ => None723                    }).collect()724                }725726                fn elasticity() -> Option<Permill> {727                    None728                }729            }730731            impl fp_rpc::ConvertTransactionRuntimeApi<Block> for Runtime {732                fn convert_transaction(transaction: pallet_ethereum::Transaction) -> <Block as BlockT>::Extrinsic  {733                    UncheckedExtrinsic::new_unsigned(734                        pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),735                    )736                }737            }738739            impl sp_session::SessionKeys<Block> for Runtime {740                fn decode_session_keys(741                    encoded: Vec<u8>,742                ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {743                    SessionKeys::decode_into_raw_public_keys(&encoded)744                }745746                fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {747                    SessionKeys::generate(seed)748                }749            }750751            impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {752                fn slot_duration() -> sp_consensus_aura::SlotDuration {753                    sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())754                }755756                fn authorities() -> Vec<AuraId> {757                    Aura::authorities().to_vec()758                }759            }760761            impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {762                fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {763                    ParachainSystem::collect_collation_info(header)764                }765            }766767            impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {768                fn account_nonce(account: AccountId) -> Index {769                    System::account_nonce(account)770                }771            }772773            impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {774                fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {775                    TransactionPayment::query_info(uxt, len)776                }777                fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {778                    TransactionPayment::query_fee_details(uxt, len)779                }780            }781782            /*783            impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber, Hash>784                for Runtime785            {786                fn call(787                    origin: AccountId,788                    dest: AccountId,789                    value: Balance,790                    gas_limit: u64,791                    input_data: Vec<u8>,792                ) -> pallet_contracts_primitives::ContractExecResult {793                    Contracts::bare_call(origin, dest, value, gas_limit, input_data, false)794                }795796                fn instantiate(797                    origin: AccountId,798                    endowment: Balance,799                    gas_limit: u64,800                    code: pallet_contracts_primitives::Code<Hash>,801                    data: Vec<u8>,802                    salt: Vec<u8>,803                ) -> pallet_contracts_primitives::ContractInstantiateResult<AccountId, BlockNumber>804                {805                    Contracts::bare_instantiate(origin, endowment, gas_limit, code, data, salt, true, false)806                }807808                fn get_storage(809                    address: AccountId,810                    key: [u8; 32],811                ) -> pallet_contracts_primitives::GetStorageResult {812                    Contracts::get_storage(address, key)813                }814815                fn rent_projection(816                    address: AccountId,817                ) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {818                    Contracts::rent_projection(address)819                }820            }821            */822823            #[cfg(feature = "runtime-benchmarks")]824            impl frame_benchmarking::Benchmark<Block> for Runtime {825                fn benchmark_metadata(extra: bool) -> (826                    Vec<frame_benchmarking::BenchmarkList>,827                    Vec<frame_support::traits::StorageInfo>,828                ) {829                    use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};830                    use frame_support::traits::StorageInfoTrait;831832                    let mut list = Vec::<BenchmarkList>::new();833834                    list_benchmark!(list, extra, pallet_evm_migration, EvmMigration);835                    list_benchmark!(list, extra, pallet_common, Common);836                    list_benchmark!(list, extra, pallet_unique, Unique);837                    list_benchmark!(list, extra, pallet_structure, Structure);838                    list_benchmark!(list, extra, pallet_inflation, Inflation);839                    list_benchmark!(list, extra, pallet_fungible, Fungible);840                    list_benchmark!(list, extra, pallet_refungible, Refungible);841                    list_benchmark!(list, extra, pallet_nonfungible, Nonfungible);842                    // list_benchmark!(list, extra, pallet_evm_coder_substrate, EvmCoderSubstrate);843844                    let storage_info = AllPalletsReversedWithSystemFirst::storage_info();845846                    return (list, storage_info)847                }848849                fn dispatch_benchmark(850                    config: frame_benchmarking::BenchmarkConfig851                ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {852                    use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};853854                    let allowlist: Vec<TrackedStorageKey> = vec![855                        // Total Issuance856                        hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),857858                        // Block Number859                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),860                        // Execution Phase861                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),862                        // Event Count863                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),864                        // System Events865                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),866867                        // Evm CurrentLogs868                        hex_literal::hex!("1da53b775b270400e7e61ed5cbc5a146547f210cec367e9af919603343b9cb56").to_vec().into(),869870                        // Transactional depth871                        hex_literal::hex!("3a7472616e73616374696f6e5f6c6576656c3a").to_vec().into(),872                    ];873874                    let mut batches = Vec::<BenchmarkBatch>::new();875                    let params = (&config, &allowlist);876877                    add_benchmark!(params, batches, pallet_evm_migration, EvmMigration);878                    add_benchmark!(params, batches, pallet_common, Common);879                    add_benchmark!(params, batches, pallet_unique, Unique);880                    add_benchmark!(params, batches, pallet_structure, Structure);881                    add_benchmark!(params, batches, pallet_inflation, Inflation);882                    add_benchmark!(params, batches, pallet_fungible, Fungible);883                    add_benchmark!(params, batches, pallet_refungible, Refungible);884                    add_benchmark!(params, batches, pallet_nonfungible, Nonfungible);885                    // add_benchmark!(params, batches, pallet_evm_coder_substrate, EvmCoderSubstrate);886887                    if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }888                    Ok(batches)889                }890            }891892            #[cfg(feature = "try-runtime")]893            impl frame_try_runtime::TryRuntime<Block> for Runtime {894                fn on_runtime_upgrade() -> (Weight, Weight) {895                    log::info!("try-runtime::on_runtime_upgrade unique-chain.");896                    let weight = Executive::try_runtime_upgrade().unwrap();897                    (weight, RuntimeBlockWeights::get().max_block)898                }899900                fn execute_block_no_check(block: Block) -> Weight {901                    Executive::execute_block_no_check(block)902                }903            }904        }905    }906}