difftreelog
feat initial rmrk send impl
in: master
10 files changed
pallets/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,
pallets/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(),
pallets/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(),
)
pallets/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(())
}
pallets/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!(
pallets/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
}
}
}
pallets/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),
pallets/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,
pallets/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.
runtime/common/src/runtime_apis.rsdiffbeforeafterboth1#[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}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}