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
before · 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 = RmrkCore::unique_collection_id(collection_id)?;151                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {152                        Ok(c) => c,153                        Err(_) => return Ok(None),154                    };155156                    let nfts_count = collection.total_supply();157158                    Ok(Some(RmrkCollectionInfo {159                        issuer: collection.owner.clone(),160                        metadata: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::Metadata)?,161                        max: collection.limits.token_limit,162                        symbol: RmrkCore::rebind(&collection.token_prefix)?,163                        nfts_count164                    }))165                }166167                fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {168                    use up_data_structs::mapping::TokenAddressMapping;169                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};170                    use pallet_common::CommonCollectionOperations;171172                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;173                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {174                        Ok(c) => c,175                        Err(_) => return Ok(None),176                    };177178                    let nft_id = TokenId(nft_by_id);179                    if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(None); }180181                    let owner = match collection.token_owner(nft_id) {182                        Some(owner) => match <Runtime as pallet_common::Config>::CrossTokenAddressMapping::address_to_token(&owner) {183                            Some((col, tok)) => RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(col.0, tok.0),184                            None => RmrkAccountIdOrCollectionNftTuple::AccountId(owner.as_sub().clone())185                        },186                        None => return Ok(None)187                    };188189                    let allowance = pallet_nonfungible::Allowance::<Runtime>::get((collection_id, nft_id));190191                    Ok(Some(RmrkInstanceInfo {192                        owner: owner,193                        royalty: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::RoyaltyInfo)?,194                        metadata: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Metadata)?,195                        equipped: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Equipped)?,196                        pending: allowance.is_some(),197                    }))198                }199200                fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {201                    use pallet_proxy_rmrk_core::misc::CollectionType;202                    use pallet_common::CommonCollectionOperations;203204                    let cross_account_id = CrossAccountId::from_sub(account_id);205                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;206                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {207                        Ok(c) => c,208                        Err(_) => return Ok(Vec::new()),209                    };210211                    Ok(212                        collection.account_tokens(cross_account_id)213                            .into_iter()214                            .map(|token| token.0)215                            .collect()216                    )217                }218219                fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {220                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;221                    let nft_id = TokenId(nft_id);222                    if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(Vec::new()); }223224                    Ok(225                        pallet_nonfungible::TokenChildren::<Runtime>::iter_prefix((collection_id, nft_id))226                            .filter_map(|(child_id, is_child)|227                                match is_child {228                                    true => Some(RmrkNftChild {229                                        collection_id: child_id.0.0,230                                        nft_id: child_id.1.0,231                                    }),232                                    false => None,233                                }234                            ).collect()235                    )236                }237238                fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {239                    use pallet_proxy_rmrk_core::misc::CollectionType;240241                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;242                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() {243                        return Ok(Vec::new());244                    }245246                    let properties = RmrkCore::filter_user_properties(247                        collection_id,248                        /* token_id = */ None,249                        filter_keys,250                        |key, value| RmrkPropertyInfo {251                            key,252                            value253                        }254                    )?;255256                    Ok(properties)257                }258259                fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {260                    use pallet_proxy_rmrk_core::misc::NftType;261262                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;263                    let token_id = TokenId(nft_id);264265                    if RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Regular).is_err() {266                        return Ok(Vec::new());267                    }268269		            let properties = RmrkCore::filter_user_properties(270                        collection_id,271                        Some(token_id),272                        filter_keys,273                        |key, value| RmrkPropertyInfo {274                            key,275                            value276                        }277                    )?;278279                    Ok(properties)280                }281282                fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {283                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, ResourceType}};284                    use pallet_common::CommonCollectionOperations;285286                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;287                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }288289                    let nft_id = TokenId(nft_id);290                    if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(Vec::new()); }291292                    let res_collection_id: CollectionId = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourceCollection)?;293                    let resource_collection = RmrkCore::get_typed_nft_collection(res_collection_id, CollectionType::Resource)?;294295                    let resources = resource_collection296                        .collection_tokens()297                        .iter()298                        .filter_map(|(res_id)| Some(RmrkResourceInfo {299                            id: res_id.0,300                            pending: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceAccept).unwrap(),301                            pending_removal: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceRemoval).unwrap(),302                            resource: match RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::ResourceType).unwrap() {303                                ResourceType::Basic => RmrkResourceTypes::Basic(RmrkBasicResource {304                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),305                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),306                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),307                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),308                                }),309                                ResourceType::Composable => RmrkResourceTypes::Composable(RmrkComposableResource {310                                    parts: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Parts).unwrap(),311                                    base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).unwrap(),312                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),313                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),314                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),315                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),316                                }),317                                ResourceType::Slot => RmrkResourceTypes::Slot(RmrkSlotResource {318                                    base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).unwrap(),319                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),320                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),321                                    slot: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Slot).unwrap(),322                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),323                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),324                                }),325                            },326                        }))327                        .collect();328329                    Ok(resources)330                }331332                fn nft_resource_priorities(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceId>, DispatchError> {333                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};334335                    let collection_id = RmrkCore::unique_collection_id(collection_id)?;336                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }337338                    let nft_id = TokenId(nft_id);339                    if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(Vec::new()); }340341                    /*let resource_collection_id: CollectionId = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourceCollection)342                        .unwrap();343                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Resource).is_err() { return Ok(Vec::new()); }344345                    let resources = pallet_nonfungible::TokenProperties::<Runtime>::iter_prefix((resource_collection_id,))346                        .filter_map(|(resource_id, properties)| Some((347                            resource_id, // ResourceId property348                            RmrkCore::get_nft_property_decoded(resource_collection_id, resource_id, RmrkProperty::Priority).unwrap(),349                        )))350                        .collect()351                        .sort_by_key(|(_, index)| *index)352                        .into_iter().map(|(resource_id, _)| resource_id)*/353                    let priorities = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourcePriorities)?;354355                    Ok(priorities)356                }357358                fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {359                    use pallet_proxy_rmrk_core::{360                        RmrkProperty, misc::{CollectionType},361                    };362363                    let collection_id = RmrkCore::unique_collection_id(base_id)?;364                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {365                        Ok(c) => c,366                        Err(_) => return Ok(None),367                    };368369                    Ok(Some(RmrkBaseInfo {370                        issuer: collection.owner.clone(),371                        base_type: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::BaseType)?,372                        symbol: RmrkCore::rebind(&collection.token_prefix)?,373                    }))374                }375376                fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {377                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};378                    use pallet_common::CommonCollectionOperations;379380                    let collection_id = RmrkCore::unique_collection_id(base_id)?;381                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {382                        Ok(c) => c,383                        Err(_) => return Ok(Vec::new()),384                    };385386387                    let parts = collection.collection_tokens()388                        .into_iter()389                        .filter_map(|token_id| {390                            let nft_type = RmrkCore::get_nft_type(collection_id, token_id).ok()?;391392                            match nft_type {393                                NftType::FixedPart => Some(RmrkPartType::FixedPart(RmrkFixedPart {394                                    id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?,395                                    src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?,396                                    z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?,397                                })),398                                NftType::SlotPart => Some(RmrkPartType::SlotPart(RmrkSlotPart {399                                    id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?,400                                    src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?,401                                    z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?,402                                    equippable: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::EquippableList).ok()?,403                                })),404                                _ => None405                            }406                        })407                        .collect();408409                    Ok(parts)410                }411412                fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {413                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};414                    use pallet_common::CommonCollectionOperations;415416                    let collection_id = RmrkCore::unique_collection_id(base_id)?;417                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {418                        Ok(c) => c,419                        Err(_) => return Ok(Vec::new()),420                    };421422423                    let theme_names = collection.collection_tokens()424                        .iter()425                        .filter_map(|token_id| {426                            let nft_type = RmrkCore::get_nft_type(collection_id, *token_id).unwrap();427428                            match nft_type {429                                Theme => Some(430                                    RmrkCore::get_nft_property_decoded(collection_id, *token_id, RmrkProperty::ThemeName).unwrap()431                                ),432                                _ => None433                            }434                        })435                        .collect();436437                    Ok(theme_names)438                }439440                fn theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {441                    use pallet_proxy_rmrk_core::{442                        RmrkProperty,443                        misc::{CollectionType, NftType}444                    };445                    use pallet_common::CommonCollectionOperations;446447                    let collection_id = RmrkCore::unique_collection_id(base_id)?;448                    let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {449                        Ok(c) => c,450                        Err(_) => return Ok(None),451                    };452453                    let theme_info = collection.collection_tokens()454                        .into_iter()455                        .find_map(|token_id| {456                            RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Theme).ok()?;457458                            let name: RmrkString = RmrkCore::get_nft_property_decoded(459                                collection_id, token_id, RmrkProperty::ThemeName460                            ).ok()?;461462                            if name == theme_name {463                                Some((name, token_id))464                            } else {465                                None466                            }467                        });468469                    let (name, theme_id) = match theme_info {470                        Some((name, theme_id)) => (name, theme_id),471                        None => return Ok(None)472                    };473474                    let properties = RmrkCore::filter_user_properties(475                        collection_id,476                        Some(theme_id),477                        filter_keys,478                        |key, value| RmrkThemeProperty {479                            key,480                            value481                        }482                    )?;483484                    let inherit = RmrkCore::get_nft_property_decoded(485                        collection_id,486                        theme_id,487                        RmrkProperty::ThemeInherit488                    )?;489490                    let theme = RmrkTheme {491                        name,492                        properties,493                        inherit,494                    };495496                    Ok(Some(theme))497                }498            }499500            impl sp_api::Core<Block> for Runtime {501                fn version() -> RuntimeVersion {502                    VERSION503                }504505                fn execute_block(block: Block) {506                    Executive::execute_block(block)507                }508509                fn initialize_block(header: &<Block as BlockT>::Header) {510                    Executive::initialize_block(header)511                }512            }513514            impl sp_api::Metadata<Block> for Runtime {515                fn metadata() -> OpaqueMetadata {516                    OpaqueMetadata::new(Runtime::metadata().into())517                }518            }519520            impl sp_block_builder::BlockBuilder<Block> for Runtime {521                fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {522                    Executive::apply_extrinsic(extrinsic)523                }524525                fn finalize_block() -> <Block as BlockT>::Header {526                    Executive::finalize_block()527                }528529                fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {530                    data.create_extrinsics()531                }532533                fn check_inherents(534                    block: Block,535                    data: sp_inherents::InherentData,536                ) -> sp_inherents::CheckInherentsResult {537                    data.check_extrinsics(&block)538                }539540                // fn random_seed() -> <Block as BlockT>::Hash {541                //     RandomnessCollectiveFlip::random_seed().0542                // }543            }544545            impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {546                fn validate_transaction(547                    source: TransactionSource,548                    tx: <Block as BlockT>::Extrinsic,549                    hash: <Block as BlockT>::Hash,550                ) -> TransactionValidity {551                    Executive::validate_transaction(source, tx, hash)552                }553            }554555            impl sp_offchain::OffchainWorkerApi<Block> for Runtime {556                fn offchain_worker(header: &<Block as BlockT>::Header) {557                    Executive::offchain_worker(header)558                }559            }560561            impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {562                fn chain_id() -> u64 {563                    <Runtime as pallet_evm::Config>::ChainId::get()564                }565566                fn account_basic(address: H160) -> EVMAccount {567                    let (account, _) = EVM::account_basic(&address);568                    account569                }570571                fn gas_price() -> U256 {572                    let (price, _) = <Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price();573                    price574                }575576                fn account_code_at(address: H160) -> Vec<u8> {577                    EVM::account_codes(address)578                }579580                fn author() -> H160 {581                    <pallet_evm::Pallet<Runtime>>::find_author()582                }583584                fn storage_at(address: H160, index: U256) -> H256 {585                    let mut tmp = [0u8; 32];586                    index.to_big_endian(&mut tmp);587                    EVM::account_storages(address, H256::from_slice(&tmp[..]))588                }589590                #[allow(clippy::redundant_closure)]591                fn call(592                    from: H160,593                    to: H160,594                    data: Vec<u8>,595                    value: U256,596                    gas_limit: U256,597                    max_fee_per_gas: Option<U256>,598                    max_priority_fee_per_gas: Option<U256>,599                    nonce: Option<U256>,600                    estimate: bool,601                    access_list: Option<Vec<(H160, Vec<H256>)>>,602                ) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {603                    let config = if estimate {604                        let mut config = <Runtime as pallet_evm::Config>::config().clone();605                        config.estimate = true;606                        Some(config)607                    } else {608                        None609                    };610611                    let is_transactional = false;612                    <Runtime as pallet_evm::Config>::Runner::call(613                        CrossAccountId::from_eth(from),614                        to,615                        data,616                        value,617                        gas_limit.low_u64(),618                        max_fee_per_gas,619                        max_priority_fee_per_gas,620                        nonce,621                        access_list.unwrap_or_default(),622                        is_transactional,623                        config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),624                    ).map_err(|err| err.error.into())625                }626627                #[allow(clippy::redundant_closure)]628                fn create(629                    from: H160,630                    data: Vec<u8>,631                    value: U256,632                    gas_limit: U256,633                    max_fee_per_gas: Option<U256>,634                    max_priority_fee_per_gas: Option<U256>,635                    nonce: Option<U256>,636                    estimate: bool,637                    access_list: Option<Vec<(H160, Vec<H256>)>>,638                ) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {639                    let config = if estimate {640                        let mut config = <Runtime as pallet_evm::Config>::config().clone();641                        config.estimate = true;642                        Some(config)643                    } else {644                        None645                    };646647                    let is_transactional = false;648                    <Runtime as pallet_evm::Config>::Runner::create(649                        CrossAccountId::from_eth(from),650                        data,651                        value,652                        gas_limit.low_u64(),653                        max_fee_per_gas,654                        max_priority_fee_per_gas,655                        nonce,656                        access_list.unwrap_or_default(),657                        is_transactional,658                        config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),659                    ).map_err(|err| err.error.into())660                }661662                fn current_transaction_statuses() -> Option<Vec<TransactionStatus>> {663                    Ethereum::current_transaction_statuses()664                }665666                fn current_block() -> Option<pallet_ethereum::Block> {667                    Ethereum::current_block()668                }669670                fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {671                    Ethereum::current_receipts()672                }673674                fn current_all() -> (675                    Option<pallet_ethereum::Block>,676                    Option<Vec<pallet_ethereum::Receipt>>,677                    Option<Vec<TransactionStatus>>678                ) {679                    (680                        Ethereum::current_block(),681                        Ethereum::current_receipts(),682                        Ethereum::current_transaction_statuses()683                    )684                }685686                fn extrinsic_filter(xts: Vec<<Block as sp_api::BlockT>::Extrinsic>) -> Vec<pallet_ethereum::Transaction> {687                    xts.into_iter().filter_map(|xt| match xt.0.function {688                        Call::Ethereum(pallet_ethereum::Call::transact { transaction }) => Some(transaction),689                        _ => None690                    }).collect()691                }692693                fn elasticity() -> Option<Permill> {694                    None695                }696            }697698            impl fp_rpc::ConvertTransactionRuntimeApi<Block> for Runtime {699                fn convert_transaction(transaction: pallet_ethereum::Transaction) -> <Block as BlockT>::Extrinsic  {700                    UncheckedExtrinsic::new_unsigned(701                        pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),702                    )703                }704            }705706            impl sp_session::SessionKeys<Block> for Runtime {707                fn decode_session_keys(708                    encoded: Vec<u8>,709                ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {710                    SessionKeys::decode_into_raw_public_keys(&encoded)711                }712713                fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {714                    SessionKeys::generate(seed)715                }716            }717718            impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {719                fn slot_duration() -> sp_consensus_aura::SlotDuration {720                    sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())721                }722723                fn authorities() -> Vec<AuraId> {724                    Aura::authorities().to_vec()725                }726            }727728            impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {729                fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {730                    ParachainSystem::collect_collation_info(header)731                }732            }733734            impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {735                fn account_nonce(account: AccountId) -> Index {736                    System::account_nonce(account)737                }738            }739740            impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {741                fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {742                    TransactionPayment::query_info(uxt, len)743                }744                fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {745                    TransactionPayment::query_fee_details(uxt, len)746                }747            }748749            /*750            impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber, Hash>751                for Runtime752            {753                fn call(754                    origin: AccountId,755                    dest: AccountId,756                    value: Balance,757                    gas_limit: u64,758                    input_data: Vec<u8>,759                ) -> pallet_contracts_primitives::ContractExecResult {760                    Contracts::bare_call(origin, dest, value, gas_limit, input_data, false)761                }762763                fn instantiate(764                    origin: AccountId,765                    endowment: Balance,766                    gas_limit: u64,767                    code: pallet_contracts_primitives::Code<Hash>,768                    data: Vec<u8>,769                    salt: Vec<u8>,770                ) -> pallet_contracts_primitives::ContractInstantiateResult<AccountId, BlockNumber>771                {772                    Contracts::bare_instantiate(origin, endowment, gas_limit, code, data, salt, true, false)773                }774775                fn get_storage(776                    address: AccountId,777                    key: [u8; 32],778                ) -> pallet_contracts_primitives::GetStorageResult {779                    Contracts::get_storage(address, key)780                }781782                fn rent_projection(783                    address: AccountId,784                ) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {785                    Contracts::rent_projection(address)786                }787            }788            */789790            #[cfg(feature = "runtime-benchmarks")]791            impl frame_benchmarking::Benchmark<Block> for Runtime {792                fn benchmark_metadata(extra: bool) -> (793                    Vec<frame_benchmarking::BenchmarkList>,794                    Vec<frame_support::traits::StorageInfo>,795                ) {796                    use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};797                    use frame_support::traits::StorageInfoTrait;798799                    let mut list = Vec::<BenchmarkList>::new();800801                    list_benchmark!(list, extra, pallet_evm_migration, EvmMigration);802                    list_benchmark!(list, extra, pallet_common, Common);803                    list_benchmark!(list, extra, pallet_unique, Unique);804                    list_benchmark!(list, extra, pallet_structure, Structure);805                    list_benchmark!(list, extra, pallet_inflation, Inflation);806                    list_benchmark!(list, extra, pallet_fungible, Fungible);807                    list_benchmark!(list, extra, pallet_refungible, Refungible);808                    list_benchmark!(list, extra, pallet_nonfungible, Nonfungible);809                    // list_benchmark!(list, extra, pallet_evm_coder_substrate, EvmCoderSubstrate);810811                    let storage_info = AllPalletsReversedWithSystemFirst::storage_info();812813                    return (list, storage_info)814                }815816                fn dispatch_benchmark(817                    config: frame_benchmarking::BenchmarkConfig818                ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {819                    use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};820821                    let allowlist: Vec<TrackedStorageKey> = vec![822                        // Total Issuance823                        hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),824825                        // Block Number826                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),827                        // Execution Phase828                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),829                        // Event Count830                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),831                        // System Events832                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),833834                        // Evm CurrentLogs835                        hex_literal::hex!("1da53b775b270400e7e61ed5cbc5a146547f210cec367e9af919603343b9cb56").to_vec().into(),836837                        // Transactional depth838                        hex_literal::hex!("3a7472616e73616374696f6e5f6c6576656c3a").to_vec().into(),839                    ];840841                    let mut batches = Vec::<BenchmarkBatch>::new();842                    let params = (&config, &allowlist);843844                    add_benchmark!(params, batches, pallet_evm_migration, EvmMigration);845                    add_benchmark!(params, batches, pallet_common, Common);846                    add_benchmark!(params, batches, pallet_unique, Unique);847                    add_benchmark!(params, batches, pallet_structure, Structure);848                    add_benchmark!(params, batches, pallet_inflation, Inflation);849                    add_benchmark!(params, batches, pallet_fungible, Fungible);850                    add_benchmark!(params, batches, pallet_refungible, Refungible);851                    add_benchmark!(params, batches, pallet_nonfungible, Nonfungible);852                    // add_benchmark!(params, batches, pallet_evm_coder_substrate, EvmCoderSubstrate);853854                    if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }855                    Ok(batches)856                }857            }858859            #[cfg(feature = "try-runtime")]860            impl frame_try_runtime::TryRuntime<Block> for Runtime {861                fn on_runtime_upgrade() -> (Weight, Weight) {862                    log::info!("try-runtime::on_runtime_upgrade unique-chain.");863                    let weight = Executive::try_runtime_upgrade().unwrap();864                    (weight, RuntimeBlockWeights::get().max_block)865                }866867                fn execute_block_no_check(block: Block) -> Weight {868                    Executive::execute_block_no_check(block)869                }870            }871        }872    }873}