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,49};50use pallet_refungible::{Pallet as PalletRefungible, RefungibleHandle};51pub mod eth;5253#[cfg(feature = "runtime-benchmarks")]54mod benchmarking;55pub mod weights;56use weights::WeightInfo;5758const NESTING_BUDGET: u32 = 5;5960decl_error! {61 /// Error for non-fungible-token module.62 pub enum Error for Module<T: Config> {63 /// Decimal_points parameter must be lower than MAX_DECIMAL_POINTS constant, currently it is 30.64 CollectionDecimalPointLimitExceeded,65 /// This address is not set as sponsor, use setCollectionSponsor first.66 ConfirmUnsetSponsorFail,67 /// Length of items properties must be greater than 0.68 EmptyArgument,69 /// Repertition is only supported by refungible collection70 RepartitionCalledOnNonRefungibleCollection,71 }72}7374pub trait Config:75 system::Config + pallet_common::Config + pallet_refungible::Config + Sized + TypeInfo76{77 type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;7879 /// Weight information for extrinsics in this pallet.80 type WeightInfo: WeightInfo;81 type CommonWeightInfo: CommonWeightInfo<Self::CrossAccountId>;82}8384decl_event! {85 pub enum Event<T>86 where87 <T as frame_system::Config>::AccountId,88 <T as pallet_evm::account::Config>::CrossAccountId,89 {90 /// Collection sponsor was removed91 ///92 /// # Arguments93 ///94 /// * collection_id: Globally unique collection identifier.95 CollectionSponsorRemoved(CollectionId),9697 /// Collection admin was added98 ///99 /// # Arguments100 ///101 /// * collection_id: Globally unique collection identifier.102 ///103 /// * admin: Admin address.104 CollectionAdminAdded(CollectionId, CrossAccountId),105106 /// Collection owned was change107 ///108 /// # Arguments109 ///110 /// * collection_id: Globally unique collection identifier.111 ///112 /// * owner: New owner address.113 CollectionOwnedChanged(CollectionId, AccountId),114115 /// Collection sponsor was set116 ///117 /// # Arguments118 ///119 /// * collection_id: Globally unique collection identifier.120 ///121 /// * owner: New sponsor address.122 CollectionSponsorSet(CollectionId, AccountId),123124 /// New sponsor was confirm125 ///126 /// # Arguments127 ///128 /// * collection_id: Globally unique collection identifier.129 ///130 /// * sponsor: New sponsor address.131 SponsorshipConfirmed(CollectionId, AccountId),132133 /// Collection admin was removed134 ///135 /// # Arguments136 ///137 /// * collection_id: Globally unique collection identifier.138 ///139 /// * admin: Admin address.140 CollectionAdminRemoved(CollectionId, CrossAccountId),141142 /// Address was remove from allow list143 ///144 /// # Arguments145 ///146 /// * collection_id: Globally unique collection identifier.147 ///148 /// * user: Address.149 AllowListAddressRemoved(CollectionId, CrossAccountId),150151 /// Address was add to allow list152 ///153 /// # Arguments154 ///155 /// * collection_id: Globally unique collection identifier.156 ///157 /// * user: Address.158 AllowListAddressAdded(CollectionId, CrossAccountId),159160 /// Collection limits was set161 ///162 /// # Arguments163 ///164 /// * collection_id: Globally unique collection identifier.165 CollectionLimitSet(CollectionId),166167 CollectionPermissionSet(CollectionId),168 }169}170171type SelfWeightOf<T> = <T as Config>::WeightInfo;172173// # Used definitions174//175// ## User control levels176//177// chain-controlled - key is uncontrolled by user178// i.e autoincrementing index179// can use non-cryptographic hash180// real - key is controlled by user181// but it is hard to generate enough colliding values, i.e owner of signed txs182// can use non-cryptographic hash183// controlled - key is completly controlled by users184// i.e maps with mutable keys185// should use cryptographic hash186//187// ## User control level downgrade reasons188//189// ?1 - chain-controlled -> controlled190// collections/tokens can be destroyed, resulting in massive holes191// ?2 - chain-controlled -> controlled192// same as ?1, but can be only added, resulting in easier exploitation193// ?3 - real -> controlled194// no confirmation required, so addresses can be easily generated195decl_storage! {196 trait Store for Module<T: Config> as Unique {197198 //#region Private members199 /// Used for migrations200 ChainVersion: u64;201 //#endregion202203 //#region Tokens transfer rate limit baskets204 /// (Collection id (controlled?2), who created (real))205 /// TODO: Off chain worker should remove from this map when collection gets removed206 pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => Option<T::BlockNumber>;207 /// Collection id (controlled?2), token id (controlled?2)208 pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;209 /// Collection id (controlled?2), owning user (real)210 pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;211 /// Collection id (controlled?2), token id (controlled?2)212 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>;213 //#endregion214215 /// Variable metadata sponsoring216 /// Collection id (controlled?2), token id (controlled?2)217 #[deprecated]218 pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;219 pub TokenPropertyBasket get(fn token_property_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;220221 /// Approval sponsoring222 pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;223 pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;224 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>;225 }226}227228decl_module! {229 pub struct Module<T: Config> for enum Call230 where231 origin: T::Origin232 {233 type Error = Error<T>;234235 fn deposit_event() = default;236237 fn on_initialize(_now: T::BlockNumber) -> Weight {238 0239 }240241 fn on_runtime_upgrade() -> Weight {242 let limit = None;243244 <VariableMetaDataBasket<T>>::remove_all(limit);245246 0247 }248249 /// 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.250 ///251 /// # Permissions252 ///253 /// * Anyone.254 ///255 /// # Arguments256 ///257 /// * collection_name: UTF-16 string with collection name (limit 64 characters), will be stored as zero-terminated.258 ///259 /// * collection_description: UTF-16 string with collection description (limit 256 characters), will be stored as zero-terminated.260 ///261 /// * token_prefix: UTF-8 string with token prefix.262 ///263 /// * mode: [CollectionMode] collection type and type dependent data.264 // returns collection ID265 #[weight = <SelfWeightOf<T>>::create_collection()]266 #[transactional]267 #[deprecated]268 pub fn create_collection(origin,269 collection_name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,270 collection_description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,271 token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,272 mode: CollectionMode) -> DispatchResult {273 let data: CreateCollectionData<T::AccountId> = CreateCollectionData {274 name: collection_name,275 description: collection_description,276 token_prefix,277 mode,278 ..Default::default()279 };280 Self::create_collection_ex(origin, data)281 }282283 /// This method creates a collection284 ///285 /// Prefer it to deprecated [`created_collection`] method286 #[weight = <SelfWeightOf<T>>::create_collection()]287 #[transactional]288 pub fn create_collection_ex(origin, data: CreateCollectionData<T::AccountId>) -> DispatchResult {289 let sender = ensure_signed(origin)?;290291 // =========292293 T::CollectionDispatch::create(T::CrossAccountId::from_sub(sender), data)?;294295 Ok(())296 }297298 /// **DANGEROUS**: Destroys collection and all NFTs within this collection. Users irrecoverably lose their assets and may lose real money.299 ///300 /// # Permissions301 ///302 /// * Collection Owner.303 ///304 /// # Arguments305 ///306 /// * collection_id: collection to destroy.307 #[weight = <SelfWeightOf<T>>::destroy_collection()]308 #[transactional]309 pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {310 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);311 let collection = <CollectionHandle<T>>::try_get(collection_id)?;312 collection.check_is_internal()?;313314 // =========315316 T::CollectionDispatch::destroy(sender, collection)?;317318 <NftTransferBasket<T>>::remove_prefix(collection_id, None);319 <FungibleTransferBasket<T>>::remove_prefix(collection_id, None);320 <ReFungibleTransferBasket<T>>::remove_prefix((collection_id,), None);321322 <NftApproveBasket<T>>::remove_prefix(collection_id, None);323 <FungibleApproveBasket<T>>::remove_prefix(collection_id, None);324 <RefungibleApproveBasket<T>>::remove_prefix((collection_id,), None);325326 Ok(())327 }328329 /// Add an address to allow list.330 ///331 /// # Permissions332 ///333 /// * Collection Owner334 /// * Collection Admin335 ///336 /// # Arguments337 ///338 /// * collection_id.339 ///340 /// * address.341 #[weight = <SelfWeightOf<T>>::add_to_allow_list()]342 #[transactional]343 pub fn add_to_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{344345 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);346 let collection = <CollectionHandle<T>>::try_get(collection_id)?;347 collection.check_is_internal()?;348349 <PalletCommon<T>>::toggle_allowlist(350 &collection,351 &sender,352 &address,353 true,354 )?;355356 Self::deposit_event(Event::<T>::AllowListAddressAdded(357 collection_id,358 address359 ));360361 Ok(())362 }363364 /// Remove an address from allow list.365 ///366 /// # Permissions367 ///368 /// * Collection Owner369 /// * Collection Admin370 ///371 /// # Arguments372 ///373 /// * collection_id.374 ///375 /// * address.376 #[weight = <SelfWeightOf<T>>::remove_from_allow_list()]377 #[transactional]378 pub fn remove_from_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{379380 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);381 let collection = <CollectionHandle<T>>::try_get(collection_id)?;382 collection.check_is_internal()?;383384 <PalletCommon<T>>::toggle_allowlist(385 &collection,386 &sender,387 &address,388 false,389 )?;390391 <Pallet<T>>::deposit_event(Event::<T>::AllowListAddressRemoved(392 collection_id,393 address394 ));395396 Ok(())397 }398399 /// Change the owner of the collection.400 ///401 /// # Permissions402 ///403 /// * Collection Owner.404 ///405 /// # Arguments406 ///407 /// * collection_id.408 ///409 /// * new_owner.410 #[weight = <SelfWeightOf<T>>::change_collection_owner()]411 #[transactional]412 pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {413414 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);415416 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;417 target_collection.check_is_internal()?;418 target_collection.check_is_owner(&sender)?;419420 target_collection.owner = new_owner.clone();421 <Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(422 collection_id,423 new_owner424 ));425426 target_collection.save()427 }428429 /// Adds an admin of the Collection.430 /// 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.431 ///432 /// # Permissions433 ///434 /// * Collection Owner.435 /// * Collection Admin.436 ///437 /// # Arguments438 ///439 /// * collection_id: ID of the Collection to add admin for.440 ///441 /// * new_admin_id: Address of new admin to add.442 #[weight = <SelfWeightOf<T>>::add_collection_admin()]443 #[transactional]444 pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {445 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);446 let collection = <CollectionHandle<T>>::try_get(collection_id)?;447 collection.check_is_internal()?;448449 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminAdded(450 collection_id,451 new_admin_id.clone()452 ));453454 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)455 }456457 /// 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.458 ///459 /// # Permissions460 ///461 /// * Collection Owner.462 /// * Collection Admin.463 ///464 /// # Arguments465 ///466 /// * collection_id: ID of the Collection to remove admin for.467 ///468 /// * account_id: Address of admin to remove.469 #[weight = <SelfWeightOf<T>>::remove_collection_admin()]470 #[transactional]471 pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {472 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);473 let collection = <CollectionHandle<T>>::try_get(collection_id)?;474 collection.check_is_internal()?;475476 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminRemoved(477 collection_id,478 account_id.clone()479 ));480481 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)482 }483484 /// # Permissions485 ///486 /// * Collection Owner487 ///488 /// # Arguments489 ///490 /// * collection_id.491 ///492 /// * new_sponsor.493 #[weight = <SelfWeightOf<T>>::set_collection_sponsor()]494 #[transactional]495 pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {496 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);497498 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;499 target_collection.check_is_owner_or_admin(&sender)?;500 target_collection.check_is_internal()?;501502 target_collection.set_sponsor(new_sponsor.clone())?;503504 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(505 collection_id,506 new_sponsor507 ));508509 target_collection.save()510 }511512 /// # Permissions513 ///514 /// * Sponsor.515 ///516 /// # Arguments517 ///518 /// * collection_id.519 #[weight = <SelfWeightOf<T>>::confirm_sponsorship()]520 #[transactional]521 pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {522 let sender = ensure_signed(origin)?;523524 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;525 target_collection.check_is_internal()?;526 ensure!(527 target_collection.confirm_sponsorship(&sender)?,528 Error::<T>::ConfirmUnsetSponsorFail529 );530531 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(532 collection_id,533 sender534 ));535536 target_collection.save()537 }538539 /// Switch back to pay-per-own-transaction model.540 ///541 /// # Permissions542 ///543 /// * Collection owner.544 ///545 /// # Arguments546 ///547 /// * collection_id.548 #[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]549 #[transactional]550 pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {551 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);552553 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;554 target_collection.check_is_internal()?;555 target_collection.check_is_owner(&sender)?;556557 target_collection.sponsorship = SponsorshipState::Disabled;558559 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(560 collection_id561 ));562 target_collection.save()563 }564565 /// This method creates a concrete instance of NFT Collection created with CreateCollection method.566 ///567 /// # Permissions568 ///569 /// * Collection Owner.570 /// * Collection Admin.571 /// * Anyone if572 /// * Allow List is enabled, and573 /// * Address is added to allow list, and574 /// * MintPermission is enabled (see SetMintPermission method)575 ///576 /// # Arguments577 ///578 /// * collection_id: ID of the collection.579 ///580 /// * owner: Address, initial owner of the NFT.581 ///582 /// * data: Token data to store on chain.583 #[weight = T::CommonWeightInfo::create_item()]584 #[transactional]585 pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {586 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);587 let budget = budget::Value::new(NESTING_BUDGET);588589 dispatch_tx::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))590 }591592 /// This method creates multiple items in a collection created with CreateCollection method.593 ///594 /// # Permissions595 ///596 /// * Collection Owner.597 /// * Collection Admin.598 /// * Anyone if599 /// * Allow List is enabled, and600 /// * Address is added to allow list, and601 /// * MintPermission is enabled (see SetMintPermission method)602 ///603 /// # Arguments604 ///605 /// * collection_id: ID of the collection.606 ///607 /// * itemsData: Array items properties. Each property is an array of bytes itself, see [create_item].608 ///609 /// * owner: Address, initial owner of the NFT.610 #[weight = T::CommonWeightInfo::create_multiple_items(&items_data)]611 #[transactional]612 pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {613 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);614 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);615 let budget = budget::Value::new(NESTING_BUDGET);616617 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))618 }619620 #[weight = T::CommonWeightInfo::set_collection_properties(properties.len() as u32)]621 #[transactional]622 pub fn set_collection_properties(623 origin,624 collection_id: CollectionId,625 properties: Vec<Property>626 ) -> DispatchResultWithPostInfo {627 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);628629 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);630631 dispatch_tx::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))632 }633634 #[weight = T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32)]635 #[transactional]636 pub fn delete_collection_properties(637 origin,638 collection_id: CollectionId,639 property_keys: Vec<PropertyKey>,640 ) -> DispatchResultWithPostInfo {641 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);642643 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);644645 dispatch_tx::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))646 }647648 #[weight = T::CommonWeightInfo::set_token_properties(properties.len() as u32)]649 #[transactional]650 pub fn set_token_properties(651 origin,652 collection_id: CollectionId,653 token_id: TokenId,654 properties: Vec<Property>655 ) -> DispatchResultWithPostInfo {656 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);657658 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);659660 dispatch_tx::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties))661 }662663 #[weight = T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32)]664 #[transactional]665 pub fn delete_token_properties(666 origin,667 collection_id: CollectionId,668 token_id: TokenId,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_tx::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys))676 }677678 #[weight = T::CommonWeightInfo::set_token_property_permissions(property_permissions.len() as u32)]679 #[transactional]680 pub fn set_token_property_permissions(681 origin,682 collection_id: CollectionId,683 property_permissions: Vec<PropertyKeyPermission>,684 ) -> DispatchResultWithPostInfo {685 ensure!(!property_permissions.is_empty(), Error::<T>::EmptyArgument);686687 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);688689 dispatch_tx::<T, _>(collection_id, |d| d.set_token_property_permissions(&sender, property_permissions))690 }691692 #[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]693 #[transactional]694 pub fn create_multiple_items_ex(origin, collection_id: CollectionId, data: CreateItemExData<T::CrossAccountId>) -> DispatchResultWithPostInfo {695 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);696 let budget = budget::Value::new(NESTING_BUDGET);697698 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))699 }700701 /// Set transfers_enabled value for particular collection702 ///703 /// # Permissions704 ///705 /// * Collection Owner.706 ///707 /// # Arguments708 ///709 /// * collection_id: ID of the collection.710 ///711 /// * value: New flag value.712 #[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]713 #[transactional]714 pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {715 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);716 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;717 target_collection.check_is_internal()?;718 target_collection.check_is_owner(&sender)?;719720 // =========721722 target_collection.limits.transfers_enabled = Some(value);723 target_collection.save()724 }725726 /// Destroys a concrete instance of NFT.727 ///728 /// # Permissions729 ///730 /// * Collection Owner.731 /// * Collection Admin.732 /// * Current NFT Owner.733 ///734 /// # Arguments735 ///736 /// * collection_id: ID of the collection.737 ///738 /// * item_id: ID of NFT to burn.739 #[weight = T::CommonWeightInfo::burn_item()]740 #[transactional]741 pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {742 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);743744 let post_info = dispatch_tx::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;745 if value == 1 {746 <NftTransferBasket<T>>::remove(collection_id, item_id);747 <NftApproveBasket<T>>::remove(collection_id, item_id);748 }749 // Those maps should be cleared only if token disappears completly, need to move this part of logic to pallets?750 // <FungibleApproveBasket<T>>::remove(collection_id, sender.as_sub());751 // <RefungibleApproveBasket<T>>::remove((collection_id, item_id, sender.as_sub()));752 Ok(post_info)753 }754755 /// Destroys a concrete instance of NFT on behalf of the owner756 /// See also: [`approve`]757 ///758 /// # Permissions759 ///760 /// * Collection Owner.761 /// * Collection Admin.762 /// * Current NFT Owner.763 ///764 /// # Arguments765 ///766 /// * collection_id: ID of the collection.767 ///768 /// * item_id: ID of NFT to burn.769 ///770 /// * from: owner of item771 #[weight = T::CommonWeightInfo::burn_from()]772 #[transactional]773 pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {774 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);775 let budget = budget::Value::new(NESTING_BUDGET);776777 dispatch_tx::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value, &budget))778 }779780 /// Change ownership of the token.781 ///782 /// # Permissions783 ///784 /// * Collection Owner785 /// * Collection Admin786 /// * Current NFT owner787 ///788 /// # Arguments789 ///790 /// * recipient: Address of token recipient.791 ///792 /// * collection_id.793 ///794 /// * item_id: ID of the item795 /// * Non-Fungible Mode: Required.796 /// * Fungible Mode: Ignored.797 /// * Re-Fungible Mode: Required.798 ///799 /// * value: Amount to transfer.800 /// * Non-Fungible Mode: Ignored801 /// * Fungible Mode: Must specify transferred amount802 /// * Re-Fungible Mode: Must specify transferred portion (between 0 and 1)803 #[weight = T::CommonWeightInfo::transfer()]804 #[transactional]805 pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {806 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);807 let budget = budget::Value::new(NESTING_BUDGET);808809 dispatch_tx::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value, &budget))810 }811812 /// Set, change, or remove approved address to transfer the ownership of the NFT.813 ///814 /// # Permissions815 ///816 /// * Collection Owner817 /// * Collection Admin818 /// * Current NFT owner819 ///820 /// # Arguments821 ///822 /// * approved: Address that is approved to transfer this NFT or zero (if needed to remove approval).823 ///824 /// * collection_id.825 ///826 /// * item_id: ID of the item.827 #[weight = T::CommonWeightInfo::approve()]828 #[transactional]829 pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {830 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);831832 dispatch_tx::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))833 }834835 /// 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.836 ///837 /// # Permissions838 /// * Collection Owner839 /// * Collection Admin840 /// * Current NFT owner841 /// * Address approved by current NFT owner842 ///843 /// # Arguments844 ///845 /// * from: Address that owns token.846 ///847 /// * recipient: Address of token recipient.848 ///849 /// * collection_id.850 ///851 /// * item_id: ID of the item.852 ///853 /// * value: Amount to transfer.854 #[weight = T::CommonWeightInfo::transfer_from()]855 #[transactional]856 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {857 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);858 let budget = budget::Value::new(NESTING_BUDGET);859860 dispatch_tx::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))861 }862863 #[weight = <SelfWeightOf<T>>::set_collection_limits()]864 #[transactional]865 pub fn set_collection_limits(866 origin,867 collection_id: CollectionId,868 new_limit: CollectionLimits,869 ) -> DispatchResult {870 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);871 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;872 target_collection.check_is_internal()?;873 target_collection.check_is_owner_or_admin(&sender)?;874 let old_limit = &target_collection.limits;875876 target_collection.limits = <PalletCommon<T>>::clamp_limits(target_collection.mode.clone(), &old_limit, new_limit)?;877878 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(879 collection_id880 ));881882 target_collection.save()883 }884885 #[weight = <SelfWeightOf<T>>::set_collection_limits()]886 #[transactional]887 pub fn set_collection_permissions(888 origin,889 collection_id: CollectionId,890 new_limit: CollectionPermissions,891 ) -> DispatchResult {892 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);893 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;894 target_collection.check_is_internal()?;895 target_collection.check_is_owner_or_admin(&sender)?;896 let old_limit = &target_collection.permissions;897898 target_collection.permissions = <PalletCommon<T>>::clamp_permissions(target_collection.mode.clone(), &old_limit, new_limit)?;899900 <Pallet<T>>::deposit_event(Event::<T>::CollectionPermissionSet(901 collection_id902 ));903904 target_collection.save()905 }906907 #[weight = <SelfWeightOf<T>>::set_collection_limits()]908 #[transactional]909 pub fn repartition(910 origin,911 collection_id: CollectionId,912 token: TokenId,913 amount: u128,914 ) -> DispatchResult {915 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);916 let target_collection = <CollectionHandle<T>>::try_get(collection_id)?;917 target_collection.check_is_internal()?;918 let refungible_collection = match target_collection.mode {919 CollectionMode::ReFungible => RefungibleHandle::cast(target_collection),920 _ => fail!(<Error<T>>::RepartitionCalledOnNonRefungibleCollection),921 };922 <PalletRefungible<T>>::repartition(&sender, &refungible_collection, token, amount)?;923 Ok(())924 }925 }926}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;