difftreelog
decoupling of unique and refungible pallets
in: master
16 files changed
.gitignorediffbeforeafterboth--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,7 @@
/.idea/
/.cargo/
+/.vscode/
tests/.vscode
cumulus-parachain/
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6608,7 +6608,6 @@
"pallet-evm",
"pallet-evm-coder-substrate",
"pallet-nonfungible",
- "pallet-refungible",
"parity-scale-codec 3.1.5",
"scale-info",
"serde",
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -1258,6 +1258,10 @@
}
}
+pub trait RefungibleExtensionsWeightInfo {
+ fn repartition() -> Weight;
+}
+
pub trait CommonCollectionOperations<T: Config> {
fn create_item(
&self,
@@ -1384,6 +1388,19 @@
spender: T::CrossAccountId,
token: TokenId,
) -> u128;
+ fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>>;
+}
+
+pub trait RefungibleExtensions<T>
+where
+ T: Config,
+{
+ fn repartition(
+ &self,
+ owner: &T::CrossAccountId,
+ token: TokenId,
+ amount: u128,
+ ) -> DispatchResultWithPostInfo;
}
// Flexible enough for implementing CommonCollectionOperations
pallets/fungible/src/common.rsdiffbeforeafterboth--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -18,7 +18,7 @@
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_common::{CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions, with_weight};
use pallet_structure::Error as StructureError;
use sp_runtime::ArithmeticError;
use sp_std::{vec::Vec, vec};
@@ -399,4 +399,8 @@
}
<Allowance<T>>::get((self.id, sender, spender))
}
+
+ fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>> {
+ None
+ }
}
pallets/nonfungible/src/common.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -22,7 +22,8 @@
PropertyKeyPermission, PropertyValue,
};
use pallet_common::{
- CommonCollectionOperations, CommonWeightInfo, with_weight, weights::WeightInfo as _,
+ CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions, with_weight,
+ weights::WeightInfo as _,
};
use sp_runtime::DispatchError;
use sp_std::vec::Vec;
@@ -467,4 +468,8 @@
0
}
}
+
+ fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>> {
+ None
+ }
}
pallets/refungible/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/refungible/src/benchmarking.rs
+++ b/pallets/refungible/src/benchmarking.rs
@@ -203,4 +203,12 @@
let item = create_max_item(&collection, &owner, [(sender.clone(), 200)])?;
<Pallet<T>>::set_allowance(&collection, &sender, &burner, item, 200)?;
}: {<Pallet<T>>::burn_from(&collection, &burner, &sender, item, 200, &Unlimited)?}
+
+ repartition_item {
+ bench_init!{
+ owner: sub; collection: collection(owner);
+ sender: cross_from_sub(owner); owner: cross_sub;
+ };
+ let item = create_max_item(&collection, &sender, [(owner.clone(), 100)])?;
+ }: {<Pallet<T>>::repartition(&collection, &owner, item, 200)?}
}
pallets/refungible/src/common.rsdiffbeforeafterboth--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -22,9 +22,9 @@
CollectionId, TokenId, CreateItemExData, CreateRefungibleExData, budget::Budget, Property,
PropertyKey, PropertyValue, PropertyKeyPermission, CreateItemData,
};
-use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};
+use pallet_common::{CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions, with_weight};
use pallet_structure::Error as StructureError;
-use sp_runtime::DispatchError;
+use sp_runtime::{DispatchError};
use sp_std::{vec::Vec, vec};
use crate::{
@@ -405,4 +405,22 @@
) -> u128 {
<Allowance<T>>::get((self.id, token, sender, spender))
}
+
+ fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>> {
+ Some(self)
+ }
+}
+
+impl<T: Config> RefungibleExtensions<T> for RefungibleHandle<T> {
+ fn repartition(
+ &self,
+ owner: &T::CrossAccountId,
+ token: TokenId,
+ amount: u128,
+ ) -> DispatchResultWithPostInfo {
+ with_weight(
+ <Pallet<T>>::repartition(self, owner, token, amount),
+ <SelfWeightOf<T>>::repartition_item(),
+ )
+ }
}
pallets/refungible/src/lib.rsdiffbeforeafterboth--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -688,8 +688,8 @@
}
pub fn repartition(
+ collection: &RefungibleHandle<T>,
owner: &T::CrossAccountId,
- collection: &RefungibleHandle<T>,
token: TokenId,
amount: u128,
) -> DispatchResult {
pallets/refungible/src/weights.rsdiffbeforeafterboth--- a/pallets/refungible/src/weights.rs
+++ b/pallets/refungible/src/weights.rs
@@ -3,7 +3,7 @@
//! Autogenerated weights for pallet_refungible
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2022-06-15, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2022-06-27, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024
// Executed Command:
@@ -49,6 +49,7 @@
fn transfer_from_removing() -> Weight;
fn transfer_from_creating_removing() -> Weight;
fn burn_from() -> Weight;
+ fn repartition_item() -> Weight;
}
/// Weights for pallet_refungible using the Substrate node and recommended hardware.
@@ -61,7 +62,7 @@
// Storage: Refungible TokenData (r:0 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn create_item() -> Weight {
- (21_321_000 as Weight)
+ (17_553_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(6 as Weight))
}
@@ -72,9 +73,9 @@
// Storage: Refungible TokenData (r:0 w:4)
// Storage: Refungible Owned (r:0 w:4)
fn create_multiple_items(b: u32, ) -> Weight {
- (16_313_000 as Weight)
- // Standard Error: 4_000
- .saturating_add((5_464_000 as Weight).saturating_mul(b as Weight))
+ (10_654_000 as Weight)
+ // Standard Error: 1_000
+ .saturating_add((5_114_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
.saturating_add(T::DbWeight::get().writes((4 as Weight).saturating_mul(b as Weight)))
@@ -86,9 +87,9 @@
// Storage: Refungible TokenData (r:0 w:4)
// Storage: Refungible Owned (r:0 w:4)
fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight {
- (15_631_000 as Weight)
- // Standard Error: 5_000
- .saturating_add((8_141_000 as Weight).saturating_mul(b as Weight))
+ (3_587_000 as Weight)
+ // Standard Error: 2_000
+ .saturating_add((7_931_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
@@ -101,9 +102,9 @@
// Storage: Refungible Balance (r:0 w:4)
// Storage: Refungible Owned (r:0 w:4)
fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight {
- (11_191_000 as Weight)
- // Standard Error: 4_000
- .saturating_add((6_321_000 as Weight).saturating_mul(b as Weight))
+ (1_980_000 as Weight)
+ // Standard Error: 2_000
+ .saturating_add((6_305_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
@@ -114,7 +115,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn burn_item_partial() -> Weight {
- (24_421_000 as Weight)
+ (21_010_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
@@ -125,13 +126,13 @@
// Storage: Refungible TokenData (r:0 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn burn_item_fully() -> Weight {
- (32_900_000 as Weight)
+ (28_413_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(6 as Weight))
}
// Storage: Refungible Balance (r:2 w:2)
fn transfer_normal() -> Weight {
- (20_215_000 as Weight)
+ (17_513_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
@@ -139,7 +140,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_creating() -> Weight {
- (24_809_000 as Weight)
+ (20_469_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
@@ -147,7 +148,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_removing() -> Weight {
- (26_704_000 as Weight)
+ (22_472_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
@@ -155,21 +156,21 @@
// Storage: Refungible AccountBalance (r:2 w:2)
// Storage: Refungible Owned (r:0 w:2)
fn transfer_creating_removing() -> Weight {
- (28_728_000 as Weight)
+ (24_866_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(6 as Weight))
}
// Storage: Refungible Balance (r:1 w:0)
// Storage: Refungible Allowance (r:0 w:1)
fn approve() -> Weight {
- (16_107_000 as Weight)
+ (13_475_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
// Storage: Refungible Allowance (r:1 w:1)
// Storage: Refungible Balance (r:2 w:2)
fn transfer_from_normal() -> Weight {
- (28_765_000 as Weight)
+ (24_707_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
@@ -178,7 +179,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_from_creating() -> Weight {
- (32_788_000 as Weight)
+ (27_812_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
@@ -187,7 +188,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_from_removing() -> Weight {
- (34_523_000 as Weight)
+ (29_966_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
@@ -196,7 +197,7 @@
// Storage: Refungible AccountBalance (r:2 w:2)
// Storage: Refungible Owned (r:0 w:2)
fn transfer_from_creating_removing() -> Weight {
- (36_749_000 as Weight)
+ (31_660_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(7 as Weight))
}
@@ -208,10 +209,17 @@
// Storage: Refungible TokenData (r:0 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn burn_from() -> Weight {
- (42_259_000 as Weight)
+ (36_248_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(7 as Weight))
}
+ // Storage: Refungible TotalSupply (r:1 w:1)
+ // Storage: Refungible Balance (r:1 w:1)
+ fn repartition_item() -> Weight {
+ (8_226_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(2 as Weight))
+ .saturating_add(T::DbWeight::get().writes(2 as Weight))
+ }
}
// For backwards compatibility and tests
@@ -223,7 +231,7 @@
// Storage: Refungible TokenData (r:0 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn create_item() -> Weight {
- (21_321_000 as Weight)
+ (17_553_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(6 as Weight))
}
@@ -234,9 +242,9 @@
// Storage: Refungible TokenData (r:0 w:4)
// Storage: Refungible Owned (r:0 w:4)
fn create_multiple_items(b: u32, ) -> Weight {
- (16_313_000 as Weight)
- // Standard Error: 4_000
- .saturating_add((5_464_000 as Weight).saturating_mul(b as Weight))
+ (10_654_000 as Weight)
+ // Standard Error: 1_000
+ .saturating_add((5_114_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
.saturating_add(RocksDbWeight::get().writes((4 as Weight).saturating_mul(b as Weight)))
@@ -248,9 +256,9 @@
// Storage: Refungible TokenData (r:0 w:4)
// Storage: Refungible Owned (r:0 w:4)
fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight {
- (15_631_000 as Weight)
- // Standard Error: 5_000
- .saturating_add((8_141_000 as Weight).saturating_mul(b as Weight))
+ (3_587_000 as Weight)
+ // Standard Error: 2_000
+ .saturating_add((7_931_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
@@ -263,9 +271,9 @@
// Storage: Refungible Balance (r:0 w:4)
// Storage: Refungible Owned (r:0 w:4)
fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight {
- (11_191_000 as Weight)
- // Standard Error: 4_000
- .saturating_add((6_321_000 as Weight).saturating_mul(b as Weight))
+ (1_980_000 as Weight)
+ // Standard Error: 2_000
+ .saturating_add((6_305_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
@@ -276,7 +284,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn burn_item_partial() -> Weight {
- (24_421_000 as Weight)
+ (21_010_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
}
@@ -287,13 +295,13 @@
// Storage: Refungible TokenData (r:0 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn burn_item_fully() -> Weight {
- (32_900_000 as Weight)
+ (28_413_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(6 as Weight))
}
// Storage: Refungible Balance (r:2 w:2)
fn transfer_normal() -> Weight {
- (20_215_000 as Weight)
+ (17_513_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
@@ -301,7 +309,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_creating() -> Weight {
- (24_809_000 as Weight)
+ (20_469_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
}
@@ -309,7 +317,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_removing() -> Weight {
- (26_704_000 as Weight)
+ (22_472_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
}
@@ -317,21 +325,21 @@
// Storage: Refungible AccountBalance (r:2 w:2)
// Storage: Refungible Owned (r:0 w:2)
fn transfer_creating_removing() -> Weight {
- (28_728_000 as Weight)
+ (24_866_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(6 as Weight))
}
// Storage: Refungible Balance (r:1 w:0)
// Storage: Refungible Allowance (r:0 w:1)
fn approve() -> Weight {
- (16_107_000 as Weight)
+ (13_475_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
// Storage: Refungible Allowance (r:1 w:1)
// Storage: Refungible Balance (r:2 w:2)
fn transfer_from_normal() -> Weight {
- (28_765_000 as Weight)
+ (24_707_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
@@ -340,7 +348,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_from_creating() -> Weight {
- (32_788_000 as Weight)
+ (27_812_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
}
@@ -349,7 +357,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_from_removing() -> Weight {
- (34_523_000 as Weight)
+ (29_966_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
}
@@ -358,7 +366,7 @@
// Storage: Refungible AccountBalance (r:2 w:2)
// Storage: Refungible Owned (r:0 w:2)
fn transfer_from_creating_removing() -> Weight {
- (36_749_000 as Weight)
+ (31_660_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(7 as Weight))
}
@@ -370,8 +378,15 @@
// Storage: Refungible TokenData (r:0 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn burn_from() -> Weight {
- (42_259_000 as Weight)
+ (36_248_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(7 as Weight))
}
+ // Storage: Refungible TotalSupply (r:1 w:1)
+ // Storage: Refungible Balance (r:1 w:1)
+ fn repartition_item() -> Weight {
+ (8_226_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(2 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(2 as Weight))
+ }
}
pallets/unique/Cargo.tomldiffbeforeafterboth--- a/pallets/unique/Cargo.toml
+++ b/pallets/unique/Cargo.toml
@@ -103,4 +103,3 @@
evm-coder = { default-features = false, path = '../../crates/evm-coder' }
pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }
pallet-nonfungible = { default-features = false, path = '../../pallets/nonfungible' }
-pallet-refungible = { default-features = false, path = '../../pallets/refungible' }
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)]2425extern crate alloc;2627use frame_support::{28 decl_module, decl_storage, decl_error, decl_event,29 dispatch::DispatchResult,30 ensure, fail,31 weights::{Weight},32 transactional,33 pallet_prelude::{DispatchResultWithPostInfo, ConstU32},34 BoundedVec,35};36use scale_info::TypeInfo;37use frame_system::{self as system, ensure_signed};38use sp_runtime::{sp_std::prelude::Vec};39use up_data_structs::{40 MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,41 CreateItemData, CollectionLimits, CollectionPermissions, CollectionId, CollectionMode, TokenId,42 SponsorshipState, CreateCollectionData, CreateItemExData, budget, Property, PropertyKey,43 PropertyKeyPermission,44};45use pallet_evm::account::CrossAccountId;46use pallet_common::{47 CollectionHandle, Pallet as PalletCommon, CommonWeightInfo, dispatch::dispatch_tx,48 dispatch::CollectionDispatch, RefungibleExtensionsWeightInfo,49};50pub mod eth;5152#[cfg(feature = "runtime-benchmarks")]53mod benchmarking;54pub mod weights;55use weights::WeightInfo;5657const NESTING_BUDGET: u32 = 5;5859decl_error! {60 /// Error for non-fungible-token module.61 pub enum Error for Module<T: Config> {62 /// Decimal_points parameter must be lower than MAX_DECIMAL_POINTS constant, currently it is 30.63 CollectionDecimalPointLimitExceeded,64 /// This address is not set as sponsor, use setCollectionSponsor first.65 ConfirmUnsetSponsorFail,66 /// Length of items properties must be greater than 0.67 EmptyArgument,68 /// Repertition is only supported by refungible collection69 RepartitionCalledOnNonRefungibleCollection,70 }71}7273pub trait Config: system::Config + pallet_common::Config + Sized + TypeInfo {74 type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;7576 /// Weight information for extrinsics in this pallet.77 type WeightInfo: WeightInfo;78 type CommonWeightInfo: CommonWeightInfo<Self::CrossAccountId>;79 type RefungibleExtensionsWeightInfo: RefungibleExtensionsWeightInfo;80}8182decl_event! {83 pub enum Event<T>84 where85 <T as frame_system::Config>::AccountId,86 <T as pallet_evm::account::Config>::CrossAccountId,87 {88 /// Collection sponsor was removed89 ///90 /// # Arguments91 ///92 /// * collection_id: Globally unique collection identifier.93 CollectionSponsorRemoved(CollectionId),9495 /// Collection admin was added96 ///97 /// # Arguments98 ///99 /// * collection_id: Globally unique collection identifier.100 ///101 /// * admin: Admin address.102 CollectionAdminAdded(CollectionId, CrossAccountId),103104 /// Collection owned was change105 ///106 /// # Arguments107 ///108 /// * collection_id: Globally unique collection identifier.109 ///110 /// * owner: New owner address.111 CollectionOwnedChanged(CollectionId, AccountId),112113 /// Collection sponsor was set114 ///115 /// # Arguments116 ///117 /// * collection_id: Globally unique collection identifier.118 ///119 /// * owner: New sponsor address.120 CollectionSponsorSet(CollectionId, AccountId),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),166 }167}168169type SelfWeightOf<T> = <T as Config>::WeightInfo;170171// # Used definitions172//173// ## User control levels174//175// chain-controlled - key is uncontrolled by user176// i.e autoincrementing index177// can use non-cryptographic hash178// real - key is controlled by user179// but it is hard to generate enough colliding values, i.e owner of signed txs180// can use non-cryptographic hash181// controlled - key is completly controlled by users182// i.e maps with mutable keys183// should use cryptographic hash184//185// ## User control level downgrade reasons186//187// ?1 - chain-controlled -> controlled188// collections/tokens can be destroyed, resulting in massive holes189// ?2 - chain-controlled -> controlled190// same as ?1, but can be only added, resulting in easier exploitation191// ?3 - real -> controlled192// no confirmation required, so addresses can be easily generated193decl_storage! {194 trait Store for Module<T: Config> as Unique {195196 //#region Private members197 /// Used for migrations198 ChainVersion: u64;199 //#endregion200201 //#region Tokens transfer rate limit baskets202 /// (Collection id (controlled?2), who created (real))203 /// TODO: Off chain worker should remove from this map when collection gets removed204 pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => Option<T::BlockNumber>;205 /// Collection id (controlled?2), token id (controlled?2)206 pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;207 /// Collection id (controlled?2), owning user (real)208 pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;209 /// Collection id (controlled?2), token id (controlled?2)210 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>;211 //#endregion212213 /// Variable metadata sponsoring214 /// Collection id (controlled?2), token id (controlled?2)215 #[deprecated]216 pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;217 pub TokenPropertyBasket get(fn token_property_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;218219 /// Approval sponsoring220 pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;221 pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;222 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>;223 }224}225226decl_module! {227 pub struct Module<T: Config> for enum Call228 where229 origin: T::Origin230 {231 type Error = Error<T>;232233 fn deposit_event() = default;234235 fn on_initialize(_now: T::BlockNumber) -> Weight {236 0237 }238239 fn on_runtime_upgrade() -> Weight {240 let limit = None;241242 <VariableMetaDataBasket<T>>::remove_all(limit);243244 0245 }246247 /// 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.248 ///249 /// # Permissions250 ///251 /// * Anyone.252 ///253 /// # Arguments254 ///255 /// * collection_name: UTF-16 string with collection name (limit 64 characters), will be stored as zero-terminated.256 ///257 /// * collection_description: UTF-16 string with collection description (limit 256 characters), will be stored as zero-terminated.258 ///259 /// * token_prefix: UTF-8 string with token prefix.260 ///261 /// * mode: [CollectionMode] collection type and type dependent data.262 // returns collection ID263 #[weight = <SelfWeightOf<T>>::create_collection()]264 #[transactional]265 #[deprecated]266 pub fn create_collection(origin,267 collection_name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,268 collection_description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,269 token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,270 mode: CollectionMode) -> DispatchResult {271 let data: CreateCollectionData<T::AccountId> = CreateCollectionData {272 name: collection_name,273 description: collection_description,274 token_prefix,275 mode,276 ..Default::default()277 };278 Self::create_collection_ex(origin, data)279 }280281 /// This method creates a collection282 ///283 /// Prefer it to deprecated [`created_collection`] method284 #[weight = <SelfWeightOf<T>>::create_collection()]285 #[transactional]286 pub fn create_collection_ex(origin, data: CreateCollectionData<T::AccountId>) -> DispatchResult {287 let sender = ensure_signed(origin)?;288289 // =========290291 T::CollectionDispatch::create(T::CrossAccountId::from_sub(sender), data)?;292293 Ok(())294 }295296 /// **DANGEROUS**: Destroys collection and all NFTs within this collection. Users irrecoverably lose their assets and may lose real money.297 ///298 /// # Permissions299 ///300 /// * Collection Owner.301 ///302 /// # Arguments303 ///304 /// * collection_id: collection to destroy.305 #[weight = <SelfWeightOf<T>>::destroy_collection()]306 #[transactional]307 pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {308 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);309 let collection = <CollectionHandle<T>>::try_get(collection_id)?;310 collection.check_is_internal()?;311312 // =========313314 T::CollectionDispatch::destroy(sender, collection)?;315316 <NftTransferBasket<T>>::remove_prefix(collection_id, None);317 <FungibleTransferBasket<T>>::remove_prefix(collection_id, None);318 <ReFungibleTransferBasket<T>>::remove_prefix((collection_id,), None);319320 <NftApproveBasket<T>>::remove_prefix(collection_id, None);321 <FungibleApproveBasket<T>>::remove_prefix(collection_id, None);322 <RefungibleApproveBasket<T>>::remove_prefix((collection_id,), None);323324 Ok(())325 }326327 /// Add an address to allow list.328 ///329 /// # Permissions330 ///331 /// * Collection Owner332 /// * Collection Admin333 ///334 /// # Arguments335 ///336 /// * collection_id.337 ///338 /// * address.339 #[weight = <SelfWeightOf<T>>::add_to_allow_list()]340 #[transactional]341 pub fn add_to_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{342343 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);344 let collection = <CollectionHandle<T>>::try_get(collection_id)?;345 collection.check_is_internal()?;346347 <PalletCommon<T>>::toggle_allowlist(348 &collection,349 &sender,350 &address,351 true,352 )?;353354 Self::deposit_event(Event::<T>::AllowListAddressAdded(355 collection_id,356 address357 ));358359 Ok(())360 }361362 /// Remove an address from allow list.363 ///364 /// # Permissions365 ///366 /// * Collection Owner367 /// * Collection Admin368 ///369 /// # Arguments370 ///371 /// * collection_id.372 ///373 /// * address.374 #[weight = <SelfWeightOf<T>>::remove_from_allow_list()]375 #[transactional]376 pub fn remove_from_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{377378 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);379 let collection = <CollectionHandle<T>>::try_get(collection_id)?;380 collection.check_is_internal()?;381382 <PalletCommon<T>>::toggle_allowlist(383 &collection,384 &sender,385 &address,386 false,387 )?;388389 <Pallet<T>>::deposit_event(Event::<T>::AllowListAddressRemoved(390 collection_id,391 address392 ));393394 Ok(())395 }396397 /// Change the owner of the collection.398 ///399 /// # Permissions400 ///401 /// * Collection Owner.402 ///403 /// # Arguments404 ///405 /// * collection_id.406 ///407 /// * new_owner.408 #[weight = <SelfWeightOf<T>>::change_collection_owner()]409 #[transactional]410 pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {411412 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);413414 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;415 target_collection.check_is_internal()?;416 target_collection.check_is_owner(&sender)?;417418 target_collection.owner = new_owner.clone();419 <Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(420 collection_id,421 new_owner422 ));423424 target_collection.save()425 }426427 /// Adds an admin of the Collection.428 /// 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.429 ///430 /// # Permissions431 ///432 /// * Collection Owner.433 /// * Collection Admin.434 ///435 /// # Arguments436 ///437 /// * collection_id: ID of the Collection to add admin for.438 ///439 /// * new_admin_id: Address of new admin to add.440 #[weight = <SelfWeightOf<T>>::add_collection_admin()]441 #[transactional]442 pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {443 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);444 let collection = <CollectionHandle<T>>::try_get(collection_id)?;445 collection.check_is_internal()?;446447 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminAdded(448 collection_id,449 new_admin_id.clone()450 ));451452 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)453 }454455 /// 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.456 ///457 /// # Permissions458 ///459 /// * Collection Owner.460 /// * Collection Admin.461 ///462 /// # Arguments463 ///464 /// * collection_id: ID of the Collection to remove admin for.465 ///466 /// * account_id: Address of admin to remove.467 #[weight = <SelfWeightOf<T>>::remove_collection_admin()]468 #[transactional]469 pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {470 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);471 let collection = <CollectionHandle<T>>::try_get(collection_id)?;472 collection.check_is_internal()?;473474 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminRemoved(475 collection_id,476 account_id.clone()477 ));478479 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)480 }481482 /// # Permissions483 ///484 /// * Collection Owner485 ///486 /// # Arguments487 ///488 /// * collection_id.489 ///490 /// * new_sponsor.491 #[weight = <SelfWeightOf<T>>::set_collection_sponsor()]492 #[transactional]493 pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {494 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);495496 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;497 target_collection.check_is_owner_or_admin(&sender)?;498 target_collection.check_is_internal()?;499500 target_collection.set_sponsor(new_sponsor.clone())?;501502 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(503 collection_id,504 new_sponsor505 ));506507 target_collection.save()508 }509510 /// # Permissions511 ///512 /// * Sponsor.513 ///514 /// # Arguments515 ///516 /// * collection_id.517 #[weight = <SelfWeightOf<T>>::confirm_sponsorship()]518 #[transactional]519 pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {520 let sender = ensure_signed(origin)?;521522 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;523 target_collection.check_is_internal()?;524 ensure!(525 target_collection.confirm_sponsorship(&sender)?,526 Error::<T>::ConfirmUnsetSponsorFail527 );528529 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(530 collection_id,531 sender532 ));533534 target_collection.save()535 }536537 /// Switch back to pay-per-own-transaction model.538 ///539 /// # Permissions540 ///541 /// * Collection owner.542 ///543 /// # Arguments544 ///545 /// * collection_id.546 #[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]547 #[transactional]548 pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {549 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);550551 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;552 target_collection.check_is_internal()?;553 target_collection.check_is_owner(&sender)?;554555 target_collection.sponsorship = SponsorshipState::Disabled;556557 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(558 collection_id559 ));560 target_collection.save()561 }562563 /// This method creates a concrete instance of NFT Collection created with CreateCollection method.564 ///565 /// # Permissions566 ///567 /// * Collection Owner.568 /// * Collection Admin.569 /// * Anyone if570 /// * Allow List is enabled, and571 /// * Address is added to allow list, and572 /// * MintPermission is enabled (see SetMintPermission method)573 ///574 /// # Arguments575 ///576 /// * collection_id: ID of the collection.577 ///578 /// * owner: Address, initial owner of the NFT.579 ///580 /// * data: Token data to store on chain.581 #[weight = T::CommonWeightInfo::create_item()]582 #[transactional]583 pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {584 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);585 let budget = budget::Value::new(NESTING_BUDGET);586587 dispatch_tx::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))588 }589590 /// This method creates multiple items in a collection created with CreateCollection method.591 ///592 /// # Permissions593 ///594 /// * Collection Owner.595 /// * Collection Admin.596 /// * Anyone if597 /// * Allow List is enabled, and598 /// * Address is added to allow list, and599 /// * MintPermission is enabled (see SetMintPermission method)600 ///601 /// # Arguments602 ///603 /// * collection_id: ID of the collection.604 ///605 /// * itemsData: Array items properties. Each property is an array of bytes itself, see [create_item].606 ///607 /// * owner: Address, initial owner of the NFT.608 #[weight = T::CommonWeightInfo::create_multiple_items(&items_data)]609 #[transactional]610 pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {611 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);612 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);613 let budget = budget::Value::new(NESTING_BUDGET);614615 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))616 }617618 #[weight = T::CommonWeightInfo::set_collection_properties(properties.len() as u32)]619 #[transactional]620 pub fn set_collection_properties(621 origin,622 collection_id: CollectionId,623 properties: Vec<Property>624 ) -> DispatchResultWithPostInfo {625 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);626627 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);628629 dispatch_tx::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))630 }631632 #[weight = T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32)]633 #[transactional]634 pub fn delete_collection_properties(635 origin,636 collection_id: CollectionId,637 property_keys: Vec<PropertyKey>,638 ) -> DispatchResultWithPostInfo {639 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);640641 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);642643 dispatch_tx::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))644 }645646 #[weight = T::CommonWeightInfo::set_token_properties(properties.len() as u32)]647 #[transactional]648 pub fn set_token_properties(649 origin,650 collection_id: CollectionId,651 token_id: TokenId,652 properties: Vec<Property>653 ) -> DispatchResultWithPostInfo {654 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);655656 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);657658 dispatch_tx::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties))659 }660661 #[weight = T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32)]662 #[transactional]663 pub fn delete_token_properties(664 origin,665 collection_id: CollectionId,666 token_id: TokenId,667 property_keys: Vec<PropertyKey>668 ) -> DispatchResultWithPostInfo {669 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);670671 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);672673 dispatch_tx::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys))674 }675676 #[weight = T::CommonWeightInfo::set_token_property_permissions(property_permissions.len() as u32)]677 #[transactional]678 pub fn set_token_property_permissions(679 origin,680 collection_id: CollectionId,681 property_permissions: Vec<PropertyKeyPermission>,682 ) -> DispatchResultWithPostInfo {683 ensure!(!property_permissions.is_empty(), Error::<T>::EmptyArgument);684685 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);686687 dispatch_tx::<T, _>(collection_id, |d| d.set_token_property_permissions(&sender, property_permissions))688 }689690 #[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]691 #[transactional]692 pub fn create_multiple_items_ex(origin, collection_id: CollectionId, data: CreateItemExData<T::CrossAccountId>) -> DispatchResultWithPostInfo {693 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);694 let budget = budget::Value::new(NESTING_BUDGET);695696 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))697 }698699 /// Set transfers_enabled value for particular collection700 ///701 /// # Permissions702 ///703 /// * Collection Owner.704 ///705 /// # Arguments706 ///707 /// * collection_id: ID of the collection.708 ///709 /// * value: New flag value.710 #[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]711 #[transactional]712 pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {713 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);714 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;715 target_collection.check_is_internal()?;716 target_collection.check_is_owner(&sender)?;717718 // =========719720 target_collection.limits.transfers_enabled = Some(value);721 target_collection.save()722 }723724 /// Destroys a concrete instance of NFT.725 ///726 /// # Permissions727 ///728 /// * Collection Owner.729 /// * Collection Admin.730 /// * Current NFT Owner.731 ///732 /// # Arguments733 ///734 /// * collection_id: ID of the collection.735 ///736 /// * item_id: ID of NFT to burn.737 #[weight = T::CommonWeightInfo::burn_item()]738 #[transactional]739 pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {740 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);741742 let post_info = dispatch_tx::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;743 if value == 1 {744 <NftTransferBasket<T>>::remove(collection_id, item_id);745 <NftApproveBasket<T>>::remove(collection_id, item_id);746 }747 // Those maps should be cleared only if token disappears completly, need to move this part of logic to pallets?748 // <FungibleApproveBasket<T>>::remove(collection_id, sender.as_sub());749 // <RefungibleApproveBasket<T>>::remove((collection_id, item_id, sender.as_sub()));750 Ok(post_info)751 }752753 /// Destroys a concrete instance of NFT on behalf of the owner754 /// See also: [`approve`]755 ///756 /// # Permissions757 ///758 /// * Collection Owner.759 /// * Collection Admin.760 /// * Current NFT Owner.761 ///762 /// # Arguments763 ///764 /// * collection_id: ID of the collection.765 ///766 /// * item_id: ID of NFT to burn.767 ///768 /// * from: owner of item769 #[weight = T::CommonWeightInfo::burn_from()]770 #[transactional]771 pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {772 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);773 let budget = budget::Value::new(NESTING_BUDGET);774775 dispatch_tx::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value, &budget))776 }777778 /// Change ownership of the token.779 ///780 /// # Permissions781 ///782 /// * Collection Owner783 /// * Collection Admin784 /// * Current NFT owner785 ///786 /// # Arguments787 ///788 /// * recipient: Address of token recipient.789 ///790 /// * collection_id.791 ///792 /// * item_id: ID of the item793 /// * Non-Fungible Mode: Required.794 /// * Fungible Mode: Ignored.795 /// * Re-Fungible Mode: Required.796 ///797 /// * value: Amount to transfer.798 /// * Non-Fungible Mode: Ignored799 /// * Fungible Mode: Must specify transferred amount800 /// * Re-Fungible Mode: Must specify transferred portion (between 0 and 1)801 #[weight = T::CommonWeightInfo::transfer()]802 #[transactional]803 pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {804 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);805 let budget = budget::Value::new(NESTING_BUDGET);806807 dispatch_tx::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value, &budget))808 }809810 /// Set, change, or remove approved address to transfer the ownership of the NFT.811 ///812 /// # Permissions813 ///814 /// * Collection Owner815 /// * Collection Admin816 /// * Current NFT owner817 ///818 /// # Arguments819 ///820 /// * approved: Address that is approved to transfer this NFT or zero (if needed to remove approval).821 ///822 /// * collection_id.823 ///824 /// * item_id: ID of the item.825 #[weight = T::CommonWeightInfo::approve()]826 #[transactional]827 pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {828 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);829830 dispatch_tx::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))831 }832833 /// 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.834 ///835 /// # Permissions836 /// * Collection Owner837 /// * Collection Admin838 /// * Current NFT owner839 /// * Address approved by current NFT owner840 ///841 /// # Arguments842 ///843 /// * from: Address that owns token.844 ///845 /// * recipient: Address of token recipient.846 ///847 /// * collection_id.848 ///849 /// * item_id: ID of the item.850 ///851 /// * value: Amount to transfer.852 #[weight = T::CommonWeightInfo::transfer_from()]853 #[transactional]854 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {855 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);856 let budget = budget::Value::new(NESTING_BUDGET);857858 dispatch_tx::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))859 }860861 #[weight = <SelfWeightOf<T>>::set_collection_limits()]862 #[transactional]863 pub fn set_collection_limits(864 origin,865 collection_id: CollectionId,866 new_limit: CollectionLimits,867 ) -> DispatchResult {868 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);869 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;870 target_collection.check_is_internal()?;871 target_collection.check_is_owner_or_admin(&sender)?;872 let old_limit = &target_collection.limits;873874 target_collection.limits = <PalletCommon<T>>::clamp_limits(target_collection.mode.clone(), &old_limit, new_limit)?;875876 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(877 collection_id878 ));879880 target_collection.save()881 }882883 #[weight = <SelfWeightOf<T>>::set_collection_limits()]884 #[transactional]885 pub fn set_collection_permissions(886 origin,887 collection_id: CollectionId,888 new_limit: CollectionPermissions,889 ) -> DispatchResult {890 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);891 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;892 target_collection.check_is_internal()?;893 target_collection.check_is_owner_or_admin(&sender)?;894 let old_limit = &target_collection.permissions;895896 target_collection.permissions = <PalletCommon<T>>::clamp_permissions(target_collection.mode.clone(), &old_limit, new_limit)?;897898 <Pallet<T>>::deposit_event(Event::<T>::CollectionPermissionSet(899 collection_id900 ));901902 target_collection.save()903 }904905 #[weight = T::RefungibleExtensionsWeightInfo::repartition()]906 #[transactional]907 pub fn repartition(908 origin,909 collection_id: CollectionId,910 token: TokenId,911 amount: u128,912 ) -> DispatchResultWithPostInfo {913 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);914 dispatch_tx::<T, _>(collection_id, |d| {915 if let Some(refungible_extensions) = d.refungible_extensions() {916 refungible_extensions.repartition(&sender, token, amount)917 } else {918 fail!(<Error<T>>::RepartitionCalledOnNonRefungibleCollection)919 }920 })921 }922 }923}pallets/unique/src/weights.rsdiffbeforeafterboth--- a/pallets/unique/src/weights.rs
+++ b/pallets/unique/src/weights.rs
@@ -3,7 +3,7 @@
//! Autogenerated weights for pallet_unique
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2022-06-15, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2022-06-28, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024
// Executed Command:
@@ -57,7 +57,7 @@
// Storage: Common CollectionProperties (r:0 w:1)
// Storage: Common CollectionById (r:0 w:1)
fn create_collection() -> Weight {
- (39_427_000 as Weight)
+ (53_511_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(6 as Weight))
}
@@ -69,27 +69,27 @@
// Storage: Common AdminAmount (r:0 w:1)
// Storage: Common CollectionProperties (r:0 w:1)
fn destroy_collection() -> Weight {
- (48_339_000 as Weight)
+ (69_481_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(6 as Weight))
}
// Storage: Common CollectionById (r:1 w:0)
// Storage: Common Allowlist (r:0 w:1)
fn add_to_allow_list() -> Weight {
- (17_379_000 as Weight)
+ (22_892_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
// Storage: Common CollectionById (r:1 w:0)
// Storage: Common Allowlist (r:0 w:1)
fn remove_from_allow_list() -> Weight {
- (17_490_000 as Weight)
+ (22_973_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
// Storage: Common CollectionById (r:1 w:1)
fn change_collection_owner() -> Weight {
- (17_701_000 as Weight)
+ (22_392_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
@@ -97,7 +97,7 @@
// Storage: Common IsAdmin (r:1 w:1)
// Storage: Common AdminAmount (r:1 w:1)
fn add_collection_admin() -> Weight {
- (23_301_000 as Weight)
+ (30_298_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
@@ -105,37 +105,37 @@
// Storage: Common IsAdmin (r:1 w:1)
// Storage: Common AdminAmount (r:1 w:1)
fn remove_collection_admin() -> Weight {
- (24_859_000 as Weight)
+ (32_842_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
// Storage: Common CollectionById (r:1 w:1)
fn set_collection_sponsor() -> Weight {
- (17_795_000 as Weight)
+ (22_613_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
// Storage: Common CollectionById (r:1 w:1)
fn confirm_sponsorship() -> Weight {
- (17_297_000 as Weight)
+ (22_462_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
// Storage: Common CollectionById (r:1 w:1)
fn remove_collection_sponsor() -> Weight {
- (17_079_000 as Weight)
+ (21_730_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
// Storage: Common CollectionById (r:1 w:1)
fn set_transfers_enabled_flag() -> Weight {
- (9_734_000 as Weight)
+ (10_941_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
// Storage: Common CollectionById (r:1 w:1)
fn set_collection_limits() -> Weight {
- (17_998_000 as Weight)
+ (22_363_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
@@ -150,7 +150,7 @@
// Storage: Common CollectionProperties (r:0 w:1)
// Storage: Common CollectionById (r:0 w:1)
fn create_collection() -> Weight {
- (39_427_000 as Weight)
+ (53_511_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(6 as Weight))
}
@@ -162,27 +162,27 @@
// Storage: Common AdminAmount (r:0 w:1)
// Storage: Common CollectionProperties (r:0 w:1)
fn destroy_collection() -> Weight {
- (48_339_000 as Weight)
+ (69_481_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(6 as Weight))
}
// Storage: Common CollectionById (r:1 w:0)
// Storage: Common Allowlist (r:0 w:1)
fn add_to_allow_list() -> Weight {
- (17_379_000 as Weight)
+ (22_892_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
// Storage: Common CollectionById (r:1 w:0)
// Storage: Common Allowlist (r:0 w:1)
fn remove_from_allow_list() -> Weight {
- (17_490_000 as Weight)
+ (22_973_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
// Storage: Common CollectionById (r:1 w:1)
fn change_collection_owner() -> Weight {
- (17_701_000 as Weight)
+ (22_392_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
@@ -190,7 +190,7 @@
// Storage: Common IsAdmin (r:1 w:1)
// Storage: Common AdminAmount (r:1 w:1)
fn add_collection_admin() -> Weight {
- (23_301_000 as Weight)
+ (30_298_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
@@ -198,37 +198,37 @@
// Storage: Common IsAdmin (r:1 w:1)
// Storage: Common AdminAmount (r:1 w:1)
fn remove_collection_admin() -> Weight {
- (24_859_000 as Weight)
+ (32_842_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
// Storage: Common CollectionById (r:1 w:1)
fn set_collection_sponsor() -> Weight {
- (17_795_000 as Weight)
+ (22_613_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
// Storage: Common CollectionById (r:1 w:1)
fn confirm_sponsorship() -> Weight {
- (17_297_000 as Weight)
+ (22_462_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
// Storage: Common CollectionById (r:1 w:1)
fn remove_collection_sponsor() -> Weight {
- (17_079_000 as Weight)
+ (21_730_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
// Storage: Common CollectionById (r:1 w:1)
fn set_transfers_enabled_flag() -> Weight {
- (9_734_000 as Weight)
+ (10_941_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
// Storage: Common CollectionById (r:1 w:1)
fn set_collection_limits() -> Weight {
- (17_998_000 as Weight)
+ (22_363_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
runtime/common/src/weights.rsdiffbeforeafterboth--- a/runtime/common/src/weights.rs
+++ b/runtime/common/src/weights.rs
@@ -16,11 +16,13 @@
use core::marker::PhantomData;
use frame_support::{weights::Weight};
-use pallet_common::{CommonWeightInfo, dispatch::dispatch_weight};
+use pallet_common::{CommonWeightInfo, dispatch::dispatch_weight, RefungibleExtensionsWeightInfo};
use pallet_fungible::{Config as FungibleConfig, common::CommonWeights as FungibleWeights};
use pallet_nonfungible::{Config as NonfungibleConfig, common::CommonWeights as NonfungibleWeights};
-use pallet_refungible::{Config as RefungibleConfig, common::CommonWeights as RefungibleWeights};
+use pallet_refungible::{
+ Config as RefungibleConfig, weights::WeightInfo, common::CommonWeights as RefungibleWeights,
+};
use up_data_structs::{CreateItemExData, CreateItemData};
macro_rules! max_weight_of {
@@ -98,3 +100,12 @@
max_weight_of!(burn_recursively_breadth_raw(amount))
}
}
+
+impl<T> RefungibleExtensionsWeightInfo for CommonWeights<T>
+where
+ T: FungibleConfig + NonfungibleConfig + RefungibleConfig,
+{
+ fn repartition() -> Weight {
+ dispatch_weight::<T>() + <<T as RefungibleConfig>::WeightInfo>::repartition_item()
+ }
+}
runtime/opal/src/lib.rsdiffbeforeafterboth--- a/runtime/opal/src/lib.rs
+++ b/runtime/opal/src/lib.rs
@@ -925,6 +925,7 @@
type Event = Event;
type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;
type CommonWeightInfo = CommonWeights<Self>;
+ type RefungibleExtensionsWeightInfo = CommonWeights<Self>;
}
parameter_types! {
runtime/tests/src/lib.rsdiffbeforeafterboth--- a/runtime/tests/src/lib.rs
+++ b/runtime/tests/src/lib.rs
@@ -255,6 +255,7 @@
type Event = ();
type WeightInfo = ();
type CommonWeightInfo = CommonWeights<Self>;
+ type RefungibleExtensionsWeightInfo = CommonWeights<Self>;
}
// Build genesis storage according to the mock runtime.
runtime/tests/src/tests.rsdiffbeforeafterboth--- a/runtime/tests/src/tests.rs
+++ b/runtime/tests/src/tests.rs
@@ -21,7 +21,7 @@
CreateReFungibleData, MAX_DECIMAL_POINTS, COLLECTION_ADMINS_LIMIT, TokenId,
MAX_TOKEN_OWNERSHIP, CreateCollectionData, CollectionMode, AccessMode, CollectionPermissions,
PropertyKeyPermission, PropertyPermission, Property, CollectionPropertiesVec,
- CollectionPropertiesPermissionsVec, TokenChild,
+ CollectionPropertiesPermissionsVec,
};
use frame_support::{assert_noop, assert_ok, assert_err};
use sp_std::convert::TryInto;