difftreelog
Revert "feat: burn children when destroying a collection"
in: master
This reverts commit 4b7f4d90a16f3a5ab26bed0511dabae078429724.
12 files changed
pallets/common/src/dispatch.rsdiffbeforeafterboth--- a/pallets/common/src/dispatch.rs
+++ b/pallets/common/src/dispatch.rs
@@ -6,7 +6,7 @@
weights::Pays,
traits::Get,
};
-use up_data_structs::{CollectionId, CreateCollectionData, budget::Budget};
+use up_data_structs::{CollectionId, CreateCollectionData};
use crate::{pallet::Config, CommonCollectionOperations, CollectionHandle};
@@ -57,11 +57,7 @@
pub trait CollectionDispatch<T: Config> {
fn create(sender: T::AccountId, data: CreateCollectionData<T::AccountId>) -> DispatchResult;
- fn destroy(
- sender: T::CrossAccountId,
- handle: CollectionHandle<T>,
- nesting_budget: &dyn Budget,
- ) -> DispatchResult;
+ fn destroy(sender: T::CrossAccountId, handle: CollectionHandle<T>) -> DispatchResult;
fn dispatch(handle: CollectionHandle<T>) -> Self;
fn into_inner(self) -> CollectionHandle<T>;
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -1169,12 +1169,6 @@
token: TokenId,
amount: u128,
) -> DispatchResultWithPostInfo;
- fn burn_item_unchecked(
- &self,
- owner: &T::CrossAccountId,
- token: TokenId,
- amount: u128,
- ) -> DispatchResult;
fn set_collection_properties(
&self,
sender: T::CrossAccountId,
pallets/fungible/src/common.rsdiffbeforeafterboth--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -170,17 +170,6 @@
)
}
- fn burn_item_unchecked(
- &self,
- owner: &T::CrossAccountId,
- _token: TokenId,
- amount: u128,
- ) -> sp_runtime::DispatchResult {
- <Pallet<T>>::burn_item_unchecked(self, owner, amount)?;
-
- Ok(())
- }
-
fn transfer(
&self,
from: T::CrossAccountId,
pallets/fungible/src/lib.rsdiffbeforeafterboth--- a/pallets/fungible/src/lib.rs
+++ b/pallets/fungible/src/lib.rs
@@ -160,36 +160,6 @@
owner: &T::CrossAccountId,
amount: u128,
) -> DispatchResult {
- if collection.access == AccessMode::AllowList {
- collection.check_allowlist(owner)?;
- }
-
- // =========
-
- Self::burn_item_unchecked(collection, owner, amount)?;
-
- <PalletEvm<T>>::deposit_log(
- ERC20Events::Transfer {
- from: *owner.as_eth(),
- to: H160::default(),
- value: amount.into(),
- }
- .to_log(collection_id_to_address(collection.id)),
- );
- <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(
- collection.id,
- TokenId::default(),
- owner.clone(),
- amount,
- ));
- Ok(())
- }
-
- pub fn burn_item_unchecked(
- collection: &FungibleHandle<T>,
- owner: &T::CrossAccountId,
- amount: u128,
- ) -> DispatchResult {
let total_supply = <TotalSupply<T>>::get(collection.id)
.checked_sub(amount)
.ok_or(<CommonError<T>>::TokenValueTooLow)?;
@@ -216,6 +186,20 @@
}
<TotalSupply<T>>::insert(collection.id, total_supply);
+ <PalletEvm<T>>::deposit_log(
+ ERC20Events::Transfer {
+ from: *owner.as_eth(),
+ to: H160::default(),
+ value: amount.into(),
+ }
+ .to_log(collection_id_to_address(collection.id)),
+ );
+ <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(
+ collection.id,
+ TokenId::default(),
+ owner.clone(),
+ amount,
+ ));
Ok(())
}
pallets/nonfungible/src/common.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -264,19 +264,6 @@
}
}
- fn burn_item_unchecked(
- &self,
- owner:& T::CrossAccountId,
- token: TokenId,
- amount: u128,
- ) -> sp_runtime::DispatchResult {
- if amount == 1 {
- <Pallet<T>>::burn_item_unchecked(self, owner, token)
- } else {
- Ok(())
- }
- }
-
fn transfer(
&self,
from: T::CrossAccountId,
pallets/nonfungible/src/lib.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -27,7 +27,6 @@
use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};
use pallet_common::{
Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, CollectionHandle,
- dispatch::CollectionDispatch,
eth::collection_id_to_address,
};
use pallet_structure::Pallet as PalletStructure;
@@ -80,8 +79,6 @@
NonfungibleItemsHaveNoAmount,
/// Unable to burn NFT with children
CantBurnNftWithChildren,
- /// Too many children to burn when destroying a collection
- TooManyChildrenToBurn,
}
#[pallet::config]
@@ -293,14 +290,13 @@
pub fn destroy_collection(
collection: NonfungibleHandle<T>,
sender: &T::CrossAccountId,
- nesting_budget: &dyn Budget,
) -> DispatchResult {
let id = collection.id;
// =========
- Self::burn_children_in_collection(id, nesting_budget)?;
PalletCommon::destroy_collection(collection.0, sender)?;
+
<TokenData<T>>::remove_prefix((id,), None);
<TokenChildren<T>>::remove_prefix((id,), None);
<Owned<T>>::remove_prefix((id,), None);
@@ -308,47 +304,9 @@
<TokensBurnt<T>>::remove(id);
<Allowance<T>>::remove_prefix((id,), None);
<AccountBalance<T>>::remove_prefix((id,), None);
- Ok(())
- }
-
- #[transactional]
- fn burn_children_in_collection(collection_id: CollectionId, nesting_budget: &dyn Budget) -> DispatchResult {
- for (parent_id, child) in <TokenChildren<T>>::drain_prefix((collection_id,))
- .map(|((parent_id, child), _)| (parent_id, child)) {
-
- let parent_address = T::CrossTokenAddressMapping::token_to_address(collection_id, parent_id);
- Self::burn_tree(parent_address, child.0, child.1, nesting_budget)?;
- }
-
Ok(())
}
- fn burn_tree(
- parent: T::CrossAccountId,
- collection_id: CollectionId,
- token_id: TokenId,
- nesting_budget: &dyn Budget
- ) -> DispatchResult {
- if !nesting_budget.consume() {
- return Err(<Error<T>>::TooManyChildrenToBurn.into());
- }
-
- let handle = <CollectionHandle<T>>::try_get(collection_id)?;
- let handle = T::CollectionDispatch::dispatch(handle);
- let handle = handle.as_dyn();
-
- let amount = handle.balance(parent.clone(), token_id);
-
- handle.burn_item_unchecked(&parent, token_id, amount)?;
-
- for child in <TokenChildren<T>>::drain_prefix((collection_id, token_id)).map(|(child, _)| child) {
- let parent = T::CrossTokenAddressMapping::token_to_address(collection_id, token_id);
- Self::burn_tree(parent, child.0, child.1, nesting_budget)?;
- }
-
- Ok(())
- }
-
pub fn burn(
collection: &NonfungibleHandle<T>,
sender: &T::CrossAccountId,
@@ -370,11 +328,31 @@
return Err(<Error<T>>::CantBurnNftWithChildren.into());
}
- let old_spender = <Allowance<T>>::get((collection.id, token));
+ let burnt = <TokensBurnt<T>>::get(collection.id)
+ .checked_add(1)
+ .ok_or(ArithmeticError::Overflow)?;
+
+ let balance = <AccountBalance<T>>::get((collection.id, token_data.owner.clone()))
+ .checked_sub(1)
+ .ok_or(ArithmeticError::Overflow)?;
+
+ if balance == 0 {
+ <AccountBalance<T>>::remove((collection.id, token_data.owner.clone()));
+ } else {
+ <AccountBalance<T>>::insert((collection.id, token_data.owner.clone()), balance);
+ }
+
+ if let Some(owner) = T::CrossTokenAddressMapping::address_to_token(&token_data.owner) {
+ Self::unnest(owner, (collection.id, token));
+ }
// =========
- Self::burn_item_unchecked(collection, &token_data.owner, token)?;
+ <Owned<T>>::remove((collection.id, &token_data.owner, token));
+ <TokensBurnt<T>>::insert(collection.id, burnt);
+ <TokenData<T>>::remove((collection.id, token));
+ <TokenProperties<T>>::remove((collection.id, token));
+ let old_spender = <Allowance<T>>::take((collection.id, token));
if let Some(old_spender) = old_spender {
<PalletCommon<T>>::deposit_event(CommonEvent::Approved(
@@ -400,40 +378,6 @@
token_data.owner,
1,
));
- Ok(())
- }
-
- pub fn burn_item_unchecked(
- collection: &NonfungibleHandle<T>,
- owner: &T::CrossAccountId,
- token: TokenId,
- ) -> DispatchResult {
- let burnt = <TokensBurnt<T>>::get(collection.id)
- .checked_add(1)
- .ok_or(ArithmeticError::Overflow)?;
-
- let balance = <AccountBalance<T>>::get((collection.id, owner.clone()))
- .checked_sub(1)
- .ok_or(ArithmeticError::Overflow)?;
-
- // =========
-
- if let Some(owner) = T::CrossTokenAddressMapping::address_to_token(owner) {
- Self::unnest(owner, (collection.id, token));
- }
-
- if balance == 0 {
- <AccountBalance<T>>::remove((collection.id, owner.clone()));
- } else {
- <AccountBalance<T>>::insert((collection.id, owner.clone()), balance);
- }
-
- <Owned<T>>::remove((collection.id, owner, token));
- <TokensBurnt<T>>::insert(collection.id, burnt);
- <TokenData<T>>::remove((collection.id, token));
- <TokenProperties<T>>::remove((collection.id, token));
- <Allowance<T>>::remove((collection.id, token));
-
Ok(())
}
pallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/lib.rs
+++ b/pallets/proxy-rmrk-core/src/lib.rs
@@ -179,8 +179,7 @@
ensure!(collection.total_supply() == 0, <Error<T>>::CollectionNotEmpty);
- let empty_budget = budget::Value::new(0);
- <PalletNft<T>>::destroy_collection(collection, &cross_sender, &empty_budget)
+ <PalletNft<T>>::destroy_collection(collection, &cross_sender)
.map_err(Self::map_common_err_to_proxy)?;
Self::deposit_event(Event::CollectionDestroyed { issuer: sender, collection_id });
pallets/refungible/src/common.rsdiffbeforeafterboth--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -205,15 +205,6 @@
)
}
- fn burn_item_unchecked(
- &self,
- owner: &T::CrossAccountId,
- token: TokenId,
- amount: u128,
- ) -> sp_runtime::DispatchResult {
- <Pallet<T>>::burn_item_unchecked(self, owner, token, amount)
- }
-
fn transfer(
&self,
from: T::CrossAccountId,
pallets/refungible/src/lib.rsdiffbeforeafterboth--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -245,25 +245,6 @@
token: TokenId,
amount: u128,
) -> DispatchResult {
- Self::burn_item_unchecked(collection, owner, token, amount)?;
-
- // TODO: ERC20 transfer event
- <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(
- collection.id,
- token,
- owner.clone(),
- amount,
- ));
-
- Ok(())
- }
-
- pub fn burn_item_unchecked(
- collection: &RefungibleHandle<T>,
- owner: &T::CrossAccountId,
- token: TokenId,
- amount: u128,
- ) -> DispatchResult {
let total_supply = <TotalSupply<T>>::get((collection.id, token))
.checked_sub(amount)
.ok_or(<CommonError<T>>::TokenValueTooLow)?;
@@ -318,6 +299,13 @@
<Balance<T>>::insert((collection.id, token, owner), balance);
}
<TotalSupply<T>>::insert((collection.id, token), total_supply);
+ // TODO: ERC20 transfer event
+ <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(
+ collection.id,
+ token,
+ owner.clone(),
+ amount,
+ ));
Ok(())
}
pallets/unique/src/lib.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617#![recursion_limit = "1024"]18#![cfg_attr(not(feature = "std"), no_std)]19#![allow(20 clippy::too_many_arguments,21 clippy::unnecessary_mut_passed,22 clippy::unused_unit23)]2425use frame_support::{26 decl_module, decl_storage, decl_error, decl_event,27 dispatch::DispatchResult,28 ensure,29 weights::{Weight},30 transactional,31 pallet_prelude::{DispatchResultWithPostInfo, ConstU32},32 BoundedVec,33};34use scale_info::TypeInfo;35use frame_system::{self as system, ensure_signed};36use sp_runtime::{sp_std::prelude::Vec};37use up_data_structs::{38 MAX_COLLECTION_NAME_LENGTH,39 MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH, AccessMode, CreateItemData,40 CollectionLimits, CollectionPermissions, CollectionId, CollectionMode, TokenId, SponsorshipState,41 CreateCollectionData, CreateItemExData, budget, Property, PropertyKey,42 PropertyKeyPermission,43};44use pallet_evm::account::CrossAccountId;45use pallet_common::{46 CollectionHandle, Pallet as PalletCommon, CommonWeightInfo, dispatch::dispatch_call,47 dispatch::CollectionDispatch,48};4950#[cfg(feature = "runtime-benchmarks")]51mod benchmarking;52pub mod weights;53use weights::WeightInfo;5455decl_error! {56 /// Error for non-fungible-token module.57 pub enum Error for Module<T: Config> {58 /// Decimal_points parameter must be lower than MAX_DECIMAL_POINTS constant, currently it is 30.59 CollectionDecimalPointLimitExceeded,60 /// This address is not set as sponsor, use setCollectionSponsor first.61 ConfirmUnsetSponsorFail,62 /// Length of items properties must be greater than 0.63 EmptyArgument,64 }65}6667pub trait Config: system::Config + pallet_common::Config + Sized + TypeInfo {68 type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;6970 /// Weight information for extrinsics in this pallet.71 type WeightInfo: WeightInfo;72 type CommonWeightInfo: CommonWeightInfo<Self::CrossAccountId>;73}7475decl_event! {76 pub enum Event<T>77 where78 <T as frame_system::Config>::AccountId,79 <T as pallet_evm::account::Config>::CrossAccountId,80 {81 /// Collection sponsor was removed82 ///83 /// # Arguments84 ///85 /// * collection_id: Globally unique collection identifier.86 CollectionSponsorRemoved(CollectionId),8788 /// Collection admin was added89 ///90 /// # Arguments91 ///92 /// * collection_id: Globally unique collection identifier.93 ///94 /// * admin: Admin address.95 CollectionAdminAdded(CollectionId, CrossAccountId),9697 /// Collection owned was change98 ///99 /// # Arguments100 ///101 /// * collection_id: Globally unique collection identifier.102 ///103 /// * owner: New owner address.104 CollectionOwnedChanged(CollectionId, AccountId),105106 /// Collection sponsor was set107 ///108 /// # Arguments109 ///110 /// * collection_id: Globally unique collection identifier.111 ///112 /// * owner: New sponsor address.113 CollectionSponsorSet(CollectionId, AccountId),114115 /// const on chain schema was set116 ///117 /// # Arguments118 ///119 /// * collection_id: Globally unique collection identifier.120 ConstOnChainSchemaSet(CollectionId),121122 /// New sponsor was confirm123 ///124 /// # Arguments125 ///126 /// * collection_id: Globally unique collection identifier.127 ///128 /// * sponsor: New sponsor address.129 SponsorshipConfirmed(CollectionId, AccountId),130131 /// Collection admin was removed132 ///133 /// # Arguments134 ///135 /// * collection_id: Globally unique collection identifier.136 ///137 /// * admin: Admin address.138 CollectionAdminRemoved(CollectionId, CrossAccountId),139140 /// Address was remove from allow list141 ///142 /// # Arguments143 ///144 /// * collection_id: Globally unique collection identifier.145 ///146 /// * user: Address.147 AllowListAddressRemoved(CollectionId, CrossAccountId),148149 /// Address was add to allow list150 ///151 /// # Arguments152 ///153 /// * collection_id: Globally unique collection identifier.154 ///155 /// * user: Address.156 AllowListAddressAdded(CollectionId, CrossAccountId),157158 /// Collection limits was set159 ///160 /// # Arguments161 ///162 /// * collection_id: Globally unique collection identifier.163 CollectionLimitSet(CollectionId),164165 CollectionPermissionSet(CollectionId),166167 /// Mint permission was set168 ///169 /// # Arguments170 ///171 /// * collection_id: Globally unique collection identifier.172 MintPermissionSet(CollectionId),173174 /// Offchain schema was set175 ///176 /// # Arguments177 ///178 /// * collection_id: Globally unique collection identifier.179 OffchainSchemaSet(CollectionId),180181 /// Public access mode was set182 ///183 /// # Arguments184 ///185 /// * collection_id: Globally unique collection identifier.186 ///187 /// * mode: New access state.188 PublicAccessModeSet(CollectionId, AccessMode),189190 /// Schema version was set191 ///192 /// # Arguments193 ///194 /// * collection_id: Globally unique collection identifier.195 SchemaVersionSet(CollectionId),196 }197}198199type SelfWeightOf<T> = <T as Config>::WeightInfo;200201// # Used definitions202//203// ## User control levels204//205// chain-controlled - key is uncontrolled by user206// i.e autoincrementing index207// can use non-cryptographic hash208// real - key is controlled by user209// but it is hard to generate enough colliding values, i.e owner of signed txs210// can use non-cryptographic hash211// controlled - key is completly controlled by users212// i.e maps with mutable keys213// should use cryptographic hash214//215// ## User control level downgrade reasons216//217// ?1 - chain-controlled -> controlled218// collections/tokens can be destroyed, resulting in massive holes219// ?2 - chain-controlled -> controlled220// same as ?1, but can be only added, resulting in easier exploitation221// ?3 - real -> controlled222// no confirmation required, so addresses can be easily generated223decl_storage! {224 trait Store for Module<T: Config> as Unique {225226 //#region Private members227 /// Used for migrations228 ChainVersion: u64;229 //#endregion230231 //#region Tokens transfer rate limit baskets232 /// (Collection id (controlled?2), who created (real))233 /// TODO: Off chain worker should remove from this map when collection gets removed234 pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => Option<T::BlockNumber>;235 /// Collection id (controlled?2), token id (controlled?2)236 pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;237 /// Collection id (controlled?2), owning user (real)238 pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;239 /// Collection id (controlled?2), token id (controlled?2)240 pub ReFungibleTransferBasket get(fn refungible_transfer_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;241 //#endregion242243 /// Variable metadata sponsoring244 /// Collection id (controlled?2), token id (controlled?2)245 #[deprecated]246 pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;247 pub TokenPropertyBasket get(fn token_property_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;248249 /// Approval sponsoring250 pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;251 pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;252 pub RefungibleApproveBasket get(fn refungible_approve_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;253 }254}255256decl_module! {257 pub struct Module<T: Config> for enum Call258 where259 origin: T::Origin260 {261 type Error = Error<T>;262263 fn deposit_event() = default;264265 fn on_initialize(_now: T::BlockNumber) -> Weight {266 0267 }268269 fn on_runtime_upgrade() -> Weight {270 let limit = None;271272 <VariableMetaDataBasket<T>>::remove_all(limit);273274 0275 }276277 /// This method creates a Collection of NFTs. Each Token may have multiple properties encoded as an array of bytes of certain length. The initial owner of the collection is set to the address that signed the transaction and can be changed later.278 ///279 /// # Permissions280 ///281 /// * Anyone.282 ///283 /// # Arguments284 ///285 /// * collection_name: UTF-16 string with collection name (limit 64 characters), will be stored as zero-terminated.286 ///287 /// * collection_description: UTF-16 string with collection description (limit 256 characters), will be stored as zero-terminated.288 ///289 /// * token_prefix: UTF-8 string with token prefix.290 ///291 /// * mode: [CollectionMode] collection type and type dependent data.292 // returns collection ID293 #[weight = <SelfWeightOf<T>>::create_collection()]294 #[transactional]295 #[deprecated]296 pub fn create_collection(origin,297 collection_name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,298 collection_description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,299 token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,300 mode: CollectionMode) -> DispatchResult {301 let data: CreateCollectionData<T::AccountId> = CreateCollectionData {302 name: collection_name,303 description: collection_description,304 token_prefix,305 mode,306 ..Default::default()307 };308 Self::create_collection_ex(origin, data)309 }310311 /// This method creates a collection312 ///313 /// Prefer it to deprecated [`created_collection`] method314 #[weight = <SelfWeightOf<T>>::create_collection()]315 #[transactional]316 pub fn create_collection_ex(origin, data: CreateCollectionData<T::AccountId>) -> DispatchResult {317 let sender = ensure_signed(origin)?;318319 // =========320321 T::CollectionDispatch::create(sender, data)?;322323 Ok(())324 }325326 /// **DANGEROUS**: Destroys collection and all NFTs within this collection. Users irrecoverably lose their assets and may lose real money.327 ///328 /// # Permissions329 ///330 /// * Collection Owner.331 ///332 /// # Arguments333 ///334 /// * collection_id: collection to destroy.335 #[weight =336 <SelfWeightOf<T>>::destroy_collection()337 + <SelfWeightOf<T>>::burn_children_in_collection(*max_children_to_burn)338 ]339 #[transactional]340 pub fn destroy_collection(341 origin,342 collection_id: CollectionId,343 max_children_to_burn: u32,344 ) -> DispatchResult {345 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);346 let collection = <CollectionHandle<T>>::try_get(collection_id)?;347348 let budget = budget::Value::new(max_children_to_burn);349350 // =========351352 T::CollectionDispatch::destroy(sender, collection, &budget)?;353354 <NftTransferBasket<T>>::remove_prefix(collection_id, None);355 <FungibleTransferBasket<T>>::remove_prefix(collection_id, None);356 <ReFungibleTransferBasket<T>>::remove_prefix((collection_id,), None);357358 <NftApproveBasket<T>>::remove_prefix(collection_id, None);359 <FungibleApproveBasket<T>>::remove_prefix(collection_id, None);360 <RefungibleApproveBasket<T>>::remove_prefix((collection_id,), None);361362 Ok(())363 }364365 /// Add an address to allow list.366 ///367 /// # Permissions368 ///369 /// * Collection Owner370 /// * Collection Admin371 ///372 /// # Arguments373 ///374 /// * collection_id.375 ///376 /// * address.377 #[weight = <SelfWeightOf<T>>::add_to_allow_list()]378 #[transactional]379 pub fn add_to_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{380381 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);382 let collection = <CollectionHandle<T>>::try_get(collection_id)?;383384 <PalletCommon<T>>::toggle_allowlist(385 &collection,386 &sender,387 &address,388 true,389 )?;390391 Self::deposit_event(Event::<T>::AllowListAddressAdded(392 collection_id,393 address394 ));395396 Ok(())397 }398399 /// Remove an address from allow list.400 ///401 /// # Permissions402 ///403 /// * Collection Owner404 /// * Collection Admin405 ///406 /// # Arguments407 ///408 /// * collection_id.409 ///410 /// * address.411 #[weight = <SelfWeightOf<T>>::remove_from_allow_list()]412 #[transactional]413 pub fn remove_from_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{414415 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);416 let collection = <CollectionHandle<T>>::try_get(collection_id)?;417418 <PalletCommon<T>>::toggle_allowlist(419 &collection,420 &sender,421 &address,422 false,423 )?;424425 <Pallet<T>>::deposit_event(Event::<T>::AllowListAddressRemoved(426 collection_id,427 address428 ));429430 Ok(())431 }432433 /// Change the owner of the collection.434 ///435 /// # Permissions436 ///437 /// * Collection Owner.438 ///439 /// # Arguments440 ///441 /// * collection_id.442 ///443 /// * new_owner.444 #[weight = <SelfWeightOf<T>>::change_collection_owner()]445 #[transactional]446 pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {447448 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);449450 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;451 target_collection.check_is_owner(&sender)?;452453 target_collection.owner = new_owner.clone();454 <Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(455 collection_id,456 new_owner457 ));458459 target_collection.save()460 }461462 /// Adds an admin of the Collection.463 /// NFT Collection can be controlled by multiple admin addresses (some which can also be servers, for example). Admins can issue and burn NFTs, as well as add and remove other admins, but cannot change NFT or Collection ownership.464 ///465 /// # Permissions466 ///467 /// * Collection Owner.468 /// * Collection Admin.469 ///470 /// # Arguments471 ///472 /// * collection_id: ID of the Collection to add admin for.473 ///474 /// * new_admin_id: Address of new admin to add.475 #[weight = <SelfWeightOf<T>>::add_collection_admin()]476 #[transactional]477 pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {478 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);479 let collection = <CollectionHandle<T>>::try_get(collection_id)?;480481 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminAdded(482 collection_id,483 new_admin_id.clone()484 ));485486 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)487 }488489 /// Remove admin address of the Collection. An admin address can remove itself. List of admins may become empty, in which case only Collection Owner will be able to add an Admin.490 ///491 /// # Permissions492 ///493 /// * Collection Owner.494 /// * Collection Admin.495 ///496 /// # Arguments497 ///498 /// * collection_id: ID of the Collection to remove admin for.499 ///500 /// * account_id: Address of admin to remove.501 #[weight = <SelfWeightOf<T>>::remove_collection_admin()]502 #[transactional]503 pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {504 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);505 let collection = <CollectionHandle<T>>::try_get(collection_id)?;506507 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminRemoved(508 collection_id,509 account_id.clone()510 ));511512 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)513 }514515 /// # Permissions516 ///517 /// * Collection Owner518 ///519 /// # Arguments520 ///521 /// * collection_id.522 ///523 /// * new_sponsor.524 #[weight = <SelfWeightOf<T>>::set_collection_sponsor()]525 #[transactional]526 pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {527 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);528529 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;530 target_collection.check_is_owner(&sender)?;531532 target_collection.sponsorship = SponsorshipState::Unconfirmed(new_sponsor.clone());533534 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(535 collection_id,536 new_sponsor537 ));538539 target_collection.save()540 }541542 /// # Permissions543 ///544 /// * Sponsor.545 ///546 /// # Arguments547 ///548 /// * collection_id.549 #[weight = <SelfWeightOf<T>>::confirm_sponsorship()]550 #[transactional]551 pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {552 let sender = ensure_signed(origin)?;553554 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;555 ensure!(556 target_collection.sponsorship.pending_sponsor() == Some(&sender),557 Error::<T>::ConfirmUnsetSponsorFail558 );559560 target_collection.sponsorship = SponsorshipState::Confirmed(sender.clone());561562 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(563 collection_id,564 sender565 ));566567 target_collection.save()568 }569570 /// Switch back to pay-per-own-transaction model.571 ///572 /// # Permissions573 ///574 /// * Collection owner.575 ///576 /// # Arguments577 ///578 /// * collection_id.579 #[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]580 #[transactional]581 pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {582 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);583584 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;585 target_collection.check_is_owner(&sender)?;586587 target_collection.sponsorship = SponsorshipState::Disabled;588589 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(590 collection_id591 ));592 target_collection.save()593 }594595 /// This method creates a concrete instance of NFT Collection created with CreateCollection method.596 ///597 /// # Permissions598 ///599 /// * Collection Owner.600 /// * Collection Admin.601 /// * Anyone if602 /// * Allow List is enabled, and603 /// * Address is added to allow list, and604 /// * MintPermission is enabled (see SetMintPermission method)605 ///606 /// # Arguments607 ///608 /// * collection_id: ID of the collection.609 ///610 /// * owner: Address, initial owner of the NFT.611 ///612 /// * data: Token data to store on chain.613 #[weight = T::CommonWeightInfo::create_item()]614 #[transactional]615 pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {616 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);617 let budget = budget::Value::new(2);618619 dispatch_call::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))620 }621622 /// This method creates multiple items in a collection created with CreateCollection method.623 ///624 /// # Permissions625 ///626 /// * Collection Owner.627 /// * Collection Admin.628 /// * Anyone if629 /// * Allow List is enabled, and630 /// * Address is added to allow list, and631 /// * MintPermission is enabled (see SetMintPermission method)632 ///633 /// # Arguments634 ///635 /// * collection_id: ID of the collection.636 ///637 /// * itemsData: Array items properties. Each property is an array of bytes itself, see [create_item].638 ///639 /// * owner: Address, initial owner of the NFT.640 #[weight = T::CommonWeightInfo::create_multiple_items(&items_data)]641 #[transactional]642 pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {643 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);644 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);645 let budget = budget::Value::new(2);646647 dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))648 }649650 #[weight = T::CommonWeightInfo::set_collection_properties(properties.len() as u32)]651 #[transactional]652 pub fn set_collection_properties(653 origin,654 collection_id: CollectionId,655 properties: Vec<Property>656 ) -> DispatchResultWithPostInfo {657 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);658659 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);660661 dispatch_call::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))662 }663664 #[weight = T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32)]665 #[transactional]666 pub fn delete_collection_properties(667 origin,668 collection_id: CollectionId,669 property_keys: Vec<PropertyKey>,670 ) -> DispatchResultWithPostInfo {671 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);672673 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);674675 dispatch_call::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))676 }677678 #[weight = T::CommonWeightInfo::set_token_properties(properties.len() as u32)]679 #[transactional]680 pub fn set_token_properties(681 origin,682 collection_id: CollectionId,683 token_id: TokenId,684 properties: Vec<Property>685 ) -> DispatchResultWithPostInfo {686 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);687688 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);689690 dispatch_call::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties))691 }692693 #[weight = T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32)]694 #[transactional]695 pub fn delete_token_properties(696 origin,697 collection_id: CollectionId,698 token_id: TokenId,699 property_keys: Vec<PropertyKey>700 ) -> DispatchResultWithPostInfo {701 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);702703 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);704705 dispatch_call::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys))706 }707708 #[weight = T::CommonWeightInfo::set_property_permissions(property_permissions.len() as u32)]709 #[transactional]710 pub fn set_property_permissions(711 origin,712 collection_id: CollectionId,713 property_permissions: Vec<PropertyKeyPermission>,714 ) -> DispatchResultWithPostInfo {715 ensure!(!property_permissions.is_empty(), Error::<T>::EmptyArgument);716717 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);718719 dispatch_call::<T, _>(collection_id, |d| d.set_property_permissions(&sender, property_permissions))720 }721722 #[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]723 #[transactional]724 pub fn create_multiple_items_ex(origin, collection_id: CollectionId, data: CreateItemExData<T::CrossAccountId>) -> DispatchResultWithPostInfo {725 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);726 let budget = budget::Value::new(2);727728 dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))729 }730731 // TODO! transaction weight732733 /// Set transfers_enabled value for particular collection734 ///735 /// # Permissions736 ///737 /// * Collection Owner.738 ///739 /// # Arguments740 ///741 /// * collection_id: ID of the collection.742 ///743 /// * value: New flag value.744 #[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]745 #[transactional]746 pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {747 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);748 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;749 target_collection.check_is_owner(&sender)?;750751 // =========752753 target_collection.limits.transfers_enabled = Some(value);754 target_collection.save()755 }756757 /// Destroys a concrete instance of NFT.758 ///759 /// # Permissions760 ///761 /// * Collection Owner.762 /// * Collection Admin.763 /// * Current NFT Owner.764 ///765 /// # Arguments766 ///767 /// * collection_id: ID of the collection.768 ///769 /// * item_id: ID of NFT to burn.770 #[weight = T::CommonWeightInfo::burn_item()]771 #[transactional]772 pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {773 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);774775 let post_info = dispatch_call::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;776 if value == 1 {777 <NftTransferBasket<T>>::remove(collection_id, item_id);778 <NftApproveBasket<T>>::remove(collection_id, item_id);779 }780 // Those maps should be cleared only if token disappears completly, need to move this part of logic to pallets?781 // <FungibleApproveBasket<T>>::remove(collection_id, sender.as_sub());782 // <RefungibleApproveBasket<T>>::remove((collection_id, item_id, sender.as_sub()));783 Ok(post_info)784 }785786 /// Destroys a concrete instance of NFT on behalf of the owner787 /// See also: [`approve`]788 ///789 /// # Permissions790 ///791 /// * Collection Owner.792 /// * Collection Admin.793 /// * Current NFT Owner.794 ///795 /// # Arguments796 ///797 /// * collection_id: ID of the collection.798 ///799 /// * item_id: ID of NFT to burn.800 ///801 /// * from: owner of item802 #[weight = T::CommonWeightInfo::burn_from()]803 #[transactional]804 pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {805 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);806 let budget = budget::Value::new(2);807808 dispatch_call::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value, &budget))809 }810811 /// Change ownership of the token.812 ///813 /// # Permissions814 ///815 /// * Collection Owner816 /// * Collection Admin817 /// * Current NFT owner818 ///819 /// # Arguments820 ///821 /// * recipient: Address of token recipient.822 ///823 /// * collection_id.824 ///825 /// * item_id: ID of the item826 /// * Non-Fungible Mode: Required.827 /// * Fungible Mode: Ignored.828 /// * Re-Fungible Mode: Required.829 ///830 /// * value: Amount to transfer.831 /// * Non-Fungible Mode: Ignored832 /// * Fungible Mode: Must specify transferred amount833 /// * Re-Fungible Mode: Must specify transferred portion (between 0 and 1)834 #[weight = T::CommonWeightInfo::transfer()]835 #[transactional]836 pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {837 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);838 let budget = budget::Value::new(2);839840 dispatch_call::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value, &budget))841 }842843 /// Set, change, or remove approved address to transfer the ownership of the NFT.844 ///845 /// # Permissions846 ///847 /// * Collection Owner848 /// * Collection Admin849 /// * Current NFT owner850 ///851 /// # Arguments852 ///853 /// * approved: Address that is approved to transfer this NFT or zero (if needed to remove approval).854 ///855 /// * collection_id.856 ///857 /// * item_id: ID of the item.858 #[weight = T::CommonWeightInfo::approve()]859 #[transactional]860 pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {861 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);862863 dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))864 }865866 /// 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.867 ///868 /// # Permissions869 /// * Collection Owner870 /// * Collection Admin871 /// * Current NFT owner872 /// * Address approved by current NFT owner873 ///874 /// # Arguments875 ///876 /// * from: Address that owns token.877 ///878 /// * recipient: Address of token recipient.879 ///880 /// * collection_id.881 ///882 /// * item_id: ID of the item.883 ///884 /// * value: Amount to transfer.885 #[weight = T::CommonWeightInfo::transfer_from()]886 #[transactional]887 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {888 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);889 let budget = budget::Value::new(2);890891 dispatch_call::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))892 }893894 #[weight = <SelfWeightOf<T>>::set_collection_limits()]895 #[transactional]896 pub fn set_collection_limits(897 origin,898 collection_id: CollectionId,899 new_limit: CollectionLimits,900 ) -> DispatchResult {901 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);902 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;903 target_collection.check_is_owner(&sender)?;904 let old_limit = &target_collection.limits;905906 target_collection.limits = <PalletCommon<T>>::clamp_limits(target_collection.mode.clone(), &old_limit, new_limit)?;907908 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(909 collection_id910 ));911912 target_collection.save()913 }914915 #[weight = <SelfWeightOf<T>>::set_collection_limits()]916 #[transactional]917 pub fn set_collection_permissions(918 origin,919 collection_id: CollectionId,920 new_limit: CollectionPermissions,921 ) -> DispatchResult {922 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);923 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;924 target_collection.check_is_owner(&sender)?;925 let old_limit = &target_collection.permissions;926927 target_collection.permissions = <PalletCommon<T>>::clamp_permissions(target_collection.mode.clone(), &old_limit, new_limit)?;928929 <Pallet<T>>::deposit_event(Event::<T>::CollectionPermissionSet(930 collection_id931 ));932933 target_collection.save()934 }935 }936}pallets/unique/src/weights.rsdiffbeforeafterboth--- a/pallets/unique/src/weights.rs
+++ b/pallets/unique/src/weights.rs
@@ -34,7 +34,6 @@
pub trait WeightInfo {
fn create_collection() -> Weight;
fn destroy_collection() -> Weight;
- fn burn_children_in_collection(max: u32) -> Weight;
fn add_to_allow_list() -> Weight;
fn remove_from_allow_list() -> Weight;
fn set_public_access_mode() -> Weight;
@@ -74,12 +73,6 @@
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
-
- fn burn_children_in_collection(max: u32) -> Weight {
- // TODO
- (50_000_000 as Weight).saturating_mul(max as Weight)
- }
-
// Storage: Common CollectionById (r:1 w:0)
// Storage: Common Allowlist (r:0 w:1)
fn add_to_allow_list() -> Weight {
@@ -199,12 +192,6 @@
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
}
-
- fn burn_children_in_collection(max: u32) -> Weight {
- // TODO
- (50_000_000 as Weight).saturating_mul(max as Weight)
- }
-
// Storage: Common CollectionById (r:1 w:0)
// Storage: Common Allowlist (r:0 w:1)
fn add_to_allow_list() -> Weight {
runtime/common/src/dispatch.rsdiffbeforeafterboth--- a/runtime/common/src/dispatch.rs
+++ b/runtime/common/src/dispatch.rs
@@ -1,4 +1,4 @@
-use frame_support::{dispatch::{DispatchResult}, ensure};
+use frame_support::{dispatch::DispatchResult, ensure};
use pallet_evm::PrecompileResult;
use sp_core::{H160, U256};
use sp_std::{borrow::ToOwned, vec::Vec};
@@ -12,7 +12,6 @@
use pallet_refungible::{Pallet as PalletRefungible, RefungibleHandle, erc::RefungibleTokenHandle};
use up_data_structs::{
CollectionMode, CreateCollectionData, MAX_DECIMAL_POINTS, mapping::TokenAddressMapping,
- budget::Budget,
};
pub enum CollectionDispatchT<T>
@@ -47,11 +46,7 @@
Ok(())
}
- fn destroy(
- sender: T::CrossAccountId,
- collection: CollectionHandle<T>,
- nesting_budget: &dyn Budget,
- ) -> DispatchResult {
+ fn destroy(sender: T::CrossAccountId, collection: CollectionHandle<T>) -> DispatchResult {
match collection.mode {
CollectionMode::ReFungible => {
PalletRefungible::destroy_collection(RefungibleHandle::cast(collection), &sender)?
@@ -60,11 +55,7 @@
PalletFungible::destroy_collection(FungibleHandle::cast(collection), &sender)?
}
CollectionMode::NFT => {
- PalletNonfungible::destroy_collection(
- NonfungibleHandle::cast(collection),
- &sender,
- nesting_budget,
- )?
+ PalletNonfungible::destroy_collection(NonfungibleHandle::cast(collection), &sender)?
}
}
Ok(())