From 368796bccdab61caa5c62011dc0bfcade06db7a3 Mon Sep 17 00:00:00 2001 From: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com> Date: Tue, 14 Feb 2023 10:19:50 +0200 Subject: [PATCH] [NFTs] Offchain mint (#13158) * Allow to mint with the pre-signed signatures * Another try * WIP: test encoder * Fix the deposits * Refactoring + tests + benchmarks * Add sp-core/runtime-benchmarks * Remove sp-core from dev deps * Enable full_crypto for benchmarks * Typo * Fix * Update frame/nfts/src/mock.rs Co-authored-by: Squirrel * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_nfts * Add docs * Add attributes into the pre-signed object & track the deposit owner for attributes * Update docs * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_nfts * Add the number of attributes provided to weights * Apply suggestions * Remove dead code * Remove Copy * Fix docs * Update frame/nfts/src/lib.rs Co-authored-by: Oliver Tale-Yazdi * Update frame/nfts/src/lib.rs Co-authored-by: Oliver Tale-Yazdi --------- Co-authored-by: Squirrel Co-authored-by: command-bot <> Co-authored-by: Oliver Tale-Yazdi --- Cargo.lock | 1 + bin/node/runtime/src/lib.rs | 4 + frame/nfts/Cargo.toml | 6 +- frame/nfts/src/benchmarking.rs | 68 +- frame/nfts/src/common_functions.rs | 2 +- frame/nfts/src/features/attributes.rs | 81 +- frame/nfts/src/features/create_delete_item.rs | 56 + frame/nfts/src/features/metadata.rs | 21 +- frame/nfts/src/features/settings.rs | 7 + frame/nfts/src/lib.rs | 66 +- frame/nfts/src/mock.rs | 23 +- frame/nfts/src/tests.rs | 1734 ++++++++++++----- frame/nfts/src/types.rs | 24 +- frame/nfts/src/weights.rs | 424 ++-- 14 files changed, 1756 insertions(+), 761 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ad3267984563a..0c2f8518473ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6017,6 +6017,7 @@ dependencies = [ "scale-info", "sp-core", "sp-io", + "sp-keystore", "sp-runtime", "sp-std", ] diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 8f8a7ceef3cfe..2c7969ebcd6b9 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1566,6 +1566,7 @@ impl pallet_uniques::Config for Runtime { parameter_types! { pub Features: PalletFeatures = PalletFeatures::all_enabled(); + pub const MaxAttributesPerCall: u32 = 10; } impl pallet_nfts::Config for Runtime { @@ -1586,7 +1587,10 @@ impl pallet_nfts::Config for Runtime { type ItemAttributesApprovalsLimit = ItemAttributesApprovalsLimit; type MaxTips = MaxTips; type MaxDeadlineDuration = MaxDeadlineDuration; + type MaxAttributesPerCall = MaxAttributesPerCall; type Features = Features; + type OffchainSignature = Signature; + type OffchainPublic = ::Signer; type WeightInfo = pallet_nfts::weights::SubstrateWeight; #[cfg(feature = "runtime-benchmarks")] type Helper = (); diff --git a/frame/nfts/Cargo.toml b/frame/nfts/Cargo.toml index 9e010cb557958..59aa4e091fe68 100644 --- a/frame/nfts/Cargo.toml +++ b/frame/nfts/Cargo.toml @@ -21,14 +21,13 @@ frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-core = { version = "7.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "7.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "7.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "5.0.0", default-features = false, path = "../../primitives/std" } [dev-dependencies] pallet-balances = { version = "4.0.0-dev", path = "../balances" } -sp-core = { version = "7.0.0", path = "../../primitives/core" } -sp-io = { version = "7.0.0", path = "../../primitives/io" } -sp-std = { version = "5.0.0", path = "../../primitives/std" } +sp-keystore = { version = "0.13.0", path = "../../primitives/keystore" } [features] default = ["std"] @@ -40,6 +39,7 @@ std = [ "log/std", "scale-info/std", "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", ] diff --git a/frame/nfts/src/benchmarking.rs b/frame/nfts/src/benchmarking.rs index a4007f6b2c133..9e724a2f63111 100644 --- a/frame/nfts/src/benchmarking.rs +++ b/frame/nfts/src/benchmarking.rs @@ -31,7 +31,11 @@ use frame_support::{ BoundedVec, }; use frame_system::RawOrigin as SystemOrigin; -use sp_runtime::traits::{Bounded, One}; +use sp_io::crypto::{sr25519_generate, sr25519_sign}; +use sp_runtime::{ + traits::{Bounded, IdentifyAccount, One}, + AccountId32, MultiSignature, MultiSigner, +}; use sp_std::prelude::*; use crate::Pallet as Nfts; @@ -148,7 +152,21 @@ fn default_item_config() -> ItemConfig { ItemConfig { settings: ItemSettings::all_enabled() } } +fn make_filled_vec(value: u16, length: usize) -> Vec { + let mut vec = vec![0u8; length]; + let mut s = Vec::from(value.to_be_bytes()); + vec.truncate(length - s.len()); + vec.append(&mut s); + vec +} + benchmarks_instance_pallet! { + where_clause { + where + T::OffchainSignature: From, + T::AccountId: From, + } + create { let collection = T::Helper::collection(0); let origin = T::CreateOrigin::try_successful_origin(&collection) @@ -439,11 +457,7 @@ benchmarks_instance_pallet! { T::Currency::make_free_balance_be(&target, DepositBalanceOf::::max_value()); let value: BoundedVec<_, _> = vec![0u8; T::ValueLimit::get() as usize].try_into().unwrap(); for i in 0..n { - let mut key = vec![0u8; T::KeyLimit::get() as usize]; - let mut s = Vec::from((i as u16).to_be_bytes()); - key.truncate(s.len()); - key.append(&mut s); - + let key = make_filled_vec(i as u16, T::KeyLimit::get() as usize); Nfts::::set_attribute( SystemOrigin::Signed(target.clone()).into(), T::Helper::collection(0), @@ -717,5 +731,47 @@ benchmarks_instance_pallet! { }.into()); } + mint_pre_signed { + let n in 0 .. T::MaxAttributesPerCall::get() as u32; + let caller_public = sr25519_generate(0.into(), None); + let caller = MultiSigner::Sr25519(caller_public).into_account().into(); + T::Currency::make_free_balance_be(&caller, DepositBalanceOf::::max_value()); + let caller_lookup = T::Lookup::unlookup(caller.clone()); + + let collection = T::Helper::collection(0); + let item = T::Helper::item(0); + assert_ok!(Nfts::::force_create( + SystemOrigin::Root.into(), + caller_lookup.clone(), + default_collection_config::() + )); + + let metadata = vec![0u8; T::StringLimit::get() as usize]; + let mut attributes = vec![]; + let attribute_value = vec![0u8; T::ValueLimit::get() as usize]; + for i in 0..n { + let attribute_key = make_filled_vec(i as u16, T::KeyLimit::get() as usize); + attributes.push((attribute_key, attribute_value.clone())); + } + let mint_data = PreSignedMint { + collection, + item, + attributes, + metadata: metadata.clone(), + only_account: None, + deadline: One::one(), + }; + let message = Encode::encode(&mint_data); + let signature = MultiSignature::Sr25519(sr25519_sign(0.into(), &caller_public, &message).unwrap()); + + let target: T::AccountId = account("target", 0, SEED); + T::Currency::make_free_balance_be(&target, DepositBalanceOf::::max_value()); + frame_system::Pallet::::set_block_number(One::one()); + }: _(SystemOrigin::Signed(target.clone()), mint_data, signature.into(), caller) + verify { + let metadata: BoundedVec<_, _> = metadata.try_into().unwrap(); + assert_last_event::(Event::ItemMetadataSet { collection, item, data: metadata }.into()); + } + impl_benchmark_test_suite!(Nfts, crate::mock::new_test_ext(), crate::mock::Test); } diff --git a/frame/nfts/src/common_functions.rs b/frame/nfts/src/common_functions.rs index 9c0faeb6b7c77..31f8a96614c6b 100644 --- a/frame/nfts/src/common_functions.rs +++ b/frame/nfts/src/common_functions.rs @@ -17,7 +17,7 @@ //! Various pieces of common functionality. -use super::*; +use crate::*; impl, I: 'static> Pallet { /// Get the owner of the item, if the item exists. diff --git a/frame/nfts/src/features/attributes.rs b/frame/nfts/src/features/attributes.rs index b25f2a60cd62d..51c75233c1d0c 100644 --- a/frame/nfts/src/features/attributes.rs +++ b/frame/nfts/src/features/attributes.rs @@ -26,6 +26,7 @@ impl, I: 'static> Pallet { namespace: AttributeNamespace, key: BoundedVec, value: BoundedVec, + depositor: T::AccountId, ) -> DispatchResult { ensure!( Self::is_pallet_feature_enabled(PalletFeature::Attributes), @@ -66,7 +67,8 @@ impl, I: 'static> Pallet { } let attribute = Attribute::::get((collection, maybe_item, &namespace, &key)); - if attribute.is_none() { + let attribute_exists = attribute.is_some(); + if !attribute_exists { collection_details.attributes.saturating_inc(); } @@ -74,6 +76,7 @@ impl, I: 'static> Pallet { attribute.map_or(AttributeDeposit { account: None, amount: Zero::zero() }, |m| m.1); let mut deposit = Zero::zero(); + // disabled DepositRequired setting only affects the CollectionOwner namespace if collection_config.is_setting_enabled(CollectionSetting::DepositRequired) || namespace != AttributeNamespace::CollectionOwner { @@ -82,33 +85,50 @@ impl, I: 'static> Pallet { .saturating_add(T::AttributeDepositBase::get()); } + let is_collection_owner_namespace = namespace == AttributeNamespace::CollectionOwner; + let is_depositor_collection_owner = + is_collection_owner_namespace && collection_details.owner == depositor; + + // NOTE: in the CollectionOwner namespace if the depositor is `None` that means the deposit + // was paid by the collection's owner. + let old_depositor = + if is_collection_owner_namespace && old_deposit.account.is_none() && attribute_exists { + Some(collection_details.owner.clone()) + } else { + old_deposit.account + }; + let depositor_has_changed = old_depositor != Some(depositor.clone()); + // NOTE: when we transfer an item, we don't move attributes in the ItemOwner namespace. // When the new owner updates the same attribute, we will update the depositor record // and return the deposit to the previous owner. - if old_deposit.account.is_some() && old_deposit.account != Some(origin.clone()) { - T::Currency::unreserve(&old_deposit.account.unwrap(), old_deposit.amount); - T::Currency::reserve(&origin, deposit)?; + if depositor_has_changed { + if let Some(old_depositor) = old_depositor { + T::Currency::unreserve(&old_depositor, old_deposit.amount); + } + T::Currency::reserve(&depositor, deposit)?; } else if deposit > old_deposit.amount { - T::Currency::reserve(&origin, deposit - old_deposit.amount)?; + T::Currency::reserve(&depositor, deposit - old_deposit.amount)?; } else if deposit < old_deposit.amount { - T::Currency::unreserve(&origin, old_deposit.amount - deposit); + T::Currency::unreserve(&depositor, old_deposit.amount - deposit); } - // NOTE: we don't track the depositor in the CollectionOwner namespace as it's always a - // collection's owner. This simplifies the collection's transfer to another owner. - let deposit_owner = match namespace { - AttributeNamespace::CollectionOwner => { - collection_details.owner_deposit.saturating_accrue(deposit); + if is_depositor_collection_owner { + if !depositor_has_changed { collection_details.owner_deposit.saturating_reduce(old_deposit.amount); - None - }, - _ => Some(origin), - }; + } + collection_details.owner_deposit.saturating_accrue(deposit); + } + let new_deposit_owner = match is_depositor_collection_owner { + true => None, + false => Some(depositor), + }; Attribute::::insert( (&collection, maybe_item, &namespace, &key), - (&value, AttributeDeposit { account: deposit_owner, amount: deposit }), + (&value, AttributeDeposit { account: new_deposit_owner, amount: deposit }), ); + Collection::::insert(collection, &collection_details); Self::deposit_event(Event::AttributeSet { collection, maybe_item, key, value, namespace }); Ok(()) @@ -188,10 +208,21 @@ impl, I: 'static> Pallet { // NOTE: if the item was previously burned, the ItemConfigOf record // might not exist. In that case, we allow to clear the attribute. let maybe_is_locked = Self::get_item_config(&collection, &item) - .map_or(false, |c| { - c.has_disabled_setting(ItemSetting::UnlockedAttributes) + .map_or(None, |c| { + Some(c.has_disabled_setting(ItemSetting::UnlockedAttributes)) }); - ensure!(!maybe_is_locked, Error::::LockedItemAttributes); + match maybe_is_locked { + Some(is_locked) => { + // when item exists, then only the collection's owner can clear that + // attribute + ensure!( + check_owner == &collection_details.owner, + Error::::NoPermission + ); + ensure!(!is_locked, Error::::LockedItemAttributes); + }, + None => (), + } }, }, _ => (), @@ -199,16 +230,16 @@ impl, I: 'static> Pallet { } collection_details.attributes.saturating_dec(); - match namespace { - AttributeNamespace::CollectionOwner => { + + match deposit.account { + Some(deposit_account) => { + T::Currency::unreserve(&deposit_account, deposit.amount); + }, + None if namespace == AttributeNamespace::CollectionOwner => { collection_details.owner_deposit.saturating_reduce(deposit.amount); T::Currency::unreserve(&collection_details.owner, deposit.amount); }, _ => (), - }; - - if let Some(deposit_account) = deposit.account { - T::Currency::unreserve(&deposit_account, deposit.amount); } Collection::::insert(collection, &collection_details); diff --git a/frame/nfts/src/features/create_delete_item.rs b/frame/nfts/src/features/create_delete_item.rs index f724fe5c63b43..63d7a540c3ae6 100644 --- a/frame/nfts/src/features/create_delete_item.rs +++ b/frame/nfts/src/features/create_delete_item.rs @@ -85,6 +85,62 @@ impl, I: 'static> Pallet { Ok(()) } + pub(crate) fn do_mint_pre_signed( + mint_to: T::AccountId, + mint_data: PreSignedMintOf, + signer: T::AccountId, + ) -> DispatchResult { + let PreSignedMint { collection, item, attributes, metadata, deadline, only_account } = + mint_data; + let metadata = Self::construct_metadata(metadata)?; + + ensure!( + attributes.len() <= T::MaxAttributesPerCall::get() as usize, + Error::::MaxAttributesLimitReached + ); + if let Some(account) = only_account { + ensure!(account == mint_to, Error::::WrongOrigin); + } + + let now = frame_system::Pallet::::block_number(); + ensure!(deadline >= now, Error::::DeadlineExpired); + + let collection_details = + Collection::::get(&collection).ok_or(Error::::UnknownCollection)?; + ensure!(collection_details.owner == signer, Error::::NoPermission); + + let item_config = ItemConfig { settings: Self::get_default_item_settings(&collection)? }; + Self::do_mint( + collection, + item, + Some(mint_to.clone()), + mint_to.clone(), + item_config, + |_, _| Ok(()), + )?; + for (key, value) in attributes { + Self::do_set_attribute( + collection_details.owner.clone(), + collection, + Some(item), + AttributeNamespace::CollectionOwner, + Self::construct_attribute_key(key)?, + Self::construct_attribute_value(value)?, + mint_to.clone(), + )?; + } + if !metadata.len().is_zero() { + Self::do_set_item_metadata( + Some(collection_details.owner.clone()), + collection, + item, + metadata, + Some(mint_to.clone()), + )?; + } + Ok(()) + } + pub fn do_burn( collection: T::CollectionId, item: T::ItemId, diff --git a/frame/nfts/src/features/metadata.rs b/frame/nfts/src/features/metadata.rs index 272b2247426d6..c4d355f1922fc 100644 --- a/frame/nfts/src/features/metadata.rs +++ b/frame/nfts/src/features/metadata.rs @@ -60,14 +60,16 @@ impl, I: 'static> Pallet { .saturating_add(T::MetadataDepositBase::get()); } - // the previous deposit was taken from the item's owner - if old_deposit.account.is_some() && maybe_depositor.is_none() { - T::Currency::unreserve(&old_deposit.account.unwrap(), old_deposit.amount); - T::Currency::reserve(&collection_details.owner, deposit)?; + let depositor = maybe_depositor.clone().unwrap_or(collection_details.owner.clone()); + let old_depositor = old_deposit.account.unwrap_or(collection_details.owner.clone()); + + if depositor != old_depositor { + T::Currency::unreserve(&old_depositor, old_deposit.amount); + T::Currency::reserve(&depositor, deposit)?; } else if deposit > old_deposit.amount { - T::Currency::reserve(&collection_details.owner, deposit - old_deposit.amount)?; + T::Currency::reserve(&depositor, deposit - old_deposit.amount)?; } else if deposit < old_deposit.amount { - T::Currency::unreserve(&collection_details.owner, old_deposit.amount - deposit); + T::Currency::unreserve(&depositor, old_deposit.amount - deposit); } if maybe_depositor.is_none() { @@ -191,4 +193,11 @@ impl, I: 'static> Pallet { Ok(()) }) } + + /// A helper method to construct metadata. + pub fn construct_metadata( + metadata: Vec, + ) -> Result, DispatchError> { + Ok(BoundedVec::try_from(metadata).map_err(|_| Error::::IncorrectMetadata)?) + } } diff --git a/frame/nfts/src/features/settings.rs b/frame/nfts/src/features/settings.rs index 5f408ed183c35..7c29711094112 100644 --- a/frame/nfts/src/features/settings.rs +++ b/frame/nfts/src/features/settings.rs @@ -96,6 +96,13 @@ impl, I: 'static> Pallet { Ok(config) } + pub(crate) fn get_default_item_settings( + collection_id: &T::CollectionId, + ) -> Result { + let collection_config = Self::get_collection_config(collection_id)?; + Ok(collection_config.mint_settings.default_item_settings) + } + pub(crate) fn is_pallet_feature_enabled(feature: PalletFeature) -> bool { let features = T::Features::get(); return features.is_enabled(feature) diff --git a/frame/nfts/src/lib.rs b/frame/nfts/src/lib.rs index 8f24c8dcd6e98..cec5ea7ffc09f 100644 --- a/frame/nfts/src/lib.rs +++ b/frame/nfts/src/lib.rs @@ -67,6 +67,7 @@ pub mod pallet { use super::*; use frame_support::{pallet_prelude::*, traits::ExistenceRequirement}; use frame_system::pallet_prelude::*; + use sp_runtime::traits::{IdentifyAccount, Verify}; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] @@ -167,10 +168,24 @@ pub mod pallet { #[pallet::constant] type MaxDeadlineDuration: Get<::BlockNumber>; + /// The max number of attributes a user could set per call. + #[pallet::constant] + type MaxAttributesPerCall: Get; + /// Disables some of pallet's features. #[pallet::constant] type Features: Get; + /// Off-Chain signature type. + /// + /// Can verify whether an `Self::OffchainPublic` created a signature. + type OffchainSignature: Verify + Parameter; + + /// Off-Chain public key. + /// + /// Must identify as an on-chain `Self::AccountId`. + type OffchainPublic: IdentifyAccount; + #[cfg(feature = "runtime-benchmarks")] /// A set of helper functions for benchmarking. type Helper: BenchmarkHelper; @@ -591,6 +606,14 @@ pub mod pallet { AlreadyClaimed, /// The provided data is incorrect. IncorrectData, + /// The extrinsic was sent by the wrong origin. + WrongOrigin, + /// The provided signature is incorrect. + WrongSignature, + /// The provided metadata might be too long. + IncorrectMetadata, + /// Can't set more attributes per one call. + MaxAttributesLimitReached, } #[pallet::call] @@ -742,10 +765,8 @@ pub mod pallet { ) -> DispatchResult { let caller = ensure_signed(origin)?; let mint_to = T::Lookup::lookup(mint_to)?; - - let collection_config = Self::get_collection_config(&collection)?; - let item_settings = collection_config.mint_settings.default_item_settings; - let item_config = ItemConfig { settings: item_settings }; + let item_config = + ItemConfig { settings: Self::get_default_item_settings(&collection)? }; Self::do_mint( collection, @@ -1325,7 +1346,15 @@ pub mod pallet { value: BoundedVec, ) -> DispatchResult { let origin = ensure_signed(origin)?; - Self::do_set_attribute(origin, collection, maybe_item, namespace, key, value) + Self::do_set_attribute( + origin.clone(), + collection, + maybe_item, + namespace, + key, + value, + origin, + ) } /// Force-set an attribute for a collection or item. @@ -1768,6 +1797,33 @@ pub mod pallet { witness_price, ) } + + /// Mint an item by providing the pre-signed approval. + /// + /// Origin must be Signed. + /// + /// - `mint_data`: The pre-signed approval that consists of the information about the item, + /// its metadata, attributes, who can mint it (`None` for anyone) and until what block + /// number. + /// - `signature`: The signature of the `data` object. + /// - `signer`: The `data` object's signer. Should be an owner of the collection. + /// + /// Emits `Issued` on success. + /// Emits `AttributeSet` if the attributes were provided. + /// Emits `ItemMetadataSet` if the metadata was not empty. + #[pallet::call_index(37)] + #[pallet::weight(T::WeightInfo::mint_pre_signed(mint_data.attributes.len() as u32))] + pub fn mint_pre_signed( + origin: OriginFor, + mint_data: PreSignedMintOf, + signature: T::OffchainSignature, + signer: T::AccountId, + ) -> DispatchResult { + let origin = ensure_signed(origin)?; + let msg = Encode::encode(&mint_data); + ensure!(signature.verify(&*msg, &signer), Error::::WrongSignature); + Self::do_mint_pre_signed(origin, mint_data, signer) + } } } diff --git a/frame/nfts/src/mock.rs b/frame/nfts/src/mock.rs index f814b209d5f78..d0ef3cf0b12c6 100644 --- a/frame/nfts/src/mock.rs +++ b/frame/nfts/src/mock.rs @@ -25,10 +25,13 @@ use frame_support::{ traits::{AsEnsureOriginWithArg, ConstU32, ConstU64}, }; use sp_core::H256; +use sp_keystore::{testing::KeyStore, KeystoreExt}; use sp_runtime::{ testing::Header, - traits::{BlakeTwo256, IdentityLookup}, + traits::{BlakeTwo256, IdentifyAccount, IdentityLookup, Verify}, + MultiSignature, }; +use std::sync::Arc; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; @@ -45,6 +48,10 @@ construct_runtime!( } ); +pub type Signature = MultiSignature; +pub type AccountPublic = ::Signer; +pub type AccountId = ::AccountId; + impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); @@ -55,7 +62,7 @@ impl frame_system::Config for Test { type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; - type AccountId = u64; + type AccountId = AccountId; type Lookup = IdentityLookup; type Header = Header; type RuntimeEvent = RuntimeEvent; @@ -93,8 +100,8 @@ impl Config for Test { type CollectionId = u32; type ItemId = u32; type Currency = Balances; - type CreateOrigin = AsEnsureOriginWithArg>; - type ForceOrigin = frame_system::EnsureRoot; + type CreateOrigin = AsEnsureOriginWithArg>; + type ForceOrigin = frame_system::EnsureRoot; type Locker = (); type CollectionDeposit = ConstU64<2>; type ItemDeposit = ConstU64<1>; @@ -108,7 +115,13 @@ impl Config for Test { type ItemAttributesApprovalsLimit = ConstU32<2>; type MaxTips = ConstU32<10>; type MaxDeadlineDuration = ConstU64<10000>; + type MaxAttributesPerCall = ConstU32<2>; type Features = Features; + /// Off-chain = signature On-chain - therefore no conversion needed. + /// It needs to be From for benchmarking. + type OffchainSignature = Signature; + /// Using `AccountPublic` here makes it trivial to convert to `AccountId` via `into_account()`. + type OffchainPublic = AccountPublic; type WeightInfo = (); #[cfg(feature = "runtime-benchmarks")] type Helper = (); @@ -117,7 +130,9 @@ impl Config for Test { pub(crate) fn new_test_ext() -> sp_io::TestExternalities { let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let keystore = KeyStore::new(); let mut ext = sp_io::TestExternalities::new(t); + ext.register_extension(KeystoreExt(Arc::new(keystore))); ext.execute_with(|| System::set_block_number(1)); ext } diff --git a/frame/nfts/src/tests.rs b/frame/nfts/src/tests.rs index ebbba33b04fa2..fce9073af2d02 100644 --- a/frame/nfts/src/tests.rs +++ b/frame/nfts/src/tests.rs @@ -28,10 +28,17 @@ use frame_support::{ }, }; use pallet_balances::Error as BalancesError; -use sp_core::bounded::BoundedVec; +use sp_core::{bounded::BoundedVec, Pair}; +use sp_runtime::{traits::IdentifyAccount, MultiSignature, MultiSigner}; use sp_std::prelude::*; -fn items() -> Vec<(u64, u32, u32)> { +type AccountIdOf = ::AccountId; + +fn account(id: u8) -> AccountIdOf { + [id; 32].into() +} + +fn items() -> Vec<(AccountIdOf, u32, u32)> { let mut r: Vec<_> = Account::::iter().map(|x| x.0).collect(); r.sort(); let mut s: Vec<_> = Item::::iter().map(|x| (x.2.owner, x.0, x.1)).collect(); @@ -56,7 +63,7 @@ fn items() -> Vec<(u64, u32, u32)> { r } -fn collections() -> Vec<(u64, u32)> { +fn collections() -> Vec<(AccountIdOf, u32)> { let mut r: Vec<_> = CollectionAccount::::iter().map(|x| (x.0, x.1)).collect(); r.sort(); let mut s: Vec<_> = Collection::::iter().map(|x| (x.1.owner, x.0)).collect(); @@ -71,22 +78,26 @@ macro_rules! bvec { } } -fn attributes(collection: u32) -> Vec<(Option, AttributeNamespace, Vec, Vec)> { +fn attributes( + collection: u32, +) -> Vec<(Option, AttributeNamespace>, Vec, Vec)> { let mut s: Vec<_> = Attribute::::iter_prefix((collection,)) .map(|(k, v)| (k.0, k.1, k.2.into(), v.0.into())) .collect(); - s.sort_by_key(|k: &(Option, AttributeNamespace, Vec, Vec)| k.0); - s.sort_by_key(|k: &(Option, AttributeNamespace, Vec, Vec)| k.2.clone()); + s.sort_by_key(|k: &(Option, AttributeNamespace>, Vec, Vec)| k.0); + s.sort_by_key(|k: &(Option, AttributeNamespace>, Vec, Vec)| { + k.2.clone() + }); s } -fn approvals(collection_id: u32, item_id: u32) -> Vec<(u64, Option)> { +fn approvals(collection_id: u32, item_id: u32) -> Vec<(AccountIdOf, Option)> { let item = Item::::get(collection_id, item_id).unwrap(); let s: Vec<_> = item.approvals.into_iter().collect(); s } -fn item_attributes_approvals(collection_id: u32, item_id: u32) -> Vec { +fn item_attributes_approvals(collection_id: u32, item_id: u32) -> Vec> { let approvals = ItemAttributesApprovalsOf::::get(collection_id, item_id); let s: Vec<_> = approvals.into_iter().collect(); s @@ -144,60 +155,83 @@ fn basic_setup_works() { #[test] fn basic_minting_should_work() { new_test_ext().execute_with(|| { - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 1, default_collection_config())); - assert_eq!(collections(), vec![(1, 0)]); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(1), 0, 42, 1, None)); - assert_eq!(items(), vec![(1, 0, 42)]); - - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 2, default_collection_config())); - assert_eq!(collections(), vec![(1, 0), (2, 1)]); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(2), 1, 69, 1, None)); - // assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(2), 1, 69, 1, default_item_config())); - assert_eq!(items(), vec![(1, 0, 42), (1, 1, 69)]); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_eq!(collections(), vec![(account(1), 0)]); + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); + assert_eq!(items(), vec![(account(1), 0, 42)]); + + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(2), + default_collection_config() + )); + assert_eq!(collections(), vec![(account(1), 0), (account(2), 1)]); + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(2)), 1, 69, account(1), None)); + assert_eq!(items(), vec![(account(1), 0, 42), (account(1), 1, 69)]); }); } #[test] fn lifecycle_should_work() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 100); - Balances::make_free_balance_be(&2, 100); + Balances::make_free_balance_be(&account(1), 100); + Balances::make_free_balance_be(&account(2), 100); assert_ok!(Nfts::create( - RuntimeOrigin::signed(1), - 1, + RuntimeOrigin::signed(account(1)), + account(1), collection_config_with_all_settings_enabled() )); - assert_eq!(Balances::reserved_balance(&1), 2); - assert_eq!(collections(), vec![(1, 0)]); - assert_ok!(Nfts::set_collection_metadata(RuntimeOrigin::signed(1), 0, bvec![0, 0])); - assert_eq!(Balances::reserved_balance(&1), 5); + assert_eq!(Balances::reserved_balance(&account(1)), 2); + assert_eq!(collections(), vec![(account(1), 0)]); + assert_ok!(Nfts::set_collection_metadata( + RuntimeOrigin::signed(account(1)), + 0, + bvec![0, 0] + )); + assert_eq!(Balances::reserved_balance(&account(1)), 5); assert!(CollectionMetadataOf::::contains_key(0)); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(1), 0, 42, 10, default_item_config())); - assert_eq!(Balances::reserved_balance(&1), 6); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(1), 0, 69, 20, default_item_config())); - assert_eq!(Balances::reserved_balance(&1), 7); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(1), 0, 70, 1, None)); - assert_eq!(items(), vec![(1, 0, 70), (10, 0, 42), (20, 0, 69)]); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 42, + account(10), + default_item_config() + )); + assert_eq!(Balances::reserved_balance(&account(1)), 6); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 69, + account(20), + default_item_config() + )); + assert_eq!(Balances::reserved_balance(&account(1)), 7); + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 70, account(1), None)); + assert_eq!(items(), vec![(account(1), 0, 70), (account(10), 0, 42), (account(20), 0, 69)]); assert_eq!(Collection::::get(0).unwrap().items, 3); assert_eq!(Collection::::get(0).unwrap().item_metadatas, 0); - assert_eq!(Balances::reserved_balance(&2), 0); - assert_ok!(Nfts::transfer(RuntimeOrigin::signed(1), 0, 70, 2)); - assert_eq!(Balances::reserved_balance(&2), 1); + assert_eq!(Balances::reserved_balance(&account(2)), 0); + assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(1)), 0, 70, account(2))); + assert_eq!(Balances::reserved_balance(&account(2)), 1); - assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(1), 0, 42, bvec![42, 42])); - assert_eq!(Balances::reserved_balance(&1), 10); + assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![42, 42])); + assert_eq!(Balances::reserved_balance(&account(1)), 10); assert!(ItemMetadataOf::::contains_key(0, 42)); - assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(1), 0, 69, bvec![69, 69])); - assert_eq!(Balances::reserved_balance(&1), 13); + assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 69, bvec![69, 69])); + assert_eq!(Balances::reserved_balance(&account(1)), 13); assert!(ItemMetadataOf::::contains_key(0, 69)); let w = Nfts::get_destroy_witness(&0).unwrap(); assert_eq!(w.items, 3); assert_eq!(w.item_metadatas, 2); - assert_ok!(Nfts::destroy(RuntimeOrigin::signed(1), 0, w)); - assert_eq!(Balances::reserved_balance(&1), 0); + assert_ok!(Nfts::destroy(RuntimeOrigin::signed(account(1)), 0, w)); + assert_eq!(Balances::reserved_balance(&account(1)), 0); assert!(!Collection::::contains_key(0)); assert!(!CollectionConfigOf::::contains_key(0)); @@ -214,31 +248,38 @@ fn lifecycle_should_work() { #[test] fn destroy_with_bad_witness_should_not_work() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 100); + Balances::make_free_balance_be(&account(1), 100); assert_ok!(Nfts::create( - RuntimeOrigin::signed(1), - 1, + RuntimeOrigin::signed(account(1)), + account(1), collection_config_with_all_settings_enabled() )); let w = Collection::::get(0).unwrap().destroy_witness(); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(1), 0, 42, 1, None)); - assert_noop!(Nfts::destroy(RuntimeOrigin::signed(1), 0, w), Error::::BadWitness); + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); + assert_noop!( + Nfts::destroy(RuntimeOrigin::signed(account(1)), 0, w), + Error::::BadWitness + ); }); } #[test] fn mint_should_work() { new_test_ext().execute_with(|| { - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 1, default_collection_config())); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(1), 0, 42, 1, None)); - assert_eq!(Nfts::owner(0, 42).unwrap(), 1); - assert_eq!(collections(), vec![(1, 0)]); - assert_eq!(items(), vec![(1, 0, 42)]); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); + assert_eq!(Nfts::owner(0, 42).unwrap(), account(1)); + assert_eq!(collections(), vec![(account(1), 0)]); + assert_eq!(items(), vec![(account(1), 0, 42)]); // validate minting start and end settings assert_ok!(Nfts::update_mint_settings( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, MintSettings { start_block: Some(2), @@ -250,55 +291,71 @@ fn mint_should_work() { System::set_block_number(1); assert_noop!( - Nfts::mint(RuntimeOrigin::signed(2), 0, 43, 1, None), + Nfts::mint(RuntimeOrigin::signed(account(2)), 0, 43, account(1), None), Error::::MintNotStarted ); System::set_block_number(4); assert_noop!( - Nfts::mint(RuntimeOrigin::signed(2), 0, 43, 1, None), + Nfts::mint(RuntimeOrigin::signed(account(2)), 0, 43, account(1), None), Error::::MintEnded ); // validate price assert_ok!(Nfts::update_mint_settings( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, MintSettings { mint_type: MintType::Public, price: Some(1), ..Default::default() } )); - Balances::make_free_balance_be(&2, 100); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(2), 0, 43, 2, None)); - assert_eq!(Balances::total_balance(&2), 99); + Balances::make_free_balance_be(&account(2), 100); + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(2)), 0, 43, account(2), None)); + assert_eq!(Balances::total_balance(&account(2)), 99); // validate types - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 1, default_collection_config())); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); assert_ok!(Nfts::update_mint_settings( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 1, MintSettings { mint_type: MintType::HolderOf(0), ..Default::default() } )); assert_noop!( - Nfts::mint(RuntimeOrigin::signed(3), 1, 42, 3, None), + Nfts::mint(RuntimeOrigin::signed(account(3)), 1, 42, account(3), None), Error::::BadWitness ); assert_noop!( - Nfts::mint(RuntimeOrigin::signed(2), 1, 42, 2, None), + Nfts::mint(RuntimeOrigin::signed(account(2)), 1, 42, account(2), None), Error::::BadWitness ); assert_noop!( - Nfts::mint(RuntimeOrigin::signed(2), 1, 42, 2, Some(MintWitness { owner_of_item: 42 })), + Nfts::mint( + RuntimeOrigin::signed(account(2)), + 1, + 42, + account(2), + Some(MintWitness { owner_of_item: 42 }) + ), Error::::BadWitness ); assert_ok!(Nfts::mint( - RuntimeOrigin::signed(2), + RuntimeOrigin::signed(account(2)), 1, 42, - 2, + account(2), Some(MintWitness { owner_of_item: 43 }) )); // can't mint twice assert_noop!( - Nfts::mint(RuntimeOrigin::signed(2), 1, 46, 2, Some(MintWitness { owner_of_item: 43 })), + Nfts::mint( + RuntimeOrigin::signed(account(2)), + 1, + 46, + account(2), + Some(MintWitness { owner_of_item: 43 }) + ), Error::::AlreadyClaimed ); }); @@ -307,33 +364,55 @@ fn mint_should_work() { #[test] fn transfer_should_work() { new_test_ext().execute_with(|| { - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 1, default_collection_config())); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(1), 0, 42, 2, default_item_config())); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 42, + account(2), + default_item_config() + )); - assert_ok!(Nfts::transfer(RuntimeOrigin::signed(2), 0, 42, 3)); - assert_eq!(items(), vec![(3, 0, 42)]); + assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(3))); + assert_eq!(items(), vec![(account(3), 0, 42)]); assert_noop!( - Nfts::transfer(RuntimeOrigin::signed(2), 0, 42, 4), + Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(4)), Error::::NoPermission ); - assert_ok!(Nfts::approve_transfer(RuntimeOrigin::signed(3), 0, 42, 2, None)); - assert_ok!(Nfts::transfer(RuntimeOrigin::signed(2), 0, 42, 4)); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(3)), + 0, + 42, + account(2), + None + )); + assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(4))); // validate we can't transfer non-transferable items let collection_id = 1; assert_ok!(Nfts::force_create( RuntimeOrigin::root(), - 1, + account(1), collection_config_from_disabled_settings( CollectionSetting::TransferableItems | CollectionSetting::DepositRequired ) )); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(1), 1, 1, 42, default_item_config())); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 1, + 1, + account(42), + default_item_config() + )); assert_noop!( - Nfts::transfer(RuntimeOrigin::signed(1), collection_id, 42, 3,), + Nfts::transfer(RuntimeOrigin::signed(account(1)), collection_id, 42, account(3)), Error::::ItemsNonTransferable ); }); @@ -342,19 +421,26 @@ fn transfer_should_work() { #[test] fn locking_transfer_should_work() { new_test_ext().execute_with(|| { - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 1, default_collection_config())); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(1), 0, 42, 1, None)); - assert_ok!(Nfts::lock_item_transfer(RuntimeOrigin::signed(1), 0, 42)); - assert_noop!(Nfts::transfer(RuntimeOrigin::signed(1), 0, 42, 2), Error::::ItemLocked); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); + assert_ok!(Nfts::lock_item_transfer(RuntimeOrigin::signed(account(1)), 0, 42)); + assert_noop!( + Nfts::transfer(RuntimeOrigin::signed(account(1)), 0, 42, account(2)), + Error::::ItemLocked + ); - assert_ok!(Nfts::unlock_item_transfer(RuntimeOrigin::signed(1), 0, 42)); + assert_ok!(Nfts::unlock_item_transfer(RuntimeOrigin::signed(account(1)), 0, 42)); assert_ok!(Nfts::lock_collection( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, CollectionSettings::from_disabled(CollectionSetting::TransferableItems.into()) )); assert_noop!( - Nfts::transfer(RuntimeOrigin::signed(1), 0, 42, 2), + Nfts::transfer(RuntimeOrigin::signed(account(1)), 0, 42, account(2)), Error::::ItemsNonTransferable ); @@ -363,99 +449,116 @@ fn locking_transfer_should_work() { 0, collection_config_with_all_settings_enabled(), )); - assert_ok!(Nfts::transfer(RuntimeOrigin::signed(1), 0, 42, 2)); + assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(1)), 0, 42, account(2))); }); } #[test] fn origin_guards_should_work() { new_test_ext().execute_with(|| { - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 1, default_collection_config())); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(1), 0, 42, 1, None)); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); - Balances::make_free_balance_be(&2, 100); - assert_ok!(Nfts::set_accept_ownership(RuntimeOrigin::signed(2), Some(0))); + Balances::make_free_balance_be(&account(2), 100); + assert_ok!(Nfts::set_accept_ownership(RuntimeOrigin::signed(account(2)), Some(0))); assert_noop!( - Nfts::transfer_ownership(RuntimeOrigin::signed(2), 0, 2), + Nfts::transfer_ownership(RuntimeOrigin::signed(account(2)), 0, account(2)), Error::::NoPermission ); assert_noop!( - Nfts::set_team(RuntimeOrigin::signed(2), 0, 2, 2, 2), + Nfts::set_team( + RuntimeOrigin::signed(account(2)), + 0, + account(2), + account(2), + account(2), + ), Error::::NoPermission ); assert_noop!( - Nfts::lock_item_transfer(RuntimeOrigin::signed(2), 0, 42), + Nfts::lock_item_transfer(RuntimeOrigin::signed(account(2)), 0, 42), Error::::NoPermission ); assert_noop!( - Nfts::unlock_item_transfer(RuntimeOrigin::signed(2), 0, 42), + Nfts::unlock_item_transfer(RuntimeOrigin::signed(account(2)), 0, 42), Error::::NoPermission ); assert_noop!( - Nfts::mint(RuntimeOrigin::signed(2), 0, 69, 2, None), + Nfts::mint(RuntimeOrigin::signed(account(2)), 0, 69, account(2), None), Error::::NoPermission ); assert_noop!( - Nfts::burn(RuntimeOrigin::signed(2), 0, 42, None), + Nfts::burn(RuntimeOrigin::signed(account(2)), 0, 42, None), Error::::NoPermission ); let w = Nfts::get_destroy_witness(&0).unwrap(); - assert_noop!(Nfts::destroy(RuntimeOrigin::signed(2), 0, w), Error::::NoPermission); + assert_noop!( + Nfts::destroy(RuntimeOrigin::signed(account(2)), 0, w), + Error::::NoPermission + ); }); } #[test] fn transfer_owner_should_work() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 100); - Balances::make_free_balance_be(&2, 100); - Balances::make_free_balance_be(&3, 100); + Balances::make_free_balance_be(&account(1), 100); + Balances::make_free_balance_be(&account(2), 100); + Balances::make_free_balance_be(&account(3), 100); assert_ok!(Nfts::create( - RuntimeOrigin::signed(1), - 1, + RuntimeOrigin::signed(account(1)), + account(1), collection_config_with_all_settings_enabled() )); - assert_eq!(collections(), vec![(1, 0)]); + assert_eq!(collections(), vec![(account(1), 0)]); assert_noop!( - Nfts::transfer_ownership(RuntimeOrigin::signed(1), 0, 2), + Nfts::transfer_ownership(RuntimeOrigin::signed(account(1)), 0, account(2)), Error::::Unaccepted ); - assert_ok!(Nfts::set_accept_ownership(RuntimeOrigin::signed(2), Some(0))); - assert_ok!(Nfts::transfer_ownership(RuntimeOrigin::signed(1), 0, 2)); + assert_ok!(Nfts::set_accept_ownership(RuntimeOrigin::signed(account(2)), Some(0))); + assert_ok!(Nfts::transfer_ownership(RuntimeOrigin::signed(account(1)), 0, account(2))); - assert_eq!(collections(), vec![(2, 0)]); - assert_eq!(Balances::total_balance(&1), 98); - assert_eq!(Balances::total_balance(&2), 102); - assert_eq!(Balances::reserved_balance(&1), 0); - assert_eq!(Balances::reserved_balance(&2), 2); + assert_eq!(collections(), vec![(account(2), 0)]); + assert_eq!(Balances::total_balance(&account(1)), 98); + assert_eq!(Balances::total_balance(&account(2)), 102); + assert_eq!(Balances::reserved_balance(&account(1)), 0); + assert_eq!(Balances::reserved_balance(&account(2)), 2); - assert_ok!(Nfts::set_accept_ownership(RuntimeOrigin::signed(1), Some(0))); + assert_ok!(Nfts::set_accept_ownership(RuntimeOrigin::signed(account(1)), Some(0))); assert_noop!( - Nfts::transfer_ownership(RuntimeOrigin::signed(1), 0, 1), + Nfts::transfer_ownership(RuntimeOrigin::signed(account(1)), 0, account(1)), Error::::NoPermission ); // Mint and set metadata now and make sure that deposit gets transferred back. - assert_ok!(Nfts::set_collection_metadata(RuntimeOrigin::signed(2), 0, bvec![0u8; 20])); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(1), 0, 42, 1, None)); - assert_eq!(Balances::reserved_balance(&1), 1); - assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(2), 0, 42, bvec![0u8; 20])); - assert_ok!(Nfts::set_accept_ownership(RuntimeOrigin::signed(3), Some(0))); - assert_ok!(Nfts::transfer_ownership(RuntimeOrigin::signed(2), 0, 3)); - assert_eq!(collections(), vec![(3, 0)]); - assert_eq!(Balances::total_balance(&2), 58); - assert_eq!(Balances::total_balance(&3), 144); - assert_eq!(Balances::reserved_balance(&2), 0); - assert_eq!(Balances::reserved_balance(&3), 44); - - assert_ok!(Nfts::transfer(RuntimeOrigin::signed(1), 0, 42, 2)); - assert_eq!(Balances::reserved_balance(&1), 0); - assert_eq!(Balances::reserved_balance(&2), 1); + assert_ok!(Nfts::set_collection_metadata( + RuntimeOrigin::signed(account(2)), + 0, + bvec![0u8; 20], + )); + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); + assert_eq!(Balances::reserved_balance(&account(1)), 1); + assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(2)), 0, 42, bvec![0u8; 20])); + assert_ok!(Nfts::set_accept_ownership(RuntimeOrigin::signed(account(3)), Some(0))); + assert_ok!(Nfts::transfer_ownership(RuntimeOrigin::signed(account(2)), 0, account(3))); + assert_eq!(collections(), vec![(account(3), 0)]); + assert_eq!(Balances::total_balance(&account(2)), 58); + assert_eq!(Balances::total_balance(&account(3)), 144); + assert_eq!(Balances::reserved_balance(&account(2)), 0); + assert_eq!(Balances::reserved_balance(&account(3)), 44); + + assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(1)), 0, 42, account(2))); + assert_eq!(Balances::reserved_balance(&account(1)), 0); + assert_eq!(Balances::reserved_balance(&account(2)), 1); // 2's acceptance from before is reset when it became an owner, so it cannot be transferred // without a fresh acceptance. assert_noop!( - Nfts::transfer_ownership(RuntimeOrigin::signed(3), 0, 2), + Nfts::transfer_ownership(RuntimeOrigin::signed(account(3)), 0, account(2)), Error::::Unaccepted ); }); @@ -464,14 +567,24 @@ fn transfer_owner_should_work() { #[test] fn set_team_should_work() { new_test_ext().execute_with(|| { - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 1, default_collection_config())); - assert_ok!(Nfts::set_team(RuntimeOrigin::signed(1), 0, 2, 3, 4)); - - assert_ok!(Nfts::mint(RuntimeOrigin::signed(2), 0, 42, 2, None)); - assert_ok!(Nfts::lock_item_transfer(RuntimeOrigin::signed(4), 0, 42)); - assert_ok!(Nfts::unlock_item_transfer(RuntimeOrigin::signed(4), 0, 42)); - assert_ok!(Nfts::transfer(RuntimeOrigin::signed(3), 0, 42, 3)); - assert_ok!(Nfts::burn(RuntimeOrigin::signed(3), 0, 42, None)); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config(), + )); + assert_ok!(Nfts::set_team( + RuntimeOrigin::signed(account(1)), + 0, + account(2), + account(3), + account(4), + )); + + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(2)), 0, 42, account(2), None)); + assert_ok!(Nfts::lock_item_transfer(RuntimeOrigin::signed(account(4)), 0, 42)); + assert_ok!(Nfts::unlock_item_transfer(RuntimeOrigin::signed(account(4)), 0, 42)); + assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(3))); + assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(3)), 0, 42, None)); }); } @@ -480,69 +593,85 @@ fn set_collection_metadata_should_work() { new_test_ext().execute_with(|| { // Cannot add metadata to unknown item assert_noop!( - Nfts::set_collection_metadata(RuntimeOrigin::signed(1), 0, bvec![0u8; 20]), + Nfts::set_collection_metadata(RuntimeOrigin::signed(account(1)), 0, bvec![0u8; 20]), Error::::NoConfig, ); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), - 1, + account(1), collection_config_with_all_settings_enabled() )); // Cannot add metadata to unowned item assert_noop!( - Nfts::set_collection_metadata(RuntimeOrigin::signed(2), 0, bvec![0u8; 20]), + Nfts::set_collection_metadata(RuntimeOrigin::signed(account(2)), 0, bvec![0u8; 20]), Error::::NoPermission, ); // Successfully add metadata and take deposit - Balances::make_free_balance_be(&1, 30); - assert_ok!(Nfts::set_collection_metadata(RuntimeOrigin::signed(1), 0, bvec![0u8; 20])); - assert_eq!(Balances::free_balance(&1), 9); + Balances::make_free_balance_be(&account(1), 30); + assert_ok!(Nfts::set_collection_metadata( + RuntimeOrigin::signed(account(1)), + 0, + bvec![0u8; 20] + )); + assert_eq!(Balances::free_balance(&account(1)), 9); assert!(CollectionMetadataOf::::contains_key(0)); // Force origin works, too. assert_ok!(Nfts::set_collection_metadata(RuntimeOrigin::root(), 0, bvec![0u8; 18])); // Update deposit - assert_ok!(Nfts::set_collection_metadata(RuntimeOrigin::signed(1), 0, bvec![0u8; 15])); - assert_eq!(Balances::free_balance(&1), 14); - assert_ok!(Nfts::set_collection_metadata(RuntimeOrigin::signed(1), 0, bvec![0u8; 25])); - assert_eq!(Balances::free_balance(&1), 4); + assert_ok!(Nfts::set_collection_metadata( + RuntimeOrigin::signed(account(1)), + 0, + bvec![0u8; 15] + )); + assert_eq!(Balances::free_balance(&account(1)), 14); + assert_ok!(Nfts::set_collection_metadata( + RuntimeOrigin::signed(account(1)), + 0, + bvec![0u8; 25] + )); + assert_eq!(Balances::free_balance(&account(1)), 4); // Cannot over-reserve assert_noop!( - Nfts::set_collection_metadata(RuntimeOrigin::signed(1), 0, bvec![0u8; 40]), + Nfts::set_collection_metadata(RuntimeOrigin::signed(account(1)), 0, bvec![0u8; 40]), BalancesError::::InsufficientBalance, ); // Can't set or clear metadata once frozen - assert_ok!(Nfts::set_collection_metadata(RuntimeOrigin::signed(1), 0, bvec![0u8; 15])); + assert_ok!(Nfts::set_collection_metadata( + RuntimeOrigin::signed(account(1)), + 0, + bvec![0u8; 15] + )); assert_ok!(Nfts::lock_collection( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, CollectionSettings::from_disabled(CollectionSetting::UnlockedMetadata.into()) )); assert_noop!( - Nfts::set_collection_metadata(RuntimeOrigin::signed(1), 0, bvec![0u8; 15]), + Nfts::set_collection_metadata(RuntimeOrigin::signed(account(1)), 0, bvec![0u8; 15]), Error::::LockedCollectionMetadata, ); assert_noop!( - Nfts::clear_collection_metadata(RuntimeOrigin::signed(1), 0), + Nfts::clear_collection_metadata(RuntimeOrigin::signed(account(1)), 0), Error::::LockedCollectionMetadata ); // Clear Metadata assert_ok!(Nfts::set_collection_metadata(RuntimeOrigin::root(), 0, bvec![0u8; 15])); assert_noop!( - Nfts::clear_collection_metadata(RuntimeOrigin::signed(2), 0), + Nfts::clear_collection_metadata(RuntimeOrigin::signed(account(2)), 0), Error::::NoPermission ); assert_noop!( - Nfts::clear_collection_metadata(RuntimeOrigin::signed(1), 1), + Nfts::clear_collection_metadata(RuntimeOrigin::signed(account(1)), 1), Error::::UnknownCollection ); assert_noop!( - Nfts::clear_collection_metadata(RuntimeOrigin::signed(1), 0), + Nfts::clear_collection_metadata(RuntimeOrigin::signed(account(1)), 0), Error::::LockedCollectionMetadata ); assert_ok!(Nfts::clear_collection_metadata(RuntimeOrigin::root(), 0)); @@ -553,61 +682,67 @@ fn set_collection_metadata_should_work() { #[test] fn set_item_metadata_should_work() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 30); + Balances::make_free_balance_be(&account(1), 30); // Cannot add metadata to unknown item assert_ok!(Nfts::force_create( RuntimeOrigin::root(), - 1, + account(1), collection_config_with_all_settings_enabled() )); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(1), 0, 42, 1, None)); + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); // Cannot add metadata to unowned item assert_noop!( - Nfts::set_metadata(RuntimeOrigin::signed(2), 0, 42, bvec![0u8; 20]), + Nfts::set_metadata(RuntimeOrigin::signed(account(2)), 0, 42, bvec![0u8; 20]), Error::::NoPermission, ); // Successfully add metadata and take deposit - assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(1), 0, 42, bvec![0u8; 20])); - assert_eq!(Balances::free_balance(&1), 8); + assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![0u8; 20])); + assert_eq!(Balances::free_balance(&account(1)), 8); assert!(ItemMetadataOf::::contains_key(0, 42)); // Force origin works, too. assert_ok!(Nfts::set_metadata(RuntimeOrigin::root(), 0, 42, bvec![0u8; 18])); // Update deposit - assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(1), 0, 42, bvec![0u8; 15])); - assert_eq!(Balances::free_balance(&1), 13); - assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(1), 0, 42, bvec![0u8; 25])); - assert_eq!(Balances::free_balance(&1), 3); + assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![0u8; 15])); + assert_eq!(Balances::free_balance(&account(1)), 13); + assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![0u8; 25])); + assert_eq!(Balances::free_balance(&account(1)), 3); // Cannot over-reserve assert_noop!( - Nfts::set_metadata(RuntimeOrigin::signed(1), 0, 42, bvec![0u8; 40]), + Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![0u8; 40]), BalancesError::::InsufficientBalance, ); // Can't set or clear metadata once frozen - assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(1), 0, 42, bvec![0u8; 15])); - assert_ok!(Nfts::lock_item_properties(RuntimeOrigin::signed(1), 0, 42, true, false)); + assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![0u8; 15])); + assert_ok!(Nfts::lock_item_properties( + RuntimeOrigin::signed(account(1)), + 0, + 42, + true, + false + )); assert_noop!( - Nfts::set_metadata(RuntimeOrigin::signed(1), 0, 42, bvec![0u8; 15]), + Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![0u8; 15]), Error::::LockedItemMetadata, ); assert_noop!( - Nfts::clear_metadata(RuntimeOrigin::signed(1), 0, 42), + Nfts::clear_metadata(RuntimeOrigin::signed(account(1)), 0, 42), Error::::LockedItemMetadata, ); // Clear Metadata assert_ok!(Nfts::set_metadata(RuntimeOrigin::root(), 0, 42, bvec![0u8; 15])); assert_noop!( - Nfts::clear_metadata(RuntimeOrigin::signed(2), 0, 42), + Nfts::clear_metadata(RuntimeOrigin::signed(account(2)), 0, 42), Error::::NoPermission, ); assert_noop!( - Nfts::clear_metadata(RuntimeOrigin::signed(1), 1, 42), + Nfts::clear_metadata(RuntimeOrigin::signed(account(1)), 1, 42), Error::::MetadataNotFound, ); assert_ok!(Nfts::clear_metadata(RuntimeOrigin::root(), 0, 42)); @@ -618,17 +753,17 @@ fn set_item_metadata_should_work() { #[test] fn set_collection_owner_attributes_should_work() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 100); + Balances::make_free_balance_be(&account(1), 100); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), - 1, + account(1), collection_config_with_all_settings_enabled() )); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(1), 0, 0, 1, None)); + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 0, account(1), None)); assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, None, AttributeNamespace::CollectionOwner, @@ -636,7 +771,7 @@ fn set_collection_owner_attributes_should_work() { bvec![0], )); assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, Some(0), AttributeNamespace::CollectionOwner, @@ -644,7 +779,7 @@ fn set_collection_owner_attributes_should_work() { bvec![0], )); assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, Some(0), AttributeNamespace::CollectionOwner, @@ -659,11 +794,11 @@ fn set_collection_owner_attributes_should_work() { (Some(0), AttributeNamespace::CollectionOwner, bvec![1], bvec![0]), ] ); - assert_eq!(Balances::reserved_balance(1), 10); + assert_eq!(Balances::reserved_balance(account(1)), 10); assert_eq!(Collection::::get(0).unwrap().owner_deposit, 9); assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, None, AttributeNamespace::CollectionOwner, @@ -678,11 +813,11 @@ fn set_collection_owner_attributes_should_work() { (Some(0), AttributeNamespace::CollectionOwner, bvec![1], bvec![0]), ] ); - assert_eq!(Balances::reserved_balance(1), 19); + assert_eq!(Balances::reserved_balance(account(1)), 19); assert_eq!(Collection::::get(0).unwrap().owner_deposit, 18); assert_ok!(Nfts::clear_attribute( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, Some(0), AttributeNamespace::CollectionOwner, @@ -695,33 +830,39 @@ fn set_collection_owner_attributes_should_work() { (Some(0), AttributeNamespace::CollectionOwner, bvec![0], bvec![0]), ] ); - assert_eq!(Balances::reserved_balance(1), 16); + assert_eq!(Balances::reserved_balance(account(1)), 16); let w = Nfts::get_destroy_witness(&0).unwrap(); - assert_ok!(Nfts::destroy(RuntimeOrigin::signed(1), 0, w)); + assert_ok!(Nfts::destroy(RuntimeOrigin::signed(account(1)), 0, w)); assert_eq!(attributes(0), vec![]); - assert_eq!(Balances::reserved_balance(1), 0); + assert_eq!(Balances::reserved_balance(account(1)), 0); }); } #[test] fn set_item_owner_attributes_should_work() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 100); - Balances::make_free_balance_be(&2, 100); - Balances::make_free_balance_be(&3, 100); + Balances::make_free_balance_be(&account(1), 100); + Balances::make_free_balance_be(&account(2), 100); + Balances::make_free_balance_be(&account(3), 100); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), - 1, + account(1), collection_config_with_all_settings_enabled() )); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(1), 0, 0, 2, default_item_config())); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 0, + account(2), + default_item_config() + )); // can't set for the collection assert_noop!( Nfts::set_attribute( - RuntimeOrigin::signed(2), + RuntimeOrigin::signed(account(2)), 0, None, AttributeNamespace::ItemOwner, @@ -733,7 +874,7 @@ fn set_item_owner_attributes_should_work() { // can't set for the non-owned item assert_noop!( Nfts::set_attribute( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, Some(0), AttributeNamespace::ItemOwner, @@ -743,7 +884,7 @@ fn set_item_owner_attributes_should_work() { Error::::NoPermission, ); assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(2), + RuntimeOrigin::signed(account(2)), 0, Some(0), AttributeNamespace::ItemOwner, @@ -751,7 +892,7 @@ fn set_item_owner_attributes_should_work() { bvec![0], )); assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(2), + RuntimeOrigin::signed(account(2)), 0, Some(0), AttributeNamespace::ItemOwner, @@ -759,7 +900,7 @@ fn set_item_owner_attributes_should_work() { bvec![0], )); assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(2), + RuntimeOrigin::signed(account(2)), 0, Some(0), AttributeNamespace::ItemOwner, @@ -774,11 +915,11 @@ fn set_item_owner_attributes_should_work() { (Some(0), AttributeNamespace::ItemOwner, bvec![2], bvec![0]), ] ); - assert_eq!(Balances::reserved_balance(2), 9); + assert_eq!(Balances::reserved_balance(account(2)), 9); // validate an attribute can be updated assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(2), + RuntimeOrigin::signed(account(2)), 0, Some(0), AttributeNamespace::ItemOwner, @@ -793,12 +934,12 @@ fn set_item_owner_attributes_should_work() { (Some(0), AttributeNamespace::ItemOwner, bvec![2], bvec![0]), ] ); - assert_eq!(Balances::reserved_balance(2), 18); + assert_eq!(Balances::reserved_balance(account(2)), 18); // validate only item's owner (or the root) can remove an attribute assert_noop!( Nfts::clear_attribute( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, Some(0), AttributeNamespace::ItemOwner, @@ -807,7 +948,7 @@ fn set_item_owner_attributes_should_work() { Error::::NoPermission, ); assert_ok!(Nfts::clear_attribute( - RuntimeOrigin::signed(2), + RuntimeOrigin::signed(account(2)), 0, Some(0), AttributeNamespace::ItemOwner, @@ -820,10 +961,10 @@ fn set_item_owner_attributes_should_work() { (Some(0), AttributeNamespace::ItemOwner, bvec![2], bvec![0]) ] ); - assert_eq!(Balances::reserved_balance(2), 15); + assert_eq!(Balances::reserved_balance(account(2)), 15); // transfer item - assert_ok!(Nfts::transfer(RuntimeOrigin::signed(2), 0, 0, 3)); + assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 0, account(3))); // validate the attribute are still here & the deposit belongs to the previous owner assert_eq!( @@ -836,12 +977,12 @@ fn set_item_owner_attributes_should_work() { let key: BoundedVec<_, _> = bvec![0]; let (_, deposit) = Attribute::::get((0, Some(0), AttributeNamespace::ItemOwner, &key)).unwrap(); - assert_eq!(deposit.account, Some(2)); + assert_eq!(deposit.account, Some(account(2))); assert_eq!(deposit.amount, 12); // on attribute update the deposit should be returned to the previous owner assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(3), + RuntimeOrigin::signed(account(3)), 0, Some(0), AttributeNamespace::ItemOwner, @@ -850,13 +991,13 @@ fn set_item_owner_attributes_should_work() { )); let (_, deposit) = Attribute::::get((0, Some(0), AttributeNamespace::ItemOwner, &key)).unwrap(); - assert_eq!(deposit.account, Some(3)); + assert_eq!(deposit.account, Some(account(3))); assert_eq!(deposit.amount, 13); - assert_eq!(Balances::reserved_balance(2), 3); - assert_eq!(Balances::reserved_balance(3), 13); + assert_eq!(Balances::reserved_balance(account(2)), 3); + assert_eq!(Balances::reserved_balance(account(3)), 13); // validate attributes on item deletion - assert_ok!(Nfts::burn(RuntimeOrigin::signed(3), 0, 0, None)); + assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(3)), 0, 0, None)); assert_eq!( attributes(0), vec![ @@ -865,90 +1006,101 @@ fn set_item_owner_attributes_should_work() { ] ); assert_ok!(Nfts::clear_attribute( - RuntimeOrigin::signed(3), + RuntimeOrigin::signed(account(3)), 0, Some(0), AttributeNamespace::ItemOwner, bvec![0], )); assert_ok!(Nfts::clear_attribute( - RuntimeOrigin::signed(2), + RuntimeOrigin::signed(account(2)), 0, Some(0), AttributeNamespace::ItemOwner, bvec![2], )); - assert_eq!(Balances::reserved_balance(2), 0); - assert_eq!(Balances::reserved_balance(3), 0); + assert_eq!(Balances::reserved_balance(account(2)), 0); + assert_eq!(Balances::reserved_balance(account(3)), 0); }); } #[test] fn set_external_account_attributes_should_work() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 100); - Balances::make_free_balance_be(&2, 100); + Balances::make_free_balance_be(&account(1), 100); + Balances::make_free_balance_be(&account(2), 100); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), - 1, + account(1), collection_config_with_all_settings_enabled() )); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(1), 0, 0, 1, default_item_config())); - assert_ok!(Nfts::approve_item_attributes(RuntimeOrigin::signed(1), 0, 0, 2)); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 0, + account(1), + default_item_config() + )); + assert_ok!(Nfts::approve_item_attributes( + RuntimeOrigin::signed(account(1)), + 0, + 0, + account(2) + )); assert_noop!( Nfts::set_attribute( - RuntimeOrigin::signed(2), + RuntimeOrigin::signed(account(2)), 0, Some(0), - AttributeNamespace::Account(1), + AttributeNamespace::Account(account(1)), bvec![0], bvec![0], ), Error::::NoPermission, ); assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(2), + RuntimeOrigin::signed(account(2)), 0, Some(0), - AttributeNamespace::Account(2), + AttributeNamespace::Account(account(2)), bvec![0], bvec![0], )); assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(2), + RuntimeOrigin::signed(account(2)), 0, Some(0), - AttributeNamespace::Account(2), + AttributeNamespace::Account(account(2)), bvec![1], bvec![0], )); assert_eq!( attributes(0), vec![ - (Some(0), AttributeNamespace::Account(2), bvec![0], bvec![0]), - (Some(0), AttributeNamespace::Account(2), bvec![1], bvec![0]), + (Some(0), AttributeNamespace::Account(account(2)), bvec![0], bvec![0]), + (Some(0), AttributeNamespace::Account(account(2)), bvec![1], bvec![0]), ] ); - assert_eq!(Balances::reserved_balance(2), 6); + assert_eq!(Balances::reserved_balance(account(2)), 6); // remove permission to set attributes assert_ok!(Nfts::cancel_item_attributes_approval( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, 0, - 2, + account(2), CancelAttributesApprovalWitness { account_attributes: 2 }, )); assert_eq!(attributes(0), vec![]); - assert_eq!(Balances::reserved_balance(2), 0); + assert_eq!(Balances::reserved_balance(account(2)), 0); assert_noop!( Nfts::set_attribute( - RuntimeOrigin::signed(2), + RuntimeOrigin::signed(account(2)), 0, Some(0), - AttributeNamespace::Account(2), + AttributeNamespace::Account(account(2)), bvec![0], bvec![0], ), @@ -960,18 +1112,33 @@ fn set_external_account_attributes_should_work() { #[test] fn validate_deposit_required_setting() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 100); - Balances::make_free_balance_be(&2, 100); - Balances::make_free_balance_be(&3, 100); + Balances::make_free_balance_be(&account(1), 100); + Balances::make_free_balance_be(&account(2), 100); + Balances::make_free_balance_be(&account(3), 100); // with the disabled DepositRequired setting, only the collection's owner can set the // attributes for free. - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 1, default_collection_config())); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(1), 0, 0, 2, default_item_config())); - assert_ok!(Nfts::approve_item_attributes(RuntimeOrigin::signed(2), 0, 0, 3)); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 0, + account(2), + default_item_config() + )); + assert_ok!(Nfts::approve_item_attributes( + RuntimeOrigin::signed(account(2)), + 0, + 0, + account(3) + )); assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, Some(0), AttributeNamespace::CollectionOwner, @@ -979,7 +1146,7 @@ fn validate_deposit_required_setting() { bvec![0], )); assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(2), + RuntimeOrigin::signed(account(2)), 0, Some(0), AttributeNamespace::ItemOwner, @@ -987,10 +1154,10 @@ fn validate_deposit_required_setting() { bvec![0], )); assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(3), + RuntimeOrigin::signed(account(3)), 0, Some(0), - AttributeNamespace::Account(3), + AttributeNamespace::Account(account(3)), bvec![2], bvec![0], )); @@ -1005,13 +1172,13 @@ fn validate_deposit_required_setting() { vec![ (Some(0), AttributeNamespace::CollectionOwner, bvec![0], bvec![0]), (Some(0), AttributeNamespace::ItemOwner, bvec![1], bvec![0]), - (Some(0), AttributeNamespace::Account(3), bvec![2], bvec![0]), + (Some(0), AttributeNamespace::Account(account(3)), bvec![2], bvec![0]), (Some(0), AttributeNamespace::Pallet, bvec![3], bvec![0]), ] ); - assert_eq!(Balances::reserved_balance(1), 0); - assert_eq!(Balances::reserved_balance(2), 3); - assert_eq!(Balances::reserved_balance(3), 3); + assert_eq!(Balances::reserved_balance(account(1)), 0); + assert_eq!(Balances::reserved_balance(account(2)), 3); + assert_eq!(Balances::reserved_balance(account(3)), 3); assert_ok!( ::AccountId, ItemConfig>>::clear_attribute( @@ -1025,7 +1192,7 @@ fn validate_deposit_required_setting() { vec![ (Some(0), AttributeNamespace::CollectionOwner, bvec![0], bvec![0]), (Some(0), AttributeNamespace::ItemOwner, bvec![1], bvec![0]), - (Some(0), AttributeNamespace::Account(3), bvec![2], bvec![0]), + (Some(0), AttributeNamespace::Account(account(3)), bvec![2], bvec![0]), ] ); }); @@ -1034,18 +1201,18 @@ fn validate_deposit_required_setting() { #[test] fn set_attribute_should_respect_lock() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 100); + Balances::make_free_balance_be(&account(1), 100); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), - 1, + account(1), collection_config_with_all_settings_enabled(), )); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(1), 0, 0, 1, None)); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(1), 0, 1, 1, None)); + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 0, account(1), None)); + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 1, account(1), None)); assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, None, AttributeNamespace::CollectionOwner, @@ -1053,7 +1220,7 @@ fn set_attribute_should_respect_lock() { bvec![0], )); assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, Some(0), AttributeNamespace::CollectionOwner, @@ -1061,7 +1228,7 @@ fn set_attribute_should_respect_lock() { bvec![0], )); assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, Some(1), AttributeNamespace::CollectionOwner, @@ -1076,11 +1243,11 @@ fn set_attribute_should_respect_lock() { (Some(1), AttributeNamespace::CollectionOwner, bvec![0], bvec![0]), ] ); - assert_eq!(Balances::reserved_balance(1), 11); + assert_eq!(Balances::reserved_balance(account(1)), 11); - assert_ok!(Nfts::set_collection_metadata(RuntimeOrigin::signed(1), 0, bvec![])); + assert_ok!(Nfts::set_collection_metadata(RuntimeOrigin::signed(account(1)), 0, bvec![])); assert_ok!(Nfts::lock_collection( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, CollectionSettings::from_disabled(CollectionSetting::UnlockedAttributes.into()) )); @@ -1088,7 +1255,7 @@ fn set_attribute_should_respect_lock() { let e = Error::::LockedCollectionAttributes; assert_noop!( Nfts::set_attribute( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, None, AttributeNamespace::CollectionOwner, @@ -1098,7 +1265,7 @@ fn set_attribute_should_respect_lock() { e ); assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, Some(0), AttributeNamespace::CollectionOwner, @@ -1106,11 +1273,17 @@ fn set_attribute_should_respect_lock() { bvec![1], )); - assert_ok!(Nfts::lock_item_properties(RuntimeOrigin::signed(1), 0, 0, false, true)); + assert_ok!(Nfts::lock_item_properties( + RuntimeOrigin::signed(account(1)), + 0, + 0, + false, + true + )); let e = Error::::LockedItemAttributes; assert_noop!( Nfts::set_attribute( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, Some(0), AttributeNamespace::CollectionOwner, @@ -1120,7 +1293,7 @@ fn set_attribute_should_respect_lock() { e ); assert_ok!(Nfts::set_attribute( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, Some(1), AttributeNamespace::CollectionOwner, @@ -1133,22 +1306,22 @@ fn set_attribute_should_respect_lock() { #[test] fn preserve_config_for_frozen_items() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 100); + Balances::make_free_balance_be(&account(1), 100); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), - 1, + account(1), collection_config_with_all_settings_enabled() )); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(1), 0, 0, 1, None)); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(1), 0, 1, 1, None)); + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 0, account(1), None)); + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 1, account(1), None)); // if the item is not locked/frozen then the config gets deleted on item burn - assert_ok!(Nfts::burn(RuntimeOrigin::signed(1), 0, 1, Some(1))); + assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(1)), 0, 1, Some(account(1)))); assert!(!ItemConfigOf::::contains_key(0, 1)); // lock the item and ensure the config stays unchanged - assert_ok!(Nfts::lock_item_properties(RuntimeOrigin::signed(1), 0, 0, true, true)); + assert_ok!(Nfts::lock_item_properties(RuntimeOrigin::signed(account(1)), 0, 0, true, true)); let expect_config = item_config_from_disabled_settings( ItemSetting::UnlockedAttributes | ItemSetting::UnlockedMetadata, @@ -1156,18 +1329,24 @@ fn preserve_config_for_frozen_items() { let config = ItemConfigOf::::get(0, 0).unwrap(); assert_eq!(config, expect_config); - assert_ok!(Nfts::burn(RuntimeOrigin::signed(1), 0, 0, Some(1))); + assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(1)), 0, 0, Some(account(1)))); let config = ItemConfigOf::::get(0, 0).unwrap(); assert_eq!(config, expect_config); // can't mint with the different config assert_noop!( - Nfts::force_mint(RuntimeOrigin::signed(1), 0, 0, 1, default_item_config()), + Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 0, + account(2), + default_item_config() + ), Error::::InconsistentItemConfig ); assert_ok!(Nfts::update_mint_settings( - RuntimeOrigin::signed(1), + RuntimeOrigin::signed(account(1)), 0, MintSettings { default_item_settings: ItemSettings::from_disabled( @@ -1176,26 +1355,36 @@ fn preserve_config_for_frozen_items() { ..Default::default() } )); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(1), 0, 0, 1, None)); + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 0, account(1), None)); }); } #[test] fn force_update_collection_should_work() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 100); + Balances::make_free_balance_be(&account(1), 100); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), - 1, + account(1), collection_config_with_all_settings_enabled() )); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(1), 0, 42, 1, None)); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(1), 0, 69, 2, default_item_config())); - assert_ok!(Nfts::set_collection_metadata(RuntimeOrigin::signed(1), 0, bvec![0; 20])); - assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(1), 0, 42, bvec![0; 20])); - assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(1), 0, 69, bvec![0; 20])); - assert_eq!(Balances::reserved_balance(1), 65); + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 69, + account(2), + default_item_config(), + )); + assert_ok!(Nfts::set_collection_metadata( + RuntimeOrigin::signed(account(1)), + 0, + bvec![0; 20] + )); + assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![0; 20])); + assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 69, bvec![0; 20])); + assert_eq!(Balances::reserved_balance(account(1)), 65); // force item status to be free holding assert_ok!(Nfts::force_collection_config( @@ -1203,52 +1392,66 @@ fn force_update_collection_should_work() { 0, collection_config_from_disabled_settings(CollectionSetting::DepositRequired.into()), )); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(1), 0, 142, 1, None)); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(1), 0, 169, 2, default_item_config())); - assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(1), 0, 142, bvec![0; 20])); - assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(1), 0, 169, bvec![0; 20])); + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 142, account(1), None)); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 169, + account(2), + default_item_config(), + )); + assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 142, bvec![0; 20])); + assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 169, bvec![0; 20])); - Balances::make_free_balance_be(&5, 100); - assert_ok!(Nfts::force_collection_owner(RuntimeOrigin::root(), 0, 5)); - assert_eq!(collections(), vec![(5, 0)]); - assert_eq!(Balances::reserved_balance(1), 2); - assert_eq!(Balances::reserved_balance(5), 63); + Balances::make_free_balance_be(&account(5), 100); + assert_ok!(Nfts::force_collection_owner(RuntimeOrigin::root(), 0, account(5))); + assert_eq!(collections(), vec![(account(5), 0)]); + assert_eq!(Balances::reserved_balance(account(1)), 2); + assert_eq!(Balances::reserved_balance(account(5)), 63); - assert_ok!(Nfts::redeposit(RuntimeOrigin::signed(5), 0, bvec![0, 42, 50, 69, 100])); - assert_eq!(Balances::reserved_balance(1), 0); + assert_ok!(Nfts::redeposit( + RuntimeOrigin::signed(account(5)), + 0, + bvec![0, 42, 50, 69, 100] + )); + assert_eq!(Balances::reserved_balance(account(1)), 0); - assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(5), 0, 42, bvec![0; 20])); - assert_eq!(Balances::reserved_balance(5), 42); + assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(5)), 0, 42, bvec![0; 20])); + assert_eq!(Balances::reserved_balance(account(5)), 42); - assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(5), 0, 69, bvec![0; 20])); - assert_eq!(Balances::reserved_balance(5), 21); + assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(5)), 0, 69, bvec![0; 20])); + assert_eq!(Balances::reserved_balance(account(5)), 21); - assert_ok!(Nfts::set_collection_metadata(RuntimeOrigin::signed(5), 0, bvec![0; 20])); - assert_eq!(Balances::reserved_balance(5), 0); + assert_ok!(Nfts::set_collection_metadata( + RuntimeOrigin::signed(account(5)), + 0, + bvec![0; 20] + )); + assert_eq!(Balances::reserved_balance(account(5)), 0); // validate new roles - assert_ok!(Nfts::set_team(RuntimeOrigin::root(), 0, 2, 3, 4)); + assert_ok!(Nfts::set_team(RuntimeOrigin::root(), 0, account(2), account(3), account(4))); assert_eq!( - CollectionRoleOf::::get(0, 2).unwrap(), + CollectionRoleOf::::get(0, account(2)).unwrap(), CollectionRoles(CollectionRole::Issuer.into()) ); assert_eq!( - CollectionRoleOf::::get(0, 3).unwrap(), + CollectionRoleOf::::get(0, account(3)).unwrap(), CollectionRoles(CollectionRole::Admin.into()) ); assert_eq!( - CollectionRoleOf::::get(0, 4).unwrap(), + CollectionRoleOf::::get(0, account(4)).unwrap(), CollectionRoles(CollectionRole::Freezer.into()) ); - assert_ok!(Nfts::set_team(RuntimeOrigin::root(), 0, 3, 2, 3)); + assert_ok!(Nfts::set_team(RuntimeOrigin::root(), 0, account(3), account(2), account(3))); assert_eq!( - CollectionRoleOf::::get(0, 2).unwrap(), + CollectionRoleOf::::get(0, account(2)).unwrap(), CollectionRoles(CollectionRole::Admin.into()) ); assert_eq!( - CollectionRoleOf::::get(0, 3).unwrap(), + CollectionRoleOf::::get(0, account(3)).unwrap(), CollectionRoles(CollectionRole::Issuer | CollectionRole::Freezer) ); }); @@ -1257,68 +1460,120 @@ fn force_update_collection_should_work() { #[test] fn burn_works() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 100); + Balances::make_free_balance_be(&account(1), 100); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), - 1, + account(1), collection_config_with_all_settings_enabled() )); - assert_ok!(Nfts::set_team(RuntimeOrigin::signed(1), 0, 2, 3, 4)); + assert_ok!(Nfts::set_team( + RuntimeOrigin::signed(account(1)), + 0, + account(2), + account(3), + account(4), + )); assert_noop!( - Nfts::burn(RuntimeOrigin::signed(5), 0, 42, Some(5)), + Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 42, Some(account(5))), Error::::UnknownItem ); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(2), 0, 42, 5, default_item_config())); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(2), 0, 69, 5, default_item_config())); - assert_eq!(Balances::reserved_balance(1), 2); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(2)), + 0, + 42, + account(5), + default_item_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(2)), + 0, + 69, + account(5), + default_item_config() + )); + assert_eq!(Balances::reserved_balance(account(1)), 2); assert_noop!( - Nfts::burn(RuntimeOrigin::signed(0), 0, 42, None), + Nfts::burn(RuntimeOrigin::signed(account(0)), 0, 42, None), Error::::NoPermission ); assert_noop!( - Nfts::burn(RuntimeOrigin::signed(5), 0, 42, Some(6)), + Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 42, Some(account(6))), Error::::WrongOwner ); - assert_ok!(Nfts::burn(RuntimeOrigin::signed(5), 0, 42, Some(5))); - assert_ok!(Nfts::burn(RuntimeOrigin::signed(3), 0, 69, Some(5))); - assert_eq!(Balances::reserved_balance(1), 0); + assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 42, Some(account(5)))); + assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(3)), 0, 69, Some(account(5)))); + assert_eq!(Balances::reserved_balance(account(1)), 0); }); } #[test] fn approval_lifecycle_works() { new_test_ext().execute_with(|| { - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 1, default_collection_config())); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(1), 0, 42, 2, default_item_config())); - assert_ok!(Nfts::approve_transfer(RuntimeOrigin::signed(2), 0, 42, 3, None)); - assert_ok!(Nfts::transfer(RuntimeOrigin::signed(3), 0, 42, 4)); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 42, + account(2), + default_item_config() + )); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + 42, + account(3), + None + )); + assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(4))); assert_noop!( - Nfts::transfer(RuntimeOrigin::signed(3), 0, 42, 3), + Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(3)), Error::::NoPermission ); assert!(Item::::get(0, 42).unwrap().approvals.is_empty()); - assert_ok!(Nfts::approve_transfer(RuntimeOrigin::signed(4), 0, 42, 2, None)); - assert_ok!(Nfts::transfer(RuntimeOrigin::signed(2), 0, 42, 2)); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(4)), + 0, + 42, + account(2), + None + )); + assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(2))); // ensure we can't buy an item when the collection has a NonTransferableItems flag let collection_id = 1; assert_ok!(Nfts::force_create( RuntimeOrigin::root(), - 1, + account(1), collection_config_from_disabled_settings( CollectionSetting::TransferableItems | CollectionSetting::DepositRequired ) )); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(1), 1, collection_id, 1, None)); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(account(1)), + 1, + collection_id, + account(1), + None, + )); assert_noop!( - Nfts::approve_transfer(RuntimeOrigin::signed(1), collection_id, 1, 2, None), + Nfts::approve_transfer( + RuntimeOrigin::signed(account(1)), + collection_id, + 1, + account(2), + None + ), Error::::ItemsNonTransferable ); }); @@ -1327,46 +1582,74 @@ fn approval_lifecycle_works() { #[test] fn cancel_approval_works() { new_test_ext().execute_with(|| { - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 1, default_collection_config())); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(1), 0, 42, 2, default_item_config())); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 42, + account(2), + default_item_config() + )); - assert_ok!(Nfts::approve_transfer(RuntimeOrigin::signed(2), 0, 42, 3, None)); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + 42, + account(3), + None + )); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(2), 1, 42, 3), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 1, 42, account(3)), Error::::UnknownItem ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(2), 0, 43, 3), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 43, account(3)), Error::::UnknownItem ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(3), 0, 42, 3), + Nfts::cancel_approval(RuntimeOrigin::signed(account(3)), 0, 42, account(3)), Error::::NoPermission ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(2), 0, 42, 4), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(4)), Error::::NotDelegate ); - assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(2), 0, 42, 3)); + assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(3))); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(2), 0, 42, 3), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(3)), Error::::NotDelegate ); let current_block = 1; System::set_block_number(current_block); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(1), 0, 69, 2, default_item_config())); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 69, + account(2), + default_item_config() + )); // approval expires after 2 blocks. - assert_ok!(Nfts::approve_transfer(RuntimeOrigin::signed(2), 0, 42, 3, Some(2))); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + 42, + account(3), + Some(2) + )); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(5), 0, 42, 3), + Nfts::cancel_approval(RuntimeOrigin::signed(account(5)), 0, 42, account(3)), Error::::NoPermission ); System::set_block_number(current_block + 3); // 5 can cancel the approval since the deadline has passed. - assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(5), 0, 42, 3)); + assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(5)), 0, 42, account(3))); assert_eq!(approvals(0, 69), vec![]); }); } @@ -1374,23 +1657,54 @@ fn cancel_approval_works() { #[test] fn approving_multiple_accounts_works() { new_test_ext().execute_with(|| { - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 1, default_collection_config())); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(1), 0, 42, 2, default_item_config())); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 42, + account(2), + default_item_config() + )); let current_block = 1; System::set_block_number(current_block); - assert_ok!(Nfts::approve_transfer(RuntimeOrigin::signed(2), 0, 42, 3, None)); - assert_ok!(Nfts::approve_transfer(RuntimeOrigin::signed(2), 0, 42, 4, None)); - assert_ok!(Nfts::approve_transfer(RuntimeOrigin::signed(2), 0, 42, 5, Some(2))); - assert_eq!(approvals(0, 42), vec![(3, None), (4, None), (5, Some(current_block + 2))]); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + 42, + account(3), + None + )); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + 42, + account(4), + None + )); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + 42, + account(5), + Some(2) + )); + assert_eq!( + approvals(0, 42), + vec![(account(3), None), (account(4), None), (account(5), Some(current_block + 2))] + ); - assert_ok!(Nfts::transfer(RuntimeOrigin::signed(4), 0, 42, 6)); + assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(4)), 0, 42, account(6))); assert_noop!( - Nfts::transfer(RuntimeOrigin::signed(3), 0, 42, 7), + Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(7)), Error::::NoPermission ); assert_noop!( - Nfts::transfer(RuntimeOrigin::signed(5), 0, 42, 8), + Nfts::transfer(RuntimeOrigin::signed(account(5)), 0, 42, account(8)), Error::::NoPermission ); }); @@ -1399,15 +1713,31 @@ fn approving_multiple_accounts_works() { #[test] fn approvals_limit_works() { new_test_ext().execute_with(|| { - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 1, default_collection_config())); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(1), 0, 42, 2, default_item_config())); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 42, + account(2), + default_item_config() + )); for i in 3..13 { - assert_ok!(Nfts::approve_transfer(RuntimeOrigin::signed(2), 0, 42, i, None)); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + 42, + account(i), + None + )); } // the limit is 10 assert_noop!( - Nfts::approve_transfer(RuntimeOrigin::signed(2), 0, 42, 14, None), + Nfts::approve_transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(14), None), Error::::ReachedApprovalLimit ); }); @@ -1421,55 +1751,89 @@ fn approval_deadline_works() { assert_ok!(Nfts::force_create( RuntimeOrigin::root(), - 1, + account(1), collection_config_from_disabled_settings(CollectionSetting::DepositRequired.into()) )); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(1), 0, 42, 2, default_item_config())); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 42, + account(2), + default_item_config() + )); // the approval expires after the 2nd block. - assert_ok!(Nfts::approve_transfer(RuntimeOrigin::signed(2), 0, 42, 3, Some(2))); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + 42, + account(3), + Some(2) + )); System::set_block_number(3); assert_noop!( - Nfts::transfer(RuntimeOrigin::signed(3), 0, 42, 4), + Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(4)), Error::::ApprovalExpired ); System::set_block_number(1); - assert_ok!(Nfts::transfer(RuntimeOrigin::signed(3), 0, 42, 4)); + assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(4))); assert_eq!(System::block_number(), 1); // make a new approval with a deadline after 4 blocks, so it will expire after the 5th // block. - assert_ok!(Nfts::approve_transfer(RuntimeOrigin::signed(4), 0, 42, 6, Some(4))); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(4)), + 0, + 42, + account(6), + Some(4) + )); // this should still work. System::set_block_number(5); - assert_ok!(Nfts::transfer(RuntimeOrigin::signed(6), 0, 42, 5)); + assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(6)), 0, 42, account(5))); }); } #[test] fn cancel_approval_works_with_admin() { new_test_ext().execute_with(|| { - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 1, default_collection_config())); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(1), 0, 42, 2, default_item_config())); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 42, + account(2), + default_item_config() + )); - assert_ok!(Nfts::approve_transfer(RuntimeOrigin::signed(2), 0, 42, 3, None)); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + 42, + account(3), + None + )); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(1), 1, 42, 1), + Nfts::cancel_approval(RuntimeOrigin::signed(account(1)), 1, 42, account(1)), Error::::UnknownItem ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(1), 0, 43, 1), + Nfts::cancel_approval(RuntimeOrigin::signed(account(1)), 0, 43, account(1)), Error::::UnknownItem ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(1), 0, 42, 4), + Nfts::cancel_approval(RuntimeOrigin::signed(account(1)), 0, 42, account(4)), Error::::NotDelegate ); - assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(1), 0, 42, 3)); + assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(1)), 0, 42, account(3))); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(1), 0, 42, 1), + Nfts::cancel_approval(RuntimeOrigin::signed(account(1)), 0, 42, account(1)), Error::::NotDelegate ); }); @@ -1478,26 +1842,42 @@ fn cancel_approval_works_with_admin() { #[test] fn cancel_approval_works_with_force() { new_test_ext().execute_with(|| { - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 1, default_collection_config())); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(1), 0, 42, 2, default_item_config())); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 42, + account(2), + default_item_config() + )); - assert_ok!(Nfts::approve_transfer(RuntimeOrigin::signed(2), 0, 42, 3, None)); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + 42, + account(3), + None + )); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::root(), 1, 42, 1), + Nfts::cancel_approval(RuntimeOrigin::root(), 1, 42, account(1)), Error::::UnknownItem ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::root(), 0, 43, 1), + Nfts::cancel_approval(RuntimeOrigin::root(), 0, 43, account(1)), Error::::UnknownItem ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::root(), 0, 42, 4), + Nfts::cancel_approval(RuntimeOrigin::root(), 0, 42, account(4)), Error::::NotDelegate ); - assert_ok!(Nfts::cancel_approval(RuntimeOrigin::root(), 0, 42, 3)); + assert_ok!(Nfts::cancel_approval(RuntimeOrigin::root(), 0, 42, account(3))); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::root(), 0, 42, 1), + Nfts::cancel_approval(RuntimeOrigin::root(), 0, 42, account(1)), Error::::NotDelegate ); }); @@ -1506,32 +1886,54 @@ fn cancel_approval_works_with_force() { #[test] fn clear_all_transfer_approvals_works() { new_test_ext().execute_with(|| { - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 1, default_collection_config())); - assert_ok!(Nfts::force_mint(RuntimeOrigin::signed(1), 0, 42, 2, default_item_config())); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 42, + account(2), + default_item_config() + )); - assert_ok!(Nfts::approve_transfer(RuntimeOrigin::signed(2), 0, 42, 3, None)); - assert_ok!(Nfts::approve_transfer(RuntimeOrigin::signed(2), 0, 42, 4, None)); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + 42, + account(3), + None + )); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + 42, + account(4), + None + )); assert_noop!( - Nfts::clear_all_transfer_approvals(RuntimeOrigin::signed(3), 0, 42), + Nfts::clear_all_transfer_approvals(RuntimeOrigin::signed(account(3)), 0, 42), Error::::NoPermission ); - assert_ok!(Nfts::clear_all_transfer_approvals(RuntimeOrigin::signed(2), 0, 42)); + assert_ok!(Nfts::clear_all_transfer_approvals(RuntimeOrigin::signed(account(2)), 0, 42)); assert!(events().contains(&Event::::AllApprovalsCancelled { collection: 0, item: 42, - owner: 2, + owner: account(2), })); assert_eq!(approvals(0, 42), vec![]); assert_noop!( - Nfts::transfer(RuntimeOrigin::signed(3), 0, 42, 5), + Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(5)), Error::::NoPermission ); assert_noop!( - Nfts::transfer(RuntimeOrigin::signed(4), 0, 42, 5), + Nfts::transfer(RuntimeOrigin::signed(account(4)), 0, 42, account(5)), Error::::NoPermission ); }); @@ -1541,15 +1943,19 @@ fn clear_all_transfer_approvals_works() { fn max_supply_should_work() { new_test_ext().execute_with(|| { let collection_id = 0; - let user_id = 1; + let user_id = account(1); let max_supply = 1; // validate set_collection_max_supply - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), user_id, default_collection_config())); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + user_id.clone(), + default_collection_config() + )); assert_eq!(CollectionConfigOf::::get(collection_id).unwrap().max_supply, None); assert_ok!(Nfts::set_collection_max_supply( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, max_supply )); @@ -1564,18 +1970,18 @@ fn max_supply_should_work() { })); assert_ok!(Nfts::set_collection_max_supply( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, max_supply + 1 )); assert_ok!(Nfts::lock_collection( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, CollectionSettings::from_disabled(CollectionSetting::UnlockedMaxSupply.into()) )); assert_noop!( Nfts::set_collection_max_supply( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, max_supply + 2 ), @@ -1583,10 +1989,22 @@ fn max_supply_should_work() { ); // validate we can't mint more to max supply - assert_ok!(Nfts::mint(RuntimeOrigin::signed(user_id), collection_id, 0, user_id, None)); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(user_id), collection_id, 1, user_id, None)); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(user_id.clone()), + collection_id, + 0, + user_id.clone(), + None + )); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(user_id.clone()), + collection_id, + 1, + user_id.clone(), + None + )); assert_noop!( - Nfts::mint(RuntimeOrigin::signed(user_id), collection_id, 2, user_id, None), + Nfts::mint(RuntimeOrigin::signed(user_id.clone()), collection_id, 2, user_id, None), Error::::MaxSupplyReached ); }); @@ -1596,15 +2014,19 @@ fn max_supply_should_work() { fn mint_settings_should_work() { new_test_ext().execute_with(|| { let collection_id = 0; - let user_id = 1; + let user_id = account(1); let item_id = 0; - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), user_id, default_collection_config())); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + user_id.clone(), + default_collection_config() + )); assert_ok!(Nfts::mint( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, item_id, - user_id, + user_id.clone(), None, )); assert_eq!( @@ -1618,7 +2040,7 @@ fn mint_settings_should_work() { let collection_id = 1; assert_ok!(Nfts::force_create( RuntimeOrigin::root(), - user_id, + user_id.clone(), CollectionConfig { mint_settings: MintSettings { default_item_settings: ItemSettings::from_disabled( @@ -1630,10 +2052,10 @@ fn mint_settings_should_work() { } )); assert_ok!(Nfts::mint( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, item_id, - user_id, + user_id.clone(), None, )); assert_eq!( @@ -1650,30 +2072,34 @@ fn mint_settings_should_work() { #[test] fn set_price_should_work() { new_test_ext().execute_with(|| { - let user_id = 1; + let user_id = account(1); let collection_id = 0; let item_1 = 1; let item_2 = 2; - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), user_id, default_collection_config())); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + user_id.clone(), + default_collection_config() + )); assert_ok!(Nfts::mint( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, item_1, - user_id, + user_id.clone(), None, )); assert_ok!(Nfts::mint( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, item_2, - user_id, + user_id.clone(), None, )); assert_ok!(Nfts::set_price( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, item_1, Some(1), @@ -1681,11 +2107,11 @@ fn set_price_should_work() { )); assert_ok!(Nfts::set_price( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, item_2, Some(2), - Some(3) + Some(account(3)), )); let item = ItemPriceOf::::get(collection_id, item_1).unwrap(); @@ -1694,7 +2120,7 @@ fn set_price_should_work() { let item = ItemPriceOf::::get(collection_id, item_2).unwrap(); assert_eq!(item.0, 2); - assert_eq!(item.1, Some(3)); + assert_eq!(item.1, Some(account(3))); assert!(events().contains(&Event::::ItemPriceSet { collection: collection_id, @@ -1705,7 +2131,7 @@ fn set_price_should_work() { // validate we can unset the price assert_ok!(Nfts::set_price( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, item_2, None, @@ -1721,22 +2147,28 @@ fn set_price_should_work() { let collection_id = 1; assert_ok!(Nfts::force_create( RuntimeOrigin::root(), - user_id, + user_id.clone(), collection_config_from_disabled_settings( CollectionSetting::TransferableItems | CollectionSetting::DepositRequired ) )); assert_ok!(Nfts::mint( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, item_1, - user_id, + user_id.clone(), None, )); assert_noop!( - Nfts::set_price(RuntimeOrigin::signed(user_id), collection_id, item_1, Some(2), None), + Nfts::set_price( + RuntimeOrigin::signed(user_id.clone()), + collection_id, + item_1, + Some(2), + None + ), Error::::ItemsNonTransferable ); }); @@ -1745,9 +2177,9 @@ fn set_price_should_work() { #[test] fn buy_item_should_work() { new_test_ext().execute_with(|| { - let user_1 = 1; - let user_2 = 2; - let user_3 = 3; + let user_1 = account(1); + let user_2 = account(2); + let user_3 = account(3); let collection_id = 0; let item_1 = 1; let item_2 = 2; @@ -1760,14 +2192,36 @@ fn buy_item_should_work() { Balances::make_free_balance_be(&user_2, initial_balance); Balances::make_free_balance_be(&user_3, initial_balance); - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), user_1, default_collection_config())); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + user_1.clone(), + default_collection_config() + )); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(user_1), collection_id, item_1, user_1, None)); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(user_1), collection_id, item_2, user_1, None)); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(user_1), collection_id, item_3, user_1, None)); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(user_1.clone()), + collection_id, + item_1, + user_1.clone(), + None + )); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(user_1.clone()), + collection_id, + item_2, + user_1.clone(), + None + )); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(user_1.clone()), + collection_id, + item_3, + user_1.clone(), + None + )); assert_ok!(Nfts::set_price( - RuntimeOrigin::signed(user_1), + RuntimeOrigin::signed(user_1.clone()), collection_id, item_1, Some(price_1), @@ -1775,22 +2229,22 @@ fn buy_item_should_work() { )); assert_ok!(Nfts::set_price( - RuntimeOrigin::signed(user_1), + RuntimeOrigin::signed(user_1.clone()), collection_id, item_2, Some(price_2), - Some(user_3), + Some(user_3.clone()), )); // can't buy for less assert_noop!( - Nfts::buy_item(RuntimeOrigin::signed(user_2), collection_id, item_1, 1), + Nfts::buy_item(RuntimeOrigin::signed(user_2.clone()), collection_id, item_1, 1), Error::::BidTooLow ); // pass the higher price to validate it will still deduct correctly assert_ok!(Nfts::buy_item( - RuntimeOrigin::signed(user_2), + RuntimeOrigin::signed(user_2.clone()), collection_id, item_1, price_1 + 1, @@ -1798,31 +2252,36 @@ fn buy_item_should_work() { // validate the new owner & balances let item = Item::::get(collection_id, item_1).unwrap(); - assert_eq!(item.owner, user_2); - assert_eq!(Balances::total_balance(&user_1), initial_balance + price_1); - assert_eq!(Balances::total_balance(&user_2), initial_balance - price_1); + assert_eq!(item.owner, user_2.clone()); + assert_eq!(Balances::total_balance(&user_1.clone()), initial_balance + price_1); + assert_eq!(Balances::total_balance(&user_2.clone()), initial_balance - price_1); // can't buy from yourself assert_noop!( - Nfts::buy_item(RuntimeOrigin::signed(user_1), collection_id, item_2, price_2), + Nfts::buy_item(RuntimeOrigin::signed(user_1.clone()), collection_id, item_2, price_2), Error::::NoPermission ); // can't buy when the item is listed for a specific buyer assert_noop!( - Nfts::buy_item(RuntimeOrigin::signed(user_2), collection_id, item_2, price_2), + Nfts::buy_item(RuntimeOrigin::signed(user_2.clone()), collection_id, item_2, price_2), Error::::NoPermission ); // can buy when I'm a whitelisted buyer - assert_ok!(Nfts::buy_item(RuntimeOrigin::signed(user_3), collection_id, item_2, price_2)); + assert_ok!(Nfts::buy_item( + RuntimeOrigin::signed(user_3.clone()), + collection_id, + item_2, + price_2 + )); assert!(events().contains(&Event::::ItemBought { collection: collection_id, item: item_2, price: price_2, - seller: user_1, - buyer: user_3, + seller: user_1.clone(), + buyer: user_3.clone(), })); // ensure we reset the buyer field @@ -1830,14 +2289,14 @@ fn buy_item_should_work() { // can't buy when item is not for sale assert_noop!( - Nfts::buy_item(RuntimeOrigin::signed(user_2), collection_id, item_3, price_2), + Nfts::buy_item(RuntimeOrigin::signed(user_2.clone()), collection_id, item_3, price_2), Error::::NotForSale ); // ensure we can't buy an item when the collection or an item are frozen { assert_ok!(Nfts::set_price( - RuntimeOrigin::signed(user_1), + RuntimeOrigin::signed(user_1.clone()), collection_id, item_3, Some(price_1), @@ -1846,7 +2305,7 @@ fn buy_item_should_work() { // lock the collection assert_ok!(Nfts::lock_collection( - RuntimeOrigin::signed(user_1), + RuntimeOrigin::signed(user_1.clone()), collection_id, CollectionSettings::from_disabled(CollectionSetting::TransferableItems.into()) )); @@ -1857,7 +2316,7 @@ fn buy_item_should_work() { bid_price: price_1, }); assert_noop!( - buy_item_call.dispatch(RuntimeOrigin::signed(user_2)), + buy_item_call.dispatch(RuntimeOrigin::signed(user_2.clone())), Error::::ItemsNonTransferable ); @@ -1870,7 +2329,7 @@ fn buy_item_should_work() { // lock the transfer assert_ok!(Nfts::lock_item_transfer( - RuntimeOrigin::signed(user_1), + RuntimeOrigin::signed(user_1.clone()), collection_id, item_3, )); @@ -1891,9 +2350,9 @@ fn buy_item_should_work() { #[test] fn pay_tips_should_work() { new_test_ext().execute_with(|| { - let user_1 = 1; - let user_2 = 2; - let user_3 = 3; + let user_1 = account(1); + let user_2 = account(2); + let user_3 = account(3); let collection_id = 0; let item_id = 1; let tip = 2; @@ -1904,10 +2363,20 @@ fn pay_tips_should_work() { Balances::make_free_balance_be(&user_3, initial_balance); assert_ok!(Nfts::pay_tips( - RuntimeOrigin::signed(user_1), + RuntimeOrigin::signed(user_1.clone()), bvec![ - ItemTip { collection: collection_id, item: item_id, receiver: user_2, amount: tip }, - ItemTip { collection: collection_id, item: item_id, receiver: user_3, amount: tip }, + ItemTip { + collection: collection_id, + item: item_id, + receiver: user_2.clone(), + amount: tip + }, + ItemTip { + collection: collection_id, + item: item_id, + receiver: user_3.clone(), + amount: tip + }, ] )); @@ -1919,15 +2388,15 @@ fn pay_tips_should_work() { assert!(events.contains(&Event::::TipSent { collection: collection_id, item: item_id, - sender: user_1, - receiver: user_2, + sender: user_1.clone(), + receiver: user_2.clone(), amount: tip, })); assert!(events.contains(&Event::::TipSent { collection: collection_id, item: item_id, - sender: user_1, - receiver: user_3, + sender: user_1.clone(), + receiver: user_3.clone(), amount: tip, })); }); @@ -1937,7 +2406,7 @@ fn pay_tips_should_work() { fn create_cancel_swap_should_work() { new_test_ext().execute_with(|| { System::set_block_number(1); - let user_id = 1; + let user_id = account(1); let collection_id = 0; let item_1 = 1; let item_2 = 2; @@ -1947,27 +2416,31 @@ fn create_cancel_swap_should_work() { let duration = 2; let expect_deadline = 3; - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), user_id, default_collection_config())); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + user_id.clone(), + default_collection_config() + )); assert_ok!(Nfts::mint( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, item_1, - user_id, + user_id.clone(), None, )); assert_ok!(Nfts::mint( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, item_2, - user_id, + user_id.clone(), None, )); // validate desired item and the collection exists assert_noop!( Nfts::create_swap( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, item_1, collection_id, @@ -1979,7 +2452,7 @@ fn create_cancel_swap_should_work() { ); assert_noop!( Nfts::create_swap( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, item_1, collection_id + 1, @@ -1993,7 +2466,7 @@ fn create_cancel_swap_should_work() { let max_duration: u64 = ::MaxDeadlineDuration::get(); assert_noop!( Nfts::create_swap( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, item_1, collection_id, @@ -2005,7 +2478,7 @@ fn create_cancel_swap_should_work() { ); assert_ok!(Nfts::create_swap( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, item_1, collection_id, @@ -2030,7 +2503,11 @@ fn create_cancel_swap_should_work() { })); // validate we can cancel the swap - assert_ok!(Nfts::cancel_swap(RuntimeOrigin::signed(user_id), collection_id, item_1)); + assert_ok!(Nfts::cancel_swap( + RuntimeOrigin::signed(user_id.clone()), + collection_id, + item_1 + )); assert!(events().contains(&Event::::SwapCancelled { offered_collection: collection_id, offered_item: item_1, @@ -2043,7 +2520,7 @@ fn create_cancel_swap_should_work() { // validate anyone can cancel the expired swap assert_ok!(Nfts::create_swap( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, item_1, collection_id, @@ -2052,11 +2529,11 @@ fn create_cancel_swap_should_work() { duration, )); assert_noop!( - Nfts::cancel_swap(RuntimeOrigin::signed(user_id + 1), collection_id, item_1), + Nfts::cancel_swap(RuntimeOrigin::signed(account(2)), collection_id, item_1), Error::::NoPermission ); System::set_block_number(expect_deadline + 1); - assert_ok!(Nfts::cancel_swap(RuntimeOrigin::signed(user_id + 1), collection_id, item_1)); + assert_ok!(Nfts::cancel_swap(RuntimeOrigin::signed(account(2)), collection_id, item_1)); // validate optional desired_item param assert_ok!(Nfts::create_swap( @@ -2078,8 +2555,8 @@ fn create_cancel_swap_should_work() { fn claim_swap_should_work() { new_test_ext().execute_with(|| { System::set_block_number(1); - let user_1 = 1; - let user_2 = 2; + let user_1 = account(1); + let user_2 = account(2); let collection_id = 0; let item_1 = 1; let item_2 = 2; @@ -2097,45 +2574,46 @@ fn claim_swap_should_work() { Balances::make_free_balance_be(&user_1, initial_balance); Balances::make_free_balance_be(&user_2, initial_balance); - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), user_1, default_collection_config())); + assert_ok!(Nfts::force_create(RuntimeOrigin::root(), user_1.clone(), default_collection_config())); assert_ok!(Nfts::mint( - RuntimeOrigin::signed(user_1), + RuntimeOrigin::signed(user_1.clone()), collection_id, - item_1,user_1, + item_1, + user_1.clone(), None, )); assert_ok!(Nfts::force_mint( - RuntimeOrigin::signed(user_1), + RuntimeOrigin::signed(user_1.clone()), collection_id, item_2, - user_2, + user_2.clone(), default_item_config(), )); assert_ok!(Nfts::force_mint( - RuntimeOrigin::signed(user_1), + RuntimeOrigin::signed(user_1.clone()), collection_id, item_3, - user_2, + user_2.clone(), default_item_config(), )); assert_ok!(Nfts::mint( - RuntimeOrigin::signed(user_1), + RuntimeOrigin::signed(user_1.clone()), collection_id, item_4, - user_1, + user_1.clone(), None, )); assert_ok!(Nfts::force_mint( - RuntimeOrigin::signed(user_1), + RuntimeOrigin::signed(user_1.clone()), collection_id, item_5, - user_2, + user_2.clone(), default_item_config(), )); assert_ok!(Nfts::create_swap( - RuntimeOrigin::signed(user_1), + RuntimeOrigin::signed(user_1.clone()), collection_id, item_1, collection_id, @@ -2148,7 +2626,7 @@ fn claim_swap_should_work() { System::set_block_number(5); assert_noop!( Nfts::claim_swap( - RuntimeOrigin::signed(user_2), + RuntimeOrigin::signed(user_2.clone()), collection_id, item_2, collection_id, @@ -2162,7 +2640,7 @@ fn claim_swap_should_work() { // validate edge cases assert_noop!( Nfts::claim_swap( - RuntimeOrigin::signed(user_2), + RuntimeOrigin::signed(user_2.clone()), collection_id, item_2, collection_id, @@ -2173,7 +2651,7 @@ fn claim_swap_should_work() { ); assert_noop!( Nfts::claim_swap( - RuntimeOrigin::signed(user_2), + RuntimeOrigin::signed(user_2.clone()), collection_id, item_4, // not my item collection_id, @@ -2184,7 +2662,7 @@ fn claim_swap_should_work() { ); assert_noop!( Nfts::claim_swap( - RuntimeOrigin::signed(user_2), + RuntimeOrigin::signed(user_2.clone()), collection_id, item_5, // my item, but not the one another part wants collection_id, @@ -2195,7 +2673,7 @@ fn claim_swap_should_work() { ); assert_noop!( Nfts::claim_swap( - RuntimeOrigin::signed(user_2), + RuntimeOrigin::signed(user_2.clone()), collection_id, item_2, collection_id, @@ -2206,7 +2684,7 @@ fn claim_swap_should_work() { ); assert_noop!( Nfts::claim_swap( - RuntimeOrigin::signed(user_2), + RuntimeOrigin::signed(user_2.clone()), collection_id, item_2, collection_id, @@ -2217,7 +2695,7 @@ fn claim_swap_should_work() { ); assert_ok!(Nfts::claim_swap( - RuntimeOrigin::signed(user_2), + RuntimeOrigin::signed(user_2.clone()), collection_id, item_2, collection_id, @@ -2227,9 +2705,9 @@ fn claim_swap_should_work() { // validate the new owner let item = Item::::get(collection_id, item_1).unwrap(); - assert_eq!(item.owner, user_2); + assert_eq!(item.owner, user_2.clone()); let item = Item::::get(collection_id, item_2).unwrap(); - assert_eq!(item.owner, user_1); + assert_eq!(item.owner, user_1.clone()); // validate the balances assert_eq!(Balances::total_balance(&user_1), initial_balance + price); @@ -2242,10 +2720,10 @@ fn claim_swap_should_work() { assert!(events().contains(&Event::::SwapClaimed { sent_collection: collection_id, sent_item: item_2, - sent_item_owner: user_2, + sent_item_owner: user_2.clone(), received_collection: collection_id, received_item: item_1, - received_item_owner: user_1, + received_item_owner: user_1.clone(), price: Some(price_with_direction.clone()), deadline, })); @@ -2257,7 +2735,7 @@ fn claim_swap_should_work() { Balances::make_free_balance_be(&user_2, initial_balance); assert_ok!(Nfts::create_swap( - RuntimeOrigin::signed(user_1), + RuntimeOrigin::signed(user_1.clone()), collection_id, item_4, collection_id, @@ -2266,7 +2744,7 @@ fn claim_swap_should_work() { duration, )); assert_ok!(Nfts::claim_swap( - RuntimeOrigin::signed(user_2), + RuntimeOrigin::signed(user_2.clone()), collection_id, item_1, collection_id, @@ -2289,7 +2767,7 @@ fn various_collection_settings() { // when we set only one value it's required to call .into() on it let config = collection_config_from_disabled_settings(CollectionSetting::TransferableItems.into()); - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 1, config)); + assert_ok!(Nfts::force_create(RuntimeOrigin::root(), account(1), config)); let config = CollectionConfigOf::::get(0).unwrap(); assert!(!config.is_setting_enabled(CollectionSetting::TransferableItems)); @@ -2299,25 +2777,29 @@ fn various_collection_settings() { let config = collection_config_from_disabled_settings( CollectionSetting::UnlockedMetadata | CollectionSetting::TransferableItems, ); - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 1, config)); + assert_ok!(Nfts::force_create(RuntimeOrigin::root(), account(1), config)); let config = CollectionConfigOf::::get(1).unwrap(); assert!(!config.is_setting_enabled(CollectionSetting::TransferableItems)); assert!(!config.is_setting_enabled(CollectionSetting::UnlockedMetadata)); - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), 1, default_collection_config())); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); }); } #[test] fn collection_locking_should_work() { new_test_ext().execute_with(|| { - let user_id = 1; + let user_id = account(1); let collection_id = 0; assert_ok!(Nfts::force_create( RuntimeOrigin::root(), - user_id, + user_id.clone(), collection_config_with_all_settings_enabled() )); @@ -2325,7 +2807,7 @@ fn collection_locking_should_work() { collection_config_from_disabled_settings(CollectionSetting::DepositRequired.into()); assert_noop!( Nfts::lock_collection( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, lock_config.settings, ), @@ -2337,7 +2819,7 @@ fn collection_locking_should_work() { CollectionSetting::TransferableItems | CollectionSetting::UnlockedAttributes, ); assert_ok!(Nfts::lock_collection( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, lock_config.settings, )); @@ -2369,33 +2851,49 @@ fn pallet_level_feature_flags_should_work() { PalletFeature::Trading | PalletFeature::Approvals | PalletFeature::Attributes, )); - let user_id = 1; + let user_id = account(1); let collection_id = 0; let item_id = 1; - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), user_id, default_collection_config())); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + user_id.clone(), + default_collection_config() + )); assert_ok!(Nfts::mint( - RuntimeOrigin::signed(user_id), + RuntimeOrigin::signed(user_id.clone()), collection_id, item_id, - user_id, + user_id.clone(), None, )); // PalletFeature::Trading assert_noop!( - Nfts::set_price(RuntimeOrigin::signed(user_id), collection_id, item_id, Some(1), None), + Nfts::set_price( + RuntimeOrigin::signed(user_id.clone()), + collection_id, + item_id, + Some(1), + None + ), Error::::MethodDisabled ); assert_noop!( - Nfts::buy_item(RuntimeOrigin::signed(user_id), collection_id, item_id, 1), + Nfts::buy_item(RuntimeOrigin::signed(user_id.clone()), collection_id, item_id, 1), Error::::MethodDisabled ); // PalletFeature::Approvals assert_noop!( - Nfts::approve_transfer(RuntimeOrigin::signed(user_id), collection_id, item_id, 2, None), + Nfts::approve_transfer( + RuntimeOrigin::signed(user_id.clone()), + collection_id, + item_id, + account(2), + None + ), Error::::MethodDisabled ); @@ -2420,25 +2918,25 @@ fn group_roles_by_account_should_work() { assert_eq!(Nfts::group_roles_by_account(vec![]), vec![]); let account_to_role = Nfts::group_roles_by_account(vec![ - (3, CollectionRole::Freezer), - (1, CollectionRole::Issuer), - (2, CollectionRole::Admin), + (account(3), CollectionRole::Freezer), + (account(1), CollectionRole::Issuer), + (account(2), CollectionRole::Admin), ]); let expect = vec![ - (1, CollectionRoles(CollectionRole::Issuer.into())), - (2, CollectionRoles(CollectionRole::Admin.into())), - (3, CollectionRoles(CollectionRole::Freezer.into())), + (account(1), CollectionRoles(CollectionRole::Issuer.into())), + (account(2), CollectionRoles(CollectionRole::Admin.into())), + (account(3), CollectionRoles(CollectionRole::Freezer.into())), ]; assert_eq!(account_to_role, expect); let account_to_role = Nfts::group_roles_by_account(vec![ - (3, CollectionRole::Freezer), - (2, CollectionRole::Issuer), - (2, CollectionRole::Admin), + (account(3), CollectionRole::Freezer), + (account(2), CollectionRole::Issuer), + (account(2), CollectionRole::Admin), ]); let expect = vec![ - (2, CollectionRoles(CollectionRole::Issuer | CollectionRole::Admin)), - (3, CollectionRoles(CollectionRole::Freezer.into())), + (account(2), CollectionRoles(CollectionRole::Issuer | CollectionRole::Admin)), + (account(3), CollectionRoles(CollectionRole::Freezer.into())), ]; assert_eq!(account_to_role, expect); }) @@ -2447,40 +2945,53 @@ fn group_roles_by_account_should_work() { #[test] fn add_remove_item_attributes_approval_should_work() { new_test_ext().execute_with(|| { - let user_1 = 1; - let user_2 = 2; - let user_3 = 3; - let user_4 = 4; + let user_1 = account(1); + let user_2 = account(2); + let user_3 = account(3); + let user_4 = account(4); let collection_id = 0; let item_id = 0; - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), user_1, default_collection_config())); - assert_ok!(Nfts::mint(RuntimeOrigin::signed(user_1), collection_id, item_id, user_1, None)); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + user_1.clone(), + default_collection_config() + )); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(user_1.clone()), + collection_id, + item_id, + user_1.clone(), + None + )); assert_ok!(Nfts::approve_item_attributes( - RuntimeOrigin::signed(user_1), + RuntimeOrigin::signed(user_1.clone()), collection_id, item_id, - user_2, + user_2.clone(), )); - assert_eq!(item_attributes_approvals(collection_id, item_id), vec![user_2]); + assert_eq!(item_attributes_approvals(collection_id, item_id), vec![user_2.clone()]); assert_ok!(Nfts::approve_item_attributes( - RuntimeOrigin::signed(user_1), + RuntimeOrigin::signed(user_1.clone()), collection_id, item_id, - user_3, + user_3.clone(), )); assert_ok!(Nfts::approve_item_attributes( - RuntimeOrigin::signed(user_1), + RuntimeOrigin::signed(user_1.clone()), collection_id, item_id, - user_2, + user_2.clone(), )); - assert_eq!(item_attributes_approvals(collection_id, item_id), vec![user_2, user_3]); + assert_eq!( + item_attributes_approvals(collection_id, item_id), + vec![user_2.clone(), user_3.clone()] + ); assert_noop!( Nfts::approve_item_attributes( - RuntimeOrigin::signed(user_1), + RuntimeOrigin::signed(user_1.clone()), collection_id, item_id, user_4, @@ -2498,3 +3009,170 @@ fn add_remove_item_attributes_approval_should_work() { assert_eq!(item_attributes_approvals(collection_id, item_id), vec![user_3]); }) } + +#[test] +fn pre_signed_mints_should_work() { + new_test_ext().execute_with(|| { + let user_1_pair = sp_core::sr25519::Pair::from_string("//Alice", None).unwrap(); + let user_1_signer = MultiSigner::Sr25519(user_1_pair.public()); + let user_1 = user_1_signer.clone().into_account(); + let mint_data = PreSignedMint { + collection: 0, + item: 0, + attributes: vec![(vec![0], vec![1]), (vec![2], vec![3])], + metadata: vec![0, 1], + only_account: None, + deadline: 10000000, + }; + let message = Encode::encode(&mint_data); + let signature = MultiSignature::Sr25519(user_1_pair.sign(&message)); + let user_2 = account(2); + let user_3 = account(3); + + Balances::make_free_balance_be(&user_1, 100); + Balances::make_free_balance_be(&user_2, 100); + assert_ok!(Nfts::create( + RuntimeOrigin::signed(user_1.clone()), + user_1.clone(), + collection_config_with_all_settings_enabled(), + )); + + assert_ok!(Nfts::mint_pre_signed( + RuntimeOrigin::signed(user_2.clone()), + mint_data.clone(), + signature.clone(), + user_1.clone(), + )); + assert_eq!(items(), vec![(user_2.clone(), 0, 0)]); + let metadata = ItemMetadataOf::::get(0, 0).unwrap(); + assert_eq!( + metadata.deposit, + ItemMetadataDeposit { account: Some(user_2.clone()), amount: 3 } + ); + assert_eq!(metadata.data, vec![0, 1]); + + assert_eq!( + attributes(0), + vec![ + (Some(0), AttributeNamespace::CollectionOwner, bvec![0], bvec![1]), + (Some(0), AttributeNamespace::CollectionOwner, bvec![2], bvec![3]), + ] + ); + let attribute_key: BoundedVec<_, _> = bvec![0]; + let (_, deposit) = Attribute::::get(( + 0, + Some(0), + AttributeNamespace::CollectionOwner, + &attribute_key, + )) + .unwrap(); + assert_eq!(deposit.account, Some(user_2.clone())); + assert_eq!(deposit.amount, 3); + + assert_eq!(Balances::free_balance(&user_1), 100 - 2); // 2 - collection deposit + assert_eq!(Balances::free_balance(&user_2), 100 - 1 - 3 - 6); // 1 - item deposit, 3 - metadata, 6 - attributes + + assert_noop!( + Nfts::mint_pre_signed( + RuntimeOrigin::signed(user_2.clone()), + mint_data, + signature.clone(), + user_1.clone(), + ), + Error::::AlreadyExists + ); + + assert_ok!(Nfts::burn(RuntimeOrigin::signed(user_2.clone()), 0, 0, Some(user_2.clone()))); + assert_eq!(Balances::free_balance(&user_2), 100 - 6); + + // validate the `only_account` field + let mint_data = PreSignedMint { + collection: 0, + item: 0, + attributes: vec![], + metadata: vec![], + only_account: Some(account(2)), + deadline: 10000000, + }; + + // can't mint with the wrong signature + assert_noop!( + Nfts::mint_pre_signed( + RuntimeOrigin::signed(user_2.clone()), + mint_data.clone(), + signature.clone(), + user_1.clone(), + ), + Error::::WrongSignature + ); + + let message = Encode::encode(&mint_data); + let signature = MultiSignature::Sr25519(user_1_pair.sign(&message)); + + assert_noop!( + Nfts::mint_pre_signed( + RuntimeOrigin::signed(user_3), + mint_data.clone(), + signature.clone(), + user_1.clone(), + ), + Error::::WrongOrigin + ); + + // validate signature's expiration + System::set_block_number(10000001); + assert_noop!( + Nfts::mint_pre_signed( + RuntimeOrigin::signed(user_2.clone()), + mint_data, + signature, + user_1.clone(), + ), + Error::::DeadlineExpired + ); + System::set_block_number(1); + + // validate the collection + let mint_data = PreSignedMint { + collection: 1, + item: 0, + attributes: vec![], + metadata: vec![], + only_account: Some(account(2)), + deadline: 10000000, + }; + let message = Encode::encode(&mint_data); + let signature = MultiSignature::Sr25519(user_1_pair.sign(&message)); + + assert_noop!( + Nfts::mint_pre_signed( + RuntimeOrigin::signed(user_2.clone()), + mint_data, + signature, + user_1.clone(), + ), + Error::::UnknownCollection + ); + + // validate max attributes limit + let mint_data = PreSignedMint { + collection: 0, + item: 0, + attributes: vec![(vec![0], vec![1]), (vec![2], vec![3]), (vec![2], vec![3])], + metadata: vec![0, 1], + only_account: None, + deadline: 10000000, + }; + let message = Encode::encode(&mint_data); + let signature = MultiSignature::Sr25519(user_1_pair.sign(&message)); + assert_noop!( + Nfts::mint_pre_signed( + RuntimeOrigin::signed(user_2), + mint_data, + signature, + user_1.clone(), + ), + Error::::MaxAttributesLimitReached + ); + }) +} diff --git a/frame/nfts/src/types.rs b/frame/nfts/src/types.rs index d8938aab4377a..c2ecd61c23028 100644 --- a/frame/nfts/src/types.rs +++ b/frame/nfts/src/types.rs @@ -61,6 +61,12 @@ pub(super) type CollectionConfigFor = CollectionConfig< ::BlockNumber, >::CollectionId, >; +pub(super) type PreSignedMintOf = PreSignedMint< + >::CollectionId, + >::ItemId, + ::AccountId, + ::BlockNumber, +>; pub trait Incrementable { fn increment(&self) -> Self; @@ -187,7 +193,7 @@ pub struct PendingSwap { pub(super) desired_item: Option, /// A price for the desired `item` with the direction. pub(super) price: Option, - /// An optional deadline for the swap. + /// A deadline for the swap. pub(super) deadline: Deadline, } @@ -473,3 +479,19 @@ impl CollectionRoles { } } impl_codec_bitflags!(CollectionRoles, u8, CollectionRole); + +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct PreSignedMint { + /// A collection of the item to be minted. + pub(super) collection: CollectionId, + /// Item's id. + pub(super) item: ItemId, + /// Additional item's key-value attributes. + pub(super) attributes: Vec<(Vec, Vec)>, + /// Additional item's metadata. + pub(super) metadata: Vec, + /// Restrict the claim to a particular account. + pub(super) only_account: Option, + /// A deadline for the signature. + pub(super) deadline: Deadline, +} diff --git a/frame/nfts/src/weights.rs b/frame/nfts/src/weights.rs index 81be145b67c88..40592c29988ed 100644 --- a/frame/nfts/src/weights.rs +++ b/frame/nfts/src/weights.rs @@ -18,25 +18,26 @@ //! Autogenerated weights for pallet_nfts //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-01-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm2`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! HOSTNAME: `runner-b3zmxxc-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate +// target/production/substrate // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_nfts // --extrinsic=* // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/nfts/src/weights.rs +// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json +// --pallet=pallet_nfts +// --chain=dev // --header=./HEADER-APACHE2 +// --output=./frame/nfts/src/weights.rs // --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -85,6 +86,7 @@ pub trait WeightInfo { fn create_swap() -> Weight; fn cancel_swap() -> Weight; fn claim_swap() -> Weight; + fn mint_pre_signed(n: u32, ) -> Weight; } /// Weights for pallet_nfts using the Substrate node and recommended hardware. @@ -104,8 +106,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `214` // Estimated: `3054` - // Minimum execution time: 32_467 nanoseconds. - Weight::from_parts(33_236_000, 3054) + // Minimum execution time: 33_666 nanoseconds. + Weight::from_parts(34_405_000, 3054) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -123,8 +125,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `42` // Estimated: `3054` - // Minimum execution time: 22_198 nanoseconds. - Weight::from_parts(22_776_000, 3054) + // Minimum execution time: 22_028 nanoseconds. + Weight::from_parts(23_030_000, 3054) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -151,18 +153,16 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 1000]`. /// The range of component `m` is `[0, 1000]`. /// The range of component `a` is `[0, 1000]`. - fn destroy(n: u32, m: u32, a: u32, ) -> Weight { + fn destroy(_n: u32, m: u32, a: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `172781 + m * (127 ±0) + a * (402 ±0)` // Estimated: `3347427 + a * (2921 ±0) + m * (2615 ±0)` - // Minimum execution time: 24_021_657 nanoseconds. - Weight::from_parts(16_029_391_606, 3347427) - // Standard Error: 20_364 - .saturating_add(Weight::from_ref_time(300_580).saturating_mul(n.into())) - // Standard Error: 20_364 - .saturating_add(Weight::from_ref_time(7_748_502).saturating_mul(m.into())) - // Standard Error: 20_364 - .saturating_add(Weight::from_ref_time(9_183_566).saturating_mul(a.into())) + // Minimum execution time: 27_944_985 nanoseconds. + Weight::from_parts(19_865_318_850, 3347427) + // Standard Error: 32_345 + .saturating_add(Weight::from_ref_time(8_729_316).saturating_mul(m.into())) + // Standard Error: 32_345 + .saturating_add(Weight::from_ref_time(10_264_491).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(1004_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into()))) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) @@ -188,8 +188,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `448` // Estimated: `13506` - // Minimum execution time: 42_634 nanoseconds. - Weight::from_parts(43_231_000, 13506) + // Minimum execution time: 43_925 nanoseconds. + Weight::from_parts(45_885_000, 13506) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -209,8 +209,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `448` // Estimated: `13506` - // Minimum execution time: 41_686 nanoseconds. - Weight::from_parts(41_991_000, 13506) + // Minimum execution time: 42_832 nanoseconds. + Weight::from_parts(44_621_000, 13506) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -236,8 +236,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `647` // Estimated: `13573` - // Minimum execution time: 45_192 nanoseconds. - Weight::from_parts(45_792_000, 13573) + // Minimum execution time: 47_787 nanoseconds. + Weight::from_parts(49_204_000, 13573) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } @@ -263,8 +263,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `882` // Estimated: `16109` - // Minimum execution time: 51_962 nanoseconds. - Weight::from_parts(52_367_000, 16109) + // Minimum execution time: 55_524 nanoseconds. + Weight::from_parts(56_962_000, 16109) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -279,10 +279,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `756 + i * (140 ±0)` // Estimated: `5103 + i * (3336 ±0)` - // Minimum execution time: 15_512 nanoseconds. - Weight::from_parts(15_731_000, 5103) - // Standard Error: 9_495 - .saturating_add(Weight::from_ref_time(11_462_413).saturating_mul(i.into())) + // Minimum execution time: 15_246 nanoseconds. + Weight::from_parts(15_671_000, 5103) + // Standard Error: 20_348 + .saturating_add(Weight::from_ref_time(14_692_422).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) @@ -296,8 +296,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `401` // Estimated: `5067` - // Minimum execution time: 19_273 nanoseconds. - Weight::from_parts(19_508_000, 5067) + // Minimum execution time: 19_270 nanoseconds. + Weight::from_parts(19_775_000, 5067) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -309,8 +309,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `401` // Estimated: `5067` - // Minimum execution time: 19_022 nanoseconds. - Weight::from_parts(19_430_000, 5067) + // Minimum execution time: 19_364 nanoseconds. + Weight::from_parts(20_274_000, 5067) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -322,8 +322,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `289` // Estimated: `5092` - // Minimum execution time: 17_593 nanoseconds. - Weight::from_parts(17_950_000, 5092) + // Minimum execution time: 17_036 nanoseconds. + Weight::from_parts(17_750_000, 5092) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -337,8 +337,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `381` // Estimated: `5082` - // Minimum execution time: 22_068 nanoseconds. - Weight::from_parts(22_235_000, 5082) + // Minimum execution time: 22_104 nanoseconds. + Weight::from_parts(23_022_000, 5082) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -350,8 +350,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `362` // Estimated: `2555` - // Minimum execution time: 25_056 nanoseconds. - Weight::from_parts(25_767_000, 2555) + // Minimum execution time: 24_516 nanoseconds. + Weight::from_parts(25_300_000, 2555) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -363,8 +363,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `304` // Estimated: `2555` - // Minimum execution time: 17_398 nanoseconds. - Weight::from_parts(17_684_000, 2555) + // Minimum execution time: 16_974 nanoseconds. + Weight::from_parts(17_654_000, 2555) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -376,8 +376,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `242` // Estimated: `2555` - // Minimum execution time: 14_054 nanoseconds. - Weight::from_parts(14_243_000, 2555) + // Minimum execution time: 13_190 nanoseconds. + Weight::from_parts(13_826_000, 2555) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -389,8 +389,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `445` // Estimated: `5078` - // Minimum execution time: 17_662 nanoseconds. - Weight::from_parts(18_073_000, 5078) + // Minimum execution time: 17_336 nanoseconds. + Weight::from_parts(18_242_000, 5078) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -406,8 +406,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `474` // Estimated: `10547` - // Minimum execution time: 40_098 nanoseconds. - Weight::from_parts(40_649_000, 10547) + // Minimum execution time: 40_791 nanoseconds. + Weight::from_parts(42_489_000, 10547) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -419,8 +419,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `337` // Estimated: `5476` - // Minimum execution time: 25_178 nanoseconds. - Weight::from_parts(25_473_000, 5476) + // Minimum execution time: 24_620 nanoseconds. + Weight::from_parts(25_370_000, 5476) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -434,8 +434,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `916` // Estimated: `7999` - // Minimum execution time: 35_202 nanoseconds. - Weight::from_parts(35_518_000, 7999) + // Minimum execution time: 36_411 nanoseconds. + Weight::from_parts(37_439_000, 7999) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -447,8 +447,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `379` // Estimated: `6492` - // Minimum execution time: 17_260 nanoseconds. - Weight::from_parts(17_498_000, 6492) + // Minimum execution time: 16_696 nanoseconds. + Weight::from_parts(17_411_000, 6492) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -463,12 +463,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 1000]`. fn cancel_item_attributes_approval(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `865 + n * (367 ±0)` + // Measured: `899 + n * (396 ±0)` // Estimated: `12016 + n * (2921 ±0)` - // Minimum execution time: 25_579 nanoseconds. - Weight::from_parts(25_846_000, 12016) - // Standard Error: 7_759 - .saturating_add(Weight::from_ref_time(7_159_200).saturating_mul(n.into())) + // Minimum execution time: 25_928 nanoseconds. + Weight::from_parts(26_440_000, 12016) + // Standard Error: 9_158 + .saturating_add(Weight::from_ref_time(9_271_441).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -487,8 +487,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `474` // Estimated: `10241` - // Minimum execution time: 33_285 nanoseconds. - Weight::from_parts(33_692_000, 10241) + // Minimum execution time: 34_150 nanoseconds. + Weight::from_parts(35_398_000, 10241) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -502,8 +502,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `609` // Estimated: `7693` - // Minimum execution time: 30_670 nanoseconds. - Weight::from_parts(31_282_000, 7693) + // Minimum execution time: 31_871 nanoseconds. + Weight::from_parts(33_057_000, 7693) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -517,8 +517,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `333` // Estimated: `7665` - // Minimum execution time: 28_313 nanoseconds. - Weight::from_parts(28_724_000, 7665) + // Minimum execution time: 28_843 nanoseconds. + Weight::from_parts(30_057_000, 7665) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -532,8 +532,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `476` // Estimated: `7665` - // Minimum execution time: 27_034 nanoseconds. - Weight::from_parts(27_655_000, 7665) + // Minimum execution time: 27_777 nanoseconds. + Weight::from_parts(28_471_000, 7665) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -547,8 +547,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `466` // Estimated: `8428` - // Minimum execution time: 23_408 nanoseconds. - Weight::from_parts(23_916_000, 8428) + // Minimum execution time: 23_726 nanoseconds. + Weight::from_parts(24_455_000, 8428) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -560,8 +560,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `474` // Estimated: `5880` - // Minimum execution time: 21_177 nanoseconds. - Weight::from_parts(21_492_000, 5880) + // Minimum execution time: 21_051 nanoseconds. + Weight::from_parts(21_722_000, 5880) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -573,8 +573,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `474` // Estimated: `5880` - // Minimum execution time: 20_279 nanoseconds. - Weight::from_parts(20_919_000, 5880) + // Minimum execution time: 20_095 nanoseconds. + Weight::from_parts(20_770_000, 5880) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -584,8 +584,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `42` // Estimated: `2527` - // Minimum execution time: 14_921 nanoseconds. - Weight::from_parts(15_382_000, 2527) + // Minimum execution time: 14_078 nanoseconds. + Weight::from_parts(14_582_000, 2527) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -597,8 +597,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `333` // Estimated: `5103` - // Minimum execution time: 18_201 nanoseconds. - Weight::from_parts(18_628_000, 5103) + // Minimum execution time: 17_677 nanoseconds. + Weight::from_parts(18_381_000, 5103) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -610,8 +610,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `333` // Estimated: `5103` - // Minimum execution time: 16_870 nanoseconds. - Weight::from_parts(17_318_000, 5103) + // Minimum execution time: 16_295 nanoseconds. + Weight::from_parts(17_036_000, 5103) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -627,8 +627,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `516` // Estimated: `8407` - // Minimum execution time: 22_604 nanoseconds. - Weight::from_parts(22_867_000, 8407) + // Minimum execution time: 22_847 nanoseconds. + Weight::from_parts(23_536_000, 8407) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -652,8 +652,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `934` // Estimated: `16129` - // Minimum execution time: 56_849 nanoseconds. - Weight::from_parts(57_336_000, 16129) + // Minimum execution time: 60_517 nanoseconds. + Weight::from_parts(62_528_000, 16129) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -662,10 +662,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_308 nanoseconds. - Weight::from_ref_time(4_805_401) - // Standard Error: 13_875 - .saturating_add(Weight::from_ref_time(3_167_190).saturating_mul(n.into())) + // Minimum execution time: 1_866 nanoseconds. + Weight::from_ref_time(3_949_301) + // Standard Error: 11_044 + .saturating_add(Weight::from_ref_time(3_424_466).saturating_mul(n.into())) } /// Storage: Nfts Item (r:2 w:0) /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) @@ -675,8 +675,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `524` // Estimated: `6672` - // Minimum execution time: 20_395 nanoseconds. - Weight::from_parts(20_716_000, 6672) + // Minimum execution time: 21_174 nanoseconds. + Weight::from_parts(21_619_000, 6672) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -688,8 +688,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `511` // Estimated: `5882` - // Minimum execution time: 19_936 nanoseconds. - Weight::from_parts(20_344_000, 5882) + // Minimum execution time: 20_606 nanoseconds. + Weight::from_parts(21_150_000, 5882) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -713,11 +713,42 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1097` // Estimated: `21970` - // Minimum execution time: 80_884 nanoseconds. - Weight::from_parts(81_643_000, 21970) + // Minimum execution time: 88_414 nanoseconds. + Weight::from_parts(91_830_000, 21970) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(11_u64)) } + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:1) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:10 w:10) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: Nfts ItemMetadataOf (r:1 w:1) + /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: Nfts Account (r:0 w:1) + /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + /// The range of component `n` is `[0, 10]`. + fn mint_pre_signed(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `596` + // Estimated: `16180 + n * (2921 ±0)` + // Minimum execution time: 124_354 nanoseconds. + Weight::from_parts(133_779_491, 16180) + // Standard Error: 38_452 + .saturating_add(Weight::from_ref_time(25_110_697).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(6_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_proof_size(2921).saturating_mul(n.into())) + } } // For backwards compatibility and tests @@ -736,8 +767,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `214` // Estimated: `3054` - // Minimum execution time: 32_467 nanoseconds. - Weight::from_parts(33_236_000, 3054) + // Minimum execution time: 33_666 nanoseconds. + Weight::from_parts(34_405_000, 3054) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -755,8 +786,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `42` // Estimated: `3054` - // Minimum execution time: 22_198 nanoseconds. - Weight::from_parts(22_776_000, 3054) + // Minimum execution time: 22_028 nanoseconds. + Weight::from_parts(23_030_000, 3054) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -783,18 +814,16 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 1000]`. /// The range of component `m` is `[0, 1000]`. /// The range of component `a` is `[0, 1000]`. - fn destroy(n: u32, m: u32, a: u32, ) -> Weight { + fn destroy(_n: u32, m: u32, a: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `172781 + m * (127 ±0) + a * (402 ±0)` // Estimated: `3347427 + a * (2921 ±0) + m * (2615 ±0)` - // Minimum execution time: 24_021_657 nanoseconds. - Weight::from_parts(16_029_391_606, 3347427) - // Standard Error: 20_364 - .saturating_add(Weight::from_ref_time(300_580).saturating_mul(n.into())) - // Standard Error: 20_364 - .saturating_add(Weight::from_ref_time(7_748_502).saturating_mul(m.into())) - // Standard Error: 20_364 - .saturating_add(Weight::from_ref_time(9_183_566).saturating_mul(a.into())) + // Minimum execution time: 27_944_985 nanoseconds. + Weight::from_parts(19_865_318_850, 3347427) + // Standard Error: 32_345 + .saturating_add(Weight::from_ref_time(8_729_316).saturating_mul(m.into())) + // Standard Error: 32_345 + .saturating_add(Weight::from_ref_time(10_264_491).saturating_mul(a.into())) .saturating_add(RocksDbWeight::get().reads(1004_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(m.into()))) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(a.into()))) @@ -820,8 +849,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `448` // Estimated: `13506` - // Minimum execution time: 42_634 nanoseconds. - Weight::from_parts(43_231_000, 13506) + // Minimum execution time: 43_925 nanoseconds. + Weight::from_parts(45_885_000, 13506) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -841,8 +870,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `448` // Estimated: `13506` - // Minimum execution time: 41_686 nanoseconds. - Weight::from_parts(41_991_000, 13506) + // Minimum execution time: 42_832 nanoseconds. + Weight::from_parts(44_621_000, 13506) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -868,8 +897,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `647` // Estimated: `13573` - // Minimum execution time: 45_192 nanoseconds. - Weight::from_parts(45_792_000, 13573) + // Minimum execution time: 47_787 nanoseconds. + Weight::from_parts(49_204_000, 13573) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } @@ -895,8 +924,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `882` // Estimated: `16109` - // Minimum execution time: 51_962 nanoseconds. - Weight::from_parts(52_367_000, 16109) + // Minimum execution time: 55_524 nanoseconds. + Weight::from_parts(56_962_000, 16109) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } @@ -911,10 +940,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `756 + i * (140 ±0)` // Estimated: `5103 + i * (3336 ±0)` - // Minimum execution time: 15_512 nanoseconds. - Weight::from_parts(15_731_000, 5103) - // Standard Error: 9_495 - .saturating_add(Weight::from_ref_time(11_462_413).saturating_mul(i.into())) + // Minimum execution time: 15_246 nanoseconds. + Weight::from_parts(15_671_000, 5103) + // Standard Error: 20_348 + .saturating_add(Weight::from_ref_time(14_692_422).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(i.into()))) @@ -928,8 +957,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `401` // Estimated: `5067` - // Minimum execution time: 19_273 nanoseconds. - Weight::from_parts(19_508_000, 5067) + // Minimum execution time: 19_270 nanoseconds. + Weight::from_parts(19_775_000, 5067) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -941,8 +970,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `401` // Estimated: `5067` - // Minimum execution time: 19_022 nanoseconds. - Weight::from_parts(19_430_000, 5067) + // Minimum execution time: 19_364 nanoseconds. + Weight::from_parts(20_274_000, 5067) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -954,8 +983,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `289` // Estimated: `5092` - // Minimum execution time: 17_593 nanoseconds. - Weight::from_parts(17_950_000, 5092) + // Minimum execution time: 17_036 nanoseconds. + Weight::from_parts(17_750_000, 5092) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -969,8 +998,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `381` // Estimated: `5082` - // Minimum execution time: 22_068 nanoseconds. - Weight::from_parts(22_235_000, 5082) + // Minimum execution time: 22_104 nanoseconds. + Weight::from_parts(23_022_000, 5082) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -982,8 +1011,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `362` // Estimated: `2555` - // Minimum execution time: 25_056 nanoseconds. - Weight::from_parts(25_767_000, 2555) + // Minimum execution time: 24_516 nanoseconds. + Weight::from_parts(25_300_000, 2555) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -995,8 +1024,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `304` // Estimated: `2555` - // Minimum execution time: 17_398 nanoseconds. - Weight::from_parts(17_684_000, 2555) + // Minimum execution time: 16_974 nanoseconds. + Weight::from_parts(17_654_000, 2555) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -1008,8 +1037,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `242` // Estimated: `2555` - // Minimum execution time: 14_054 nanoseconds. - Weight::from_parts(14_243_000, 2555) + // Minimum execution time: 13_190 nanoseconds. + Weight::from_parts(13_826_000, 2555) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1021,8 +1050,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `445` // Estimated: `5078` - // Minimum execution time: 17_662 nanoseconds. - Weight::from_parts(18_073_000, 5078) + // Minimum execution time: 17_336 nanoseconds. + Weight::from_parts(18_242_000, 5078) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1038,8 +1067,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `474` // Estimated: `10547` - // Minimum execution time: 40_098 nanoseconds. - Weight::from_parts(40_649_000, 10547) + // Minimum execution time: 40_791 nanoseconds. + Weight::from_parts(42_489_000, 10547) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1051,8 +1080,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `337` // Estimated: `5476` - // Minimum execution time: 25_178 nanoseconds. - Weight::from_parts(25_473_000, 5476) + // Minimum execution time: 24_620 nanoseconds. + Weight::from_parts(25_370_000, 5476) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1066,8 +1095,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `916` // Estimated: `7999` - // Minimum execution time: 35_202 nanoseconds. - Weight::from_parts(35_518_000, 7999) + // Minimum execution time: 36_411 nanoseconds. + Weight::from_parts(37_439_000, 7999) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1079,8 +1108,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `379` // Estimated: `6492` - // Minimum execution time: 17_260 nanoseconds. - Weight::from_parts(17_498_000, 6492) + // Minimum execution time: 16_696 nanoseconds. + Weight::from_parts(17_411_000, 6492) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1095,12 +1124,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 1000]`. fn cancel_item_attributes_approval(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `865 + n * (367 ±0)` + // Measured: `899 + n * (396 ±0)` // Estimated: `12016 + n * (2921 ±0)` - // Minimum execution time: 25_579 nanoseconds. - Weight::from_parts(25_846_000, 12016) - // Standard Error: 7_759 - .saturating_add(Weight::from_ref_time(7_159_200).saturating_mul(n.into())) + // Minimum execution time: 25_928 nanoseconds. + Weight::from_parts(26_440_000, 12016) + // Standard Error: 9_158 + .saturating_add(Weight::from_ref_time(9_271_441).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -1119,8 +1148,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `474` // Estimated: `10241` - // Minimum execution time: 33_285 nanoseconds. - Weight::from_parts(33_692_000, 10241) + // Minimum execution time: 34_150 nanoseconds. + Weight::from_parts(35_398_000, 10241) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1134,8 +1163,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `609` // Estimated: `7693` - // Minimum execution time: 30_670 nanoseconds. - Weight::from_parts(31_282_000, 7693) + // Minimum execution time: 31_871 nanoseconds. + Weight::from_parts(33_057_000, 7693) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1149,8 +1178,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `333` // Estimated: `7665` - // Minimum execution time: 28_313 nanoseconds. - Weight::from_parts(28_724_000, 7665) + // Minimum execution time: 28_843 nanoseconds. + Weight::from_parts(30_057_000, 7665) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1164,8 +1193,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `476` // Estimated: `7665` - // Minimum execution time: 27_034 nanoseconds. - Weight::from_parts(27_655_000, 7665) + // Minimum execution time: 27_777 nanoseconds. + Weight::from_parts(28_471_000, 7665) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1179,8 +1208,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `466` // Estimated: `8428` - // Minimum execution time: 23_408 nanoseconds. - Weight::from_parts(23_916_000, 8428) + // Minimum execution time: 23_726 nanoseconds. + Weight::from_parts(24_455_000, 8428) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1192,8 +1221,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `474` // Estimated: `5880` - // Minimum execution time: 21_177 nanoseconds. - Weight::from_parts(21_492_000, 5880) + // Minimum execution time: 21_051 nanoseconds. + Weight::from_parts(21_722_000, 5880) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1205,8 +1234,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `474` // Estimated: `5880` - // Minimum execution time: 20_279 nanoseconds. - Weight::from_parts(20_919_000, 5880) + // Minimum execution time: 20_095 nanoseconds. + Weight::from_parts(20_770_000, 5880) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1216,8 +1245,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `42` // Estimated: `2527` - // Minimum execution time: 14_921 nanoseconds. - Weight::from_parts(15_382_000, 2527) + // Minimum execution time: 14_078 nanoseconds. + Weight::from_parts(14_582_000, 2527) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1229,8 +1258,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `333` // Estimated: `5103` - // Minimum execution time: 18_201 nanoseconds. - Weight::from_parts(18_628_000, 5103) + // Minimum execution time: 17_677 nanoseconds. + Weight::from_parts(18_381_000, 5103) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1242,8 +1271,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `333` // Estimated: `5103` - // Minimum execution time: 16_870 nanoseconds. - Weight::from_parts(17_318_000, 5103) + // Minimum execution time: 16_295 nanoseconds. + Weight::from_parts(17_036_000, 5103) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1259,8 +1288,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `516` // Estimated: `8407` - // Minimum execution time: 22_604 nanoseconds. - Weight::from_parts(22_867_000, 8407) + // Minimum execution time: 22_847 nanoseconds. + Weight::from_parts(23_536_000, 8407) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1284,8 +1313,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `934` // Estimated: `16129` - // Minimum execution time: 56_849 nanoseconds. - Weight::from_parts(57_336_000, 16129) + // Minimum execution time: 60_517 nanoseconds. + Weight::from_parts(62_528_000, 16129) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } @@ -1294,10 +1323,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_308 nanoseconds. - Weight::from_ref_time(4_805_401) - // Standard Error: 13_875 - .saturating_add(Weight::from_ref_time(3_167_190).saturating_mul(n.into())) + // Minimum execution time: 1_866 nanoseconds. + Weight::from_ref_time(3_949_301) + // Standard Error: 11_044 + .saturating_add(Weight::from_ref_time(3_424_466).saturating_mul(n.into())) } /// Storage: Nfts Item (r:2 w:0) /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) @@ -1307,8 +1336,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `524` // Estimated: `6672` - // Minimum execution time: 20_395 nanoseconds. - Weight::from_parts(20_716_000, 6672) + // Minimum execution time: 21_174 nanoseconds. + Weight::from_parts(21_619_000, 6672) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1320,8 +1349,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `511` // Estimated: `5882` - // Minimum execution time: 19_936 nanoseconds. - Weight::from_parts(20_344_000, 5882) + // Minimum execution time: 20_606 nanoseconds. + Weight::from_parts(21_150_000, 5882) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1345,9 +1374,40 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1097` // Estimated: `21970` - // Minimum execution time: 80_884 nanoseconds. - Weight::from_parts(81_643_000, 21970) + // Minimum execution time: 88_414 nanoseconds. + Weight::from_parts(91_830_000, 21970) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(11_u64)) } + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:1) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:10 w:10) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: Nfts ItemMetadataOf (r:1 w:1) + /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: Nfts Account (r:0 w:1) + /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + /// The range of component `n` is `[0, 10]`. + fn mint_pre_signed(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `596` + // Estimated: `16180 + n * (2921 ±0)` + // Minimum execution time: 124_354 nanoseconds. + Weight::from_parts(133_779_491, 16180) + // Standard Error: 38_452 + .saturating_add(Weight::from_ref_time(25_110_697).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(RocksDbWeight::get().writes(6_u64)) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_proof_size(2921).saturating_mul(n.into())) + } }