From d76cc13924e4aed0a11079dfc5da1a9bd77ebb82 Mon Sep 17 00:00:00 2001 From: Igor Kozyrev Date: Wed, 08 Jun 2022 17:09:52 +0000 Subject: [PATCH] Merge branch 'develop' into feature/CORE-302-ss58Format --- --- a/pallets/common/src/benchmarking.rs +++ b/pallets/common/src/benchmarking.rs @@ -20,8 +20,8 @@ use frame_benchmarking::{benchmarks, account}; use up_data_structs::{ CollectionMode, CreateCollectionData, CollectionId, Property, PropertyKey, PropertyValue, - MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH, - OFFCHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT, MAX_PROPERTIES_PER_ITEM, + CollectionPermissions, NestingRule, MAX_COLLECTION_NAME_LENGTH, + MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH, MAX_PROPERTIES_PER_ITEM, }; use frame_support::{ traits::{Currency, Get}, @@ -74,15 +74,15 @@ } pub fn create_collection_raw( - owner: T::AccountId, + owner: T::CrossAccountId, mode: CollectionMode, handler: impl FnOnce( - T::AccountId, + T::CrossAccountId, CreateCollectionData, ) -> Result, cast: impl FnOnce(CollectionHandle) -> R, ) -> Result { - T::Currency::deposit_creating(&owner, T::CollectionCreationPrice::get()); + ::Currency::deposit_creating(&owner.as_sub(), T::CollectionCreationPrice::get()); let name = create_u16_data::(); let description = create_u16_data::(); let token_prefix = create_data::(); @@ -93,13 +93,19 @@ name, description, token_prefix, + permissions: Some(CollectionPermissions { + nesting: Some(NestingRule::Permissive), + ..Default::default() + }), ..Default::default() }, ) .and_then(CollectionHandle::try_get) .map(cast) } -fn create_collection(owner: T::AccountId) -> Result, DispatchError> { +fn create_collection( + owner: T::CrossAccountId, +) -> Result, DispatchError> { create_collection_raw( owner, CollectionMode::NFT, @@ -127,7 +133,7 @@ bench_init!($($rest)*); }; ($name:ident: collection($owner:ident); $($rest:tt)*) => { - let $name = create_collection::($owner.clone())?; + let $name = create_collection::(T::CrossAccountId::from_sub($owner.clone()))?; bench_init!($($rest)*); }; ($name:ident: cross; $($rest:tt)*) => { --- a/pallets/common/src/lib.rs +++ b/pallets/common/src/lib.rs @@ -1168,8 +1168,9 @@ ); Ok(new_limit) } + pub fn clamp_permissions( - mode: CollectionMode, + _mode: CollectionMode, old_limit: &CollectionPermissions, mut new_limit: CollectionPermissions, ) -> Result { @@ -1204,6 +1205,22 @@ fn approve() -> Weight; fn transfer_from() -> Weight; fn burn_from() -> Weight; + + /// Differs from burn_item in case of Fungible and Refungible, as it should burn + /// whole users's balance + /// + /// This method shouldn't be used directly, as it doesn't count breadth price, use `burn_recursively` instead + fn burn_recursively_self_raw() -> Weight; + /// Cost of iterating over `amount` children while burning, without counting child burning itself + /// + /// This method shouldn't be used directly, as it doesn't count depth price, use `burn_recursively` instead + fn burn_recursively_breadth_raw(amount: u32) -> Weight; + + fn burn_recursively(max_selfs: u32, max_breadth: u32) -> Weight { + Self::burn_recursively_self_raw() + .saturating_mul(max_selfs.max(1) as u64) + .saturating_add(Self::burn_recursively_breadth_raw(max_breadth)) + } } pub trait CommonCollectionOperations { @@ -1233,6 +1250,13 @@ token: TokenId, amount: u128, ) -> DispatchResultWithPostInfo; + fn burn_item_recursively( + &self, + sender: T::CrossAccountId, + token: TokenId, + self_budget: &dyn Budget, + breadth_budget: &dyn Budget, + ) -> DispatchResultWithPostInfo; fn set_collection_properties( &self, sender: T::CrossAccountId, --- a/pallets/fungible/src/benchmarking.rs +++ b/pallets/fungible/src/benchmarking.rs @@ -25,7 +25,9 @@ const SEED: u32 = 1; -fn create_collection(owner: T::AccountId) -> Result, DispatchError> { +fn create_collection( + owner: T::CrossAccountId, +) -> Result, DispatchError> { create_collection_raw( owner, CollectionMode::Fungible(0), --- a/pallets/fungible/src/common.rs +++ b/pallets/fungible/src/common.rs @@ -16,9 +16,10 @@ use core::marker::PhantomData; -use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight}; +use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, traits::Get}; use up_data_structs::{TokenId, CollectionId, CreateItemExData, budget::Budget, CreateItemData}; use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight}; +use pallet_structure::Error as StructureError; use sp_runtime::ArithmeticError; use sp_std::{vec::Vec, vec}; use up_data_structs::{Property, PropertyKey, PropertyValue, PropertyKeyPermission}; @@ -91,6 +92,16 @@ fn burn_from() -> Weight { >::burn_from() } + + fn burn_recursively_self_raw() -> Weight { + // Read to get total balance + Self::burn_item() + T::DbWeight::get().reads(1) + } + + fn burn_recursively_breadth_raw(_amount: u32) -> Weight { + // Fungible tokens can't have children + 0 + } } impl CommonCollectionOperations for FungibleHandle { @@ -170,6 +181,26 @@ ) } + fn burn_item_recursively( + &self, + sender: T::CrossAccountId, + token: TokenId, + self_budget: &dyn Budget, + _breadth_budget: &dyn Budget, + ) -> DispatchResultWithPostInfo { + // Should not happen? + ensure!( + token == TokenId::default(), + >::FungibleItemsHaveNoId + ); + ensure!(self_budget.consume(), >::DepthLimit,); + + with_weight( + >::burn(self, &sender, >::get((self.id, &sender))), + >::burn_recursively_self_raw(), + ) + } + fn transfer( &self, from: T::CrossAccountId, --- a/pallets/nonfungible/src/benchmarking.rs +++ b/pallets/nonfungible/src/benchmarking.rs @@ -18,12 +18,9 @@ use crate::{Pallet, Config, NonfungibleHandle}; use sp_std::prelude::*; -use pallet_common::benchmarking::{create_collection_raw, create_data, property_key, property_value}; +use pallet_common::benchmarking::{create_collection_raw, property_key, property_value}; use frame_benchmarking::{benchmarks, account}; -use up_data_structs::{ - CollectionMode, MAX_ITEMS_PER_BATCH, MAX_PROPERTIES_PER_ITEM, CUSTOM_DATA_LIMIT, - budget::Unlimited, -}; +use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH, MAX_PROPERTIES_PER_ITEM, budget::Unlimited}; use pallet_common::bench_init; const SEED: u32 = 1; @@ -49,7 +46,7 @@ } fn create_collection( - owner: T::AccountId, + owner: T::CrossAccountId, ) -> Result, DispatchError> { create_collection_raw( owner, @@ -96,6 +93,26 @@ let item = create_max_item(&collection, &sender, burner.clone())?; }: {>::burn(&collection, &burner, item)?} + burn_recursively_self_raw { + bench_init!{ + owner: sub; collection: collection(owner); + sender: cross_from_sub(owner); burner: cross_sub; + }; + let item = create_max_item(&collection, &sender, burner.clone())?; + }: {>::burn_recursively(&collection, &burner, item, &Unlimited, &Unlimited)} + + burn_recursively_breadth_plus_self_plus_self_per_each_raw { + let b in 0..200; + bench_init!{ + owner: sub; collection: collection(owner); + sender: cross_from_sub(owner); burner: cross_sub; + }; + let item = create_max_item(&collection, &sender, burner.clone())?; + for i in 0..b { + create_max_item(&collection, &sender, T::CrossTokenAddressMapping::token_to_address(collection.id, item))?; + } + }: {>::burn_recursively(&collection, &burner, item, &Unlimited, &Unlimited)} + transfer { bench_init!{ owner: sub; collection: collection(owner); --- a/pallets/nonfungible/src/common.rs +++ b/pallets/nonfungible/src/common.rs @@ -108,6 +108,15 @@ fn burn_from() -> Weight { >::burn_from() } + + fn burn_recursively_self_raw() -> Weight { + >::burn_recursively_self_raw() + } + + fn burn_recursively_breadth_raw(amount: u32) -> Weight { + >::burn_recursively_breadth_plus_self_plus_self_per_each_raw(amount) + .saturating_sub(Self::burn_recursively_self_raw().saturating_mul(amount as u64 + 1)) + } } fn map_create_data( @@ -264,6 +273,16 @@ } } + fn burn_item_recursively( + &self, + sender: T::CrossAccountId, + token: TokenId, + self_budget: &dyn Budget, + breadth_budget: &dyn Budget, + ) -> DispatchResultWithPostInfo { + >::burn_recursively(self, &sender, token, self_budget, breadth_budget) + } + fn transfer( &self, from: T::CrossAccountId, --- a/pallets/nonfungible/src/lib.rs +++ b/pallets/nonfungible/src/lib.rs @@ -18,7 +18,13 @@ use erc::ERC721Events; use evm_coder::ToLog; -use frame_support::{BoundedVec, ensure, fail, transactional, storage::with_transaction}; +use frame_support::{ + BoundedVec, ensure, fail, transactional, + storage::with_transaction, + pallet_prelude::DispatchResultWithPostInfo, + pallet_prelude::Weight, + weights::{PostDispatchInfo, Pays}, +}; use up_data_structs::{ AccessMode, CollectionId, CustomDataLimit, TokenId, CreateCollectionData, CreateNftExData, mapping::TokenAddressMapping, NestingRule, budget::Budget, Property, PropertyPermission, @@ -29,7 +35,7 @@ Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, CollectionHandle, eth::collection_id_to_address, }; -use pallet_structure::Pallet as PalletStructure; +use pallet_structure::{Pallet as PalletStructure, Error as StructureError}; use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder}; use sp_core::H160; use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome}; @@ -39,6 +45,7 @@ use scale_info::TypeInfo; pub use pallet::*; +use weights::WeightInfo; #[cfg(feature = "runtime-benchmarks")] pub mod benchmarking; pub mod common; @@ -373,7 +380,7 @@ >::deposit_event(CommonEvent::Approved( collection.id, token, - sender.clone(), + token_data.owner.clone(), old_spender, 0, )); @@ -396,6 +403,45 @@ Ok(()) } + #[transactional] + pub fn burn_recursively( + collection: &NonfungibleHandle, + sender: &T::CrossAccountId, + token: TokenId, + self_budget: &dyn Budget, + breadth_budget: &dyn Budget, + ) -> DispatchResultWithPostInfo { + ensure!(self_budget.consume(), >::DepthLimit,); + + let current_token_account = + T::CrossTokenAddressMapping::token_to_address(collection.id, token); + + let mut weight = 0 as Weight; + + // This method is transactional, if user in fact doesn't have permissions to remove token - + // tokens removed here will be restored after rejected transaction + for ((collection, token), _) in >::iter_prefix((collection.id, token)) { + ensure!(breadth_budget.consume(), >::BreadthLimit,); + let PostDispatchInfo { actual_weight, .. } = + >::burn_item_recursively( + current_token_account.clone(), + collection, + token, + self_budget, + breadth_budget, + )?; + if let Some(actual_weight) = actual_weight { + weight = weight.saturating_add(actual_weight); + } + } + + Self::burn(collection, sender, token)?; + DispatchResultWithPostInfo::Ok(PostDispatchInfo { + actual_weight: Some(weight + >::burn_item()), + pays_fee: Pays::Yes, + }) + } + pub fn set_token_property( collection: &NonfungibleHandle, sender: &T::CrossAccountId, @@ -964,6 +1010,7 @@ ); ensure_sender_allowed::(handle.id, under, from, sender, nesting_budget)? } + NestingRule::Permissive => {} } Ok(()) } --- a/pallets/nonfungible/src/weights.rs +++ b/pallets/nonfungible/src/weights.rs @@ -36,6 +36,8 @@ fn create_multiple_items(b: u32, ) -> Weight; fn create_multiple_items_ex(b: u32, ) -> Weight; fn burn_item() -> Weight; + fn burn_recursively_self_raw() -> Weight; + fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32, ) -> Weight; fn transfer() -> Weight; fn approve() -> Weight; fn transfer_from() -> Weight; @@ -92,7 +94,35 @@ .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } - + // Storage: Nonfungible TokenChildren (r:1 w:0) + // Storage: Nonfungible TokenData (r:1 w:1) + // Storage: Nonfungible TokensBurnt (r:1 w:1) + // Storage: Nonfungible AccountBalance (r:1 w:1) + // Storage: Nonfungible Allowance (r:1 w:0) + // Storage: Nonfungible Owned (r:0 w:1) + // Storage: Nonfungible TokenProperties (r:0 w:1) + fn burn_recursively_self_raw() -> Weight { + (86_136_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) + } + // Storage: Nonfungible TokenChildren (r:1 w:0) + // Storage: Nonfungible TokenData (r:1 w:1) + // Storage: Nonfungible TokensBurnt (r:1 w:1) + // Storage: Nonfungible AccountBalance (r:1 w:1) + // Storage: Nonfungible Allowance (r:1 w:0) + // Storage: Nonfungible Owned (r:0 w:1) + // Storage: Nonfungible TokenProperties (r:0 w:1) + // Storage: Common CollectionById (r:1 w:0) + fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 42_828_000 + .saturating_add((381_478_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(b as Weight))) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) + .saturating_add(T::DbWeight::get().writes((4 as Weight).saturating_mul(b as Weight))) + } // Storage: Nonfungible TokenData (r:1 w:1) // Storage: Nonfungible AccountBalance (r:2 w:2) // Storage: Nonfungible Allowance (r:1 w:0) @@ -204,7 +234,35 @@ .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } - + // Storage: Nonfungible TokenChildren (r:1 w:0) + // Storage: Nonfungible TokenData (r:1 w:1) + // Storage: Nonfungible TokensBurnt (r:1 w:1) + // Storage: Nonfungible AccountBalance (r:1 w:1) + // Storage: Nonfungible Allowance (r:1 w:0) + // Storage: Nonfungible Owned (r:0 w:1) + // Storage: Nonfungible TokenProperties (r:0 w:1) + fn burn_recursively_self_raw() -> Weight { + (86_136_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(5 as Weight)) + } + // Storage: Nonfungible TokenChildren (r:1 w:0) + // Storage: Nonfungible TokenData (r:1 w:1) + // Storage: Nonfungible TokensBurnt (r:1 w:1) + // Storage: Nonfungible AccountBalance (r:1 w:1) + // Storage: Nonfungible Allowance (r:1 w:0) + // Storage: Nonfungible Owned (r:0 w:1) + // Storage: Nonfungible TokenProperties (r:0 w:1) + // Storage: Common CollectionById (r:1 w:0) + fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 42_828_000 + .saturating_add((381_478_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) + .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(b as Weight))) + .saturating_add(RocksDbWeight::get().writes(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes((4 as Weight).saturating_mul(b as Weight))) + } // Storage: Nonfungible TokenData (r:1 w:1) // Storage: Nonfungible AccountBalance (r:2 w:2) // Storage: Nonfungible Allowance (r:1 w:0) --- a/pallets/refungible/src/benchmarking.rs +++ b/pallets/refungible/src/benchmarking.rs @@ -50,7 +50,9 @@ Ok(TokenId(>::get(&collection.id))) } -fn create_collection(owner: T::AccountId) -> Result, DispatchError> { +fn create_collection( + owner: T::CrossAccountId, +) -> Result, DispatchError> { create_collection_raw( owner, CollectionMode::NFT, --- a/pallets/refungible/src/common.rs +++ b/pallets/refungible/src/common.rs @@ -17,12 +17,13 @@ use core::marker::PhantomData; use sp_std::collections::btree_map::BTreeMap; -use frame_support::{dispatch::DispatchResultWithPostInfo, fail, weights::Weight}; +use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, traits::Get}; use up_data_structs::{ CollectionId, TokenId, CreateItemExData, CreateRefungibleExData, budget::Budget, Property, PropertyKey, PropertyValue, PropertyKeyPermission, CreateItemData, }; use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight}; +use pallet_structure::Error as StructureError; use sp_runtime::DispatchError; use sp_std::{vec::Vec, vec}; @@ -113,6 +114,15 @@ fn burn_from() -> Weight { >::burn_from() } + + fn burn_recursively_self_raw() -> Weight { + // Read to get total balance + Self::burn_item() + T::DbWeight::get().reads(1) + } + fn burn_recursively_breadth_raw(_amount: u32) -> Weight { + // Refungible token can't have children + 0 + } } fn map_create_data( @@ -205,6 +215,25 @@ ) } + fn burn_item_recursively( + &self, + sender: T::CrossAccountId, + token: TokenId, + self_budget: &dyn Budget, + _breadth_budget: &dyn Budget, + ) -> DispatchResultWithPostInfo { + ensure!(self_budget.consume(), >::DepthLimit,); + with_weight( + >::burn( + self, + &sender, + token, + >::get((self.id, token, &sender)), + ), + >::burn_recursively_self_raw(), + ) + } + fn transfer( &self, from: T::CrossAccountId, --- a/pallets/scheduler/src/lib.rs +++ b/pallets/scheduler/src/lib.rs @@ -60,8 +60,9 @@ // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; +// FIXME +// #[cfg(feature = "runtime-benchmarks")] +// mod benchmarking; pub mod weights; --- a/pallets/structure/src/benchmarking.rs +++ b/pallets/structure/src/benchmarking.rs @@ -5,6 +5,7 @@ use up_data_structs::{ CreateCollectionData, CollectionMode, CreateItemData, CreateNftData, budget::Unlimited, }; +use pallet_common::Config as CommonConfig; use pallet_evm::account::CrossAccountId; const SEED: u32 = 1; @@ -14,8 +15,8 @@ let caller: T::AccountId = account("caller", 0, SEED); let caller_cross = T::CrossAccountId::from_sub(caller.clone()); - T::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get()); - T::CollectionDispatch::create(caller, CreateCollectionData { + ::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get()); + T::CollectionDispatch::create(caller_cross.clone(), CreateCollectionData { mode: CollectionMode::NFT, ..Default::default() })?; --- a/pallets/structure/src/lib.rs +++ b/pallets/structure/src/lib.rs @@ -3,7 +3,7 @@ use pallet_common::CommonCollectionOperations; use sp_std::collections::btree_set::BTreeSet; -use frame_support::dispatch::{DispatchError, DispatchResult}; +use frame_support::dispatch::{DispatchError, DispatchResult, DispatchResultWithPostInfo}; use frame_support::fail; pub use pallet::*; use pallet_common::{dispatch::CollectionDispatch, CollectionHandle}; @@ -29,6 +29,8 @@ OuroborosDetected, /// While searched for owner, encountered depth limit DepthLimit, + /// While iterating over children, encountered breadth limit + BreadthLimit, /// While searched for owner, found token owner by not-yet-existing token TokenNotFound, } @@ -184,6 +186,19 @@ Err(>::DepthLimit.into()) } + pub fn burn_item_recursively( + from: T::CrossAccountId, + collection: CollectionId, + token: TokenId, + self_budget: &dyn Budget, + breadth_budget: &dyn Budget, + ) -> DispatchResultWithPostInfo { + let handle = >::try_get(collection)?; + let dispatch = T::CollectionDispatch::dispatch(handle); + let dispatch = dispatch.as_dyn(); + dispatch.burn_item_recursively(from.clone(), token, self_budget, breadth_budget) + } + pub fn check_nesting( from: T::CrossAccountId, under: &T::CrossAccountId, --- a/pallets/unique/src/benchmarking.rs +++ b/pallets/unique/src/benchmarking.rs @@ -22,7 +22,10 @@ use frame_support::traits::{tokens::currency::Currency, Get}; use frame_benchmarking::{benchmarks, account}; use sp_runtime::DispatchError; -use pallet_common::benchmarking::{create_data, create_var_data, create_u16_data}; +use pallet_common::{ + Config as CommonConfig, + benchmarking::{create_data, create_u16_data}, +}; const SEED: u32 = 1; @@ -30,7 +33,7 @@ owner: T::AccountId, mode: CollectionMode, ) -> Result { - T::Currency::deposit_creating(&owner, T::CollectionCreationPrice::get()); + ::Currency::deposit_creating(&owner, T::CollectionCreationPrice::get()); let col_name = create_u16_data::(); let col_desc = create_u16_data::(); let token_prefix = create_data::(); @@ -54,7 +57,7 @@ let token_prefix = create_data::(); let mode: CollectionMode = CollectionMode::NFT; let caller: T::AccountId = account("caller", 0, SEED); - T::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get()); + ::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get()); }: _(RawOrigin::Signed(caller.clone()), col_name.clone(), col_desc.clone(), token_prefix.clone(), mode) verify { assert_eq!(>::get(CollectionId(1)).unwrap().owner, caller); @@ -77,16 +80,6 @@ let collection = create_nft_collection::(caller.clone())?; >::add_to_allow_list(RawOrigin::Signed(caller.clone()).into(), collection, T::CrossAccountId::from_sub(allowlist_account.clone()))?; }: _(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(allowlist_account)) - - set_public_access_mode { - let caller: T::AccountId = account("caller", 0, SEED); - let collection = create_nft_collection::(caller.clone())?; - }: _(RawOrigin::Signed(caller.clone()), collection, AccessMode::AllowList) - - set_mint_permission { - let caller: T::AccountId = account("caller", 0, SEED); - let collection = create_nft_collection::(caller.clone())?; - }: _(RawOrigin::Signed(caller.clone()), collection, true) change_collection_owner { let caller: T::AccountId = account("caller", 0, SEED); @@ -145,7 +138,6 @@ owner_can_transfer: Some(true), sponsored_data_rate_limit: None, transfers_enabled: Some(true), - nesting_rule: None, }; }: set_collection_limits(RawOrigin::Signed(caller.clone()), collection, cl) } --- a/primitives/data-structs/src/lib.rs +++ b/primitives/data-structs/src/lib.rs @@ -469,6 +469,8 @@ #[derivative(Debug(format_with = "bounded::set_debug"))] BoundedBTreeSet>, ), + /// Used for tests + Permissive, } #[derive(Encode, Decode, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)] --- a/runtime/common/src/weights.rs +++ b/runtime/common/src/weights.rs @@ -89,4 +89,12 @@ fn burn_from() -> Weight { dispatch_weight::() + max_weight_of!(burn_from()) } + + fn burn_recursively_self_raw() -> Weight { + max_weight_of!(burn_recursively_self_raw()) + } + + fn burn_recursively_breadth_raw(amount: u32) -> Weight { + max_weight_of!(burn_recursively_breadth_raw(amount)) + } } --- a/runtime/unique/src/lib.rs +++ b/runtime/unique/src/lib.rs @@ -73,6 +73,7 @@ CollectionId, TokenId, TokenData, Property, PropertyKeyPermission, CollectionLimits, CollectionStats, RpcCollection, mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping}, + TokenChild, }; // use pallet_contracts::weights::WeightInfo; -- gitstuff