diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 7b83ef98d7d50..c34c46b04c0dc 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1453,6 +1453,7 @@ parameter_types! { pub const ItemDeposit: Balance = 1 * DOLLARS; pub const KeyLimit: u32 = 32; pub const ValueLimit: u32 = 256; + pub const ApprovalsLimit: u32 = 20; } impl pallet_uniques::Config for Runtime { @@ -1490,6 +1491,7 @@ impl pallet_nfts::Config for Runtime { type StringLimit = StringLimit; type KeyLimit = KeyLimit; type ValueLimit = ValueLimit; + type ApprovalsLimit = ApprovalsLimit; type WeightInfo = pallet_nfts::weights::SubstrateWeight; #[cfg(feature = "runtime-benchmarks")] type Helper = (); diff --git a/frame/nfts/src/benchmarking.rs b/frame/nfts/src/benchmarking.rs index e30b5ebbd3fe5..ca38851222e8d 100644 --- a/frame/nfts/src/benchmarking.rs +++ b/frame/nfts/src/benchmarking.rs @@ -368,9 +368,10 @@ benchmarks_instance_pallet! { let (item, ..) = mint_item::(0); let delegate: T::AccountId = account("delegate", 0, SEED); let delegate_lookup = T::Lookup::unlookup(delegate.clone()); - }: _(SystemOrigin::Signed(caller.clone()), collection, item, delegate_lookup) + let deadline = T::BlockNumber::max_value(); + }: _(SystemOrigin::Signed(caller.clone()), collection, item, delegate_lookup, Some(deadline)) verify { - assert_last_event::(Event::ApprovedTransfer { collection, item, owner: caller, delegate }.into()); + assert_last_event::(Event::ApprovedTransfer { collection, item, owner: caller, delegate, deadline: Some(deadline) }.into()); } cancel_approval { @@ -379,12 +380,26 @@ benchmarks_instance_pallet! { let delegate: T::AccountId = account("delegate", 0, SEED); let delegate_lookup = T::Lookup::unlookup(delegate.clone()); let origin = SystemOrigin::Signed(caller.clone()).into(); - Nfts::::approve_transfer(origin, collection, item, delegate_lookup.clone())?; - }: _(SystemOrigin::Signed(caller.clone()), collection, item, Some(delegate_lookup)) + let deadline = T::BlockNumber::max_value(); + Nfts::::approve_transfer(origin, collection, item, delegate_lookup.clone(), Some(deadline))?; + }: _(SystemOrigin::Signed(caller.clone()), collection, item, delegate_lookup) verify { assert_last_event::(Event::ApprovalCancelled { collection, item, owner: caller, delegate }.into()); } + clear_all_transfer_approvals { + let (collection, caller, _) = create_collection::(); + let (item, ..) = mint_item::(0); + let delegate: T::AccountId = account("delegate", 0, SEED); + let delegate_lookup = T::Lookup::unlookup(delegate.clone()); + let origin = SystemOrigin::Signed(caller.clone()).into(); + let deadline = T::BlockNumber::max_value(); + Nfts::::approve_transfer(origin, collection, item, delegate_lookup.clone(), Some(deadline))?; + }: _(SystemOrigin::Signed(caller.clone()), collection, item) + verify { + assert_last_event::(Event::AllApprovalsCancelled {collection, item, owner: caller}.into()); + } + set_accept_ownership { let caller: T::AccountId = whitelisted_caller(); T::Currency::make_free_balance_be(&caller, DepositBalanceOf::::max_value()); diff --git a/frame/nfts/src/functions.rs b/frame/nfts/src/functions.rs index 107214558307f..27ab752dbabf6 100644 --- a/frame/nfts/src/functions.rs +++ b/frame/nfts/src/functions.rs @@ -48,6 +48,12 @@ impl, I: 'static> Pallet { Account::::insert((&dest, &collection, &item), ()); let origin = details.owner; details.owner = dest; + + // The approved accounts have to be reset to None, because otherwise pre-approve attack + // would be possible, where the owner can approve his second account before making the + // transaction and then claiming the item back. + details.approvals.clear(); + Item::::insert(&collection, &item, &details); ItemPriceOf::::remove(&collection, &item); @@ -168,7 +174,12 @@ impl, I: 'static> Pallet { let owner = owner.clone(); Account::::insert((&owner, &collection, &item), ()); - let details = ItemDetails { owner, approved: None, is_frozen: false, deposit }; + let details = ItemDetails { + owner, + approvals: ApprovalsOf::::default(), + is_frozen: false, + deposit, + }; Item::::insert(&collection, &item, details); Ok(()) }, diff --git a/frame/nfts/src/lib.rs b/frame/nfts/src/lib.rs index cb96e8138ba5e..14691c21a0ef2 100644 --- a/frame/nfts/src/lib.rs +++ b/frame/nfts/src/lib.rs @@ -46,7 +46,7 @@ use frame_support::{ traits::{ tokens::Locker, BalanceStatus::Reserved, Currency, EnsureOriginWithArg, ReservableCurrency, }, - transactional, + transactional, BoundedBTreeMap, }; use frame_system::Config as SystemConfig; use sp_runtime::{ @@ -59,7 +59,7 @@ pub use pallet::*; pub use types::*; pub use weights::WeightInfo; -type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; +type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; #[frame_support::pallet] pub mod pallet { @@ -149,6 +149,10 @@ pub mod pallet { #[pallet::constant] type ValueLimit: Get; + /// The maximum approvals an item could have. + #[pallet::constant] + type ApprovalsLimit: Get; + #[cfg(feature = "runtime-benchmarks")] /// A set of helper functions for benchmarking. type Helper: BenchmarkHelper; @@ -157,6 +161,12 @@ pub mod pallet { type WeightInfo: WeightInfo; } + pub type ApprovalsOf = BoundedBTreeMap< + ::AccountId, + Option<::BlockNumber>, + >::ApprovalsLimit, + >; + #[pallet::storage] #[pallet::storage_prefix = "Class"] /// Details of a collection. @@ -209,7 +219,7 @@ pub mod pallet { T::CollectionId, Blake2_128Concat, T::ItemId, - ItemDetails>, + ItemDetails, ApprovalsOf>, OptionQuery, >; @@ -311,6 +321,7 @@ pub mod pallet { item: T::ItemId, owner: T::AccountId, delegate: T::AccountId, + deadline: Option<::BlockNumber>, }, /// An approval for a `delegate` account to transfer the `item` of an item /// `collection` was cancelled by its `owner`. @@ -320,6 +331,8 @@ pub mod pallet { owner: T::AccountId, delegate: T::AccountId, }, + /// All approvals of an item got cancelled. + AllApprovalsCancelled { collection: T::CollectionId, item: T::ItemId, owner: T::AccountId }, /// A `collection` has had its attributes changed by the `Force` origin. ItemStatusChanged { collection: T::CollectionId }, /// New metadata has been set for a `collection`. @@ -385,6 +398,8 @@ pub mod pallet { UnknownCollection, /// The item ID has already been used for an item. AlreadyExists, + /// The approval had a deadline that expired, so the approval isn't valid anymore. + ApprovalExpired, /// The owner turned out to be different to what was expected. WrongOwner, /// Invalid witness data given. @@ -393,10 +408,10 @@ pub mod pallet { InUse, /// The item or collection is frozen. Frozen, + /// The provided account is not a delegate. + NotDelegate, /// The delegate turned out to be different to what was expected. WrongDelegate, - /// There is no delegate approved. - NoDelegate, /// No approval exists that would allow the transfer. Unapproved, /// The named owner has not signed ownership of the collection is acceptable. @@ -415,6 +430,8 @@ pub mod pallet { NotForSale, /// The provided bid is too low. BidTooLow, + /// The item has reached its approval limit. + ReachedApprovalLimit, } impl, I: 'static> Pallet { @@ -630,8 +647,12 @@ pub mod pallet { Self::do_transfer(collection, item, dest, |collection_details, details| { if details.owner != origin && collection_details.admin != origin { - let approved = details.approved.take().map_or(false, |i| i == origin); - ensure!(approved, Error::::NoPermission); + let deadline = + details.approvals.get(&origin).ok_or(Error::::NoPermission)?; + if let Some(d) = deadline { + let block_number = frame_system::Pallet::::block_number(); + ensure!(block_number <= *d, Error::::ApprovalExpired); + } } Ok(()) }) @@ -912,6 +933,8 @@ pub mod pallet { /// - `collection`: The collection of the item to be approved for delegated transfer. /// - `item`: The item of the item to be approved for delegated transfer. /// - `delegate`: The account to delegate permission to transfer the item. + /// - `maybe_deadline`: Optional deadline for the approval. Specified by providing the + /// number of blocks after which the approval will expire /// /// Emits `ApprovedTransfer` on success. /// @@ -922,6 +945,7 @@ pub mod pallet { collection: T::CollectionId, item: T::ItemId, delegate: AccountIdLookupOf, + maybe_deadline: Option<::BlockNumber>, ) -> DispatchResult { let maybe_check: Option = T::ForceOrigin::try_origin(origin) .map(|_| None) @@ -939,21 +963,27 @@ pub mod pallet { ensure!(permitted, Error::::NoPermission); } - details.approved = Some(delegate); + let now = frame_system::Pallet::::block_number(); + let deadline = maybe_deadline.map(|d| d.saturating_add(now)); + + details + .approvals + .try_insert(delegate.clone(), deadline) + .map_err(|_| Error::::ReachedApprovalLimit)?; Item::::insert(&collection, &item, &details); - let delegate = details.approved.expect("set as Some above; qed"); Self::deposit_event(Event::ApprovedTransfer { collection, item, owner: details.owner, delegate, + deadline, }); Ok(()) } - /// Cancel the prior approval for the transfer of an item by a delegate. + /// Cancel one of the transfer approvals for a specific item. /// /// Origin must be either: /// - the `Force` origin; @@ -962,9 +992,8 @@ pub mod pallet { /// /// Arguments: /// - `collection`: The collection of the item of whose approval will be cancelled. - /// - `item`: The item of the item of whose approval will be cancelled. - /// - `maybe_check_delegate`: If `Some` will ensure that the given account is the one to - /// which permission of transfer is delegated. + /// - `item`: The item of the collection of whose approval will be cancelled. + /// - `delegate`: The account that is going to loose their approval. /// /// Emits `ApprovalCancelled` on success. /// @@ -974,7 +1003,67 @@ pub mod pallet { origin: OriginFor, collection: T::CollectionId, item: T::ItemId, - maybe_check_delegate: Option>, + delegate: AccountIdLookupOf, + ) -> DispatchResult { + let maybe_check: Option = T::ForceOrigin::try_origin(origin) + .map(|_| None) + .or_else(|origin| ensure_signed(origin).map(Some).map_err(DispatchError::from))?; + + let delegate = T::Lookup::lookup(delegate)?; + + let collection_details = + Collection::::get(&collection).ok_or(Error::::UnknownCollection)?; + let mut details = + Item::::get(&collection, &item).ok_or(Error::::UnknownCollection)?; + + let maybe_deadline = + details.approvals.get(&delegate).ok_or(Error::::NotDelegate)?; + + let is_past_deadline = if let Some(deadline) = maybe_deadline { + let now = frame_system::Pallet::::block_number(); + now > *deadline + } else { + false + }; + + if !is_past_deadline { + if let Some(check) = maybe_check { + let permitted = check == collection_details.admin || check == details.owner; + ensure!(permitted, Error::::NoPermission); + } + } + + details.approvals.remove(&delegate); + Item::::insert(&collection, &item, &details); + Self::deposit_event(Event::ApprovalCancelled { + collection, + item, + owner: details.owner, + delegate, + }); + + Ok(()) + } + + /// Cancel all the approvals of a specific item. + /// + /// Origin must be either: + /// - the `Force` origin; + /// - `Signed` with the signer being the Admin of the `collection`; + /// - `Signed` with the signer being the Owner of the `item`; + /// + /// Arguments: + /// - `collection`: The collection of the item of whose approvals will be cleared. + /// - `item`: The item of the collection of whose approvals will be cleared. + /// + /// Emits `AllApprovalsCancelled` on success. + /// + /// Weight: `O(1)` + #[pallet::weight(T::WeightInfo::clear_all_transfer_approvals())] + pub fn clear_all_transfer_approvals( + origin: OriginFor, + collection: T::CollectionId, + item: T::ItemId, ) -> DispatchResult { let maybe_check: Option = T::ForceOrigin::try_origin(origin) .map(|_| None) @@ -988,18 +1077,13 @@ pub mod pallet { let permitted = check == collection_details.admin || check == details.owner; ensure!(permitted, Error::::NoPermission); } - let maybe_check_delegate = maybe_check_delegate.map(T::Lookup::lookup).transpose()?; - let old = details.approved.take().ok_or(Error::::NoDelegate)?; - if let Some(check_delegate) = maybe_check_delegate { - ensure!(check_delegate == old, Error::::WrongDelegate); - } + details.approvals.clear(); Item::::insert(&collection, &item, &details); - Self::deposit_event(Event::ApprovalCancelled { + Self::deposit_event(Event::AllApprovalsCancelled { collection, item, owner: details.owner, - delegate: old, }); Ok(()) diff --git a/frame/nfts/src/mock.rs b/frame/nfts/src/mock.rs index f3040faac5f40..ad7a94b3eed50 100644 --- a/frame/nfts/src/mock.rs +++ b/frame/nfts/src/mock.rs @@ -100,6 +100,7 @@ impl Config for Test { type StringLimit = ConstU32<50>; type KeyLimit = ConstU32<50>; type ValueLimit = ConstU32<50>; + type ApprovalsLimit = ConstU32<10>; type WeightInfo = (); #[cfg(feature = "runtime-benchmarks")] type Helper = (); diff --git a/frame/nfts/src/tests.rs b/frame/nfts/src/tests.rs index 2b20d124bd9ae..9fb29d0e95c26 100644 --- a/frame/nfts/src/tests.rs +++ b/frame/nfts/src/tests.rs @@ -70,6 +70,12 @@ fn attributes(collection: u32) -> Vec<(Option, Vec, Vec)> { s } +fn approvals(collection_id: u32, item_id: u32) -> Vec<(u64, Option)> { + let item = Item::::get(collection_id, item_id).unwrap(); + let s: Vec<_> = item.approvals.into_iter().collect(); + s +} + fn events() -> Vec> { let result = System::events() .into_iter() @@ -180,7 +186,7 @@ fn transfer_should_work() { assert_eq!(items(), vec![(3, 0, 42)]); assert_noop!(Nfts::transfer(Origin::signed(2), 0, 42, 4), Error::::NoPermission); - assert_ok!(Nfts::approve_transfer(Origin::signed(3), 0, 42, 2)); + assert_ok!(Nfts::approve_transfer(Origin::signed(3), 0, 42, 2, None)); assert_ok!(Nfts::transfer(Origin::signed(2), 0, 42, 4)); }); } @@ -535,12 +541,12 @@ fn approval_lifecycle_works() { new_test_ext().execute_with(|| { assert_ok!(Nfts::force_create(Origin::root(), 0, 1, true)); assert_ok!(Nfts::mint(Origin::signed(1), 0, 42, 2)); - assert_ok!(Nfts::approve_transfer(Origin::signed(2), 0, 42, 3)); + assert_ok!(Nfts::approve_transfer(Origin::signed(2), 0, 42, 3, None)); assert_ok!(Nfts::transfer(Origin::signed(3), 0, 42, 4)); assert_noop!(Nfts::transfer(Origin::signed(3), 0, 42, 3), Error::::NoPermission); - assert!(Item::::get(0, 42).unwrap().approved.is_none()); + assert!(Item::::get(0, 42).unwrap().approvals.is_empty()); - assert_ok!(Nfts::approve_transfer(Origin::signed(4), 0, 42, 2)); + assert_ok!(Nfts::approve_transfer(Origin::signed(4), 0, 42, 2, None)); assert_ok!(Nfts::transfer(Origin::signed(2), 0, 42, 2)); }); } @@ -551,29 +557,107 @@ fn cancel_approval_works() { assert_ok!(Nfts::force_create(Origin::root(), 0, 1, true)); assert_ok!(Nfts::mint(Origin::signed(1), 0, 42, 2)); - assert_ok!(Nfts::approve_transfer(Origin::signed(2), 0, 42, 3)); + assert_ok!(Nfts::approve_transfer(Origin::signed(2), 0, 42, 3, None)); assert_noop!( - Nfts::cancel_approval(Origin::signed(2), 1, 42, None), + Nfts::cancel_approval(Origin::signed(2), 1, 42, 3), Error::::UnknownCollection ); assert_noop!( - Nfts::cancel_approval(Origin::signed(2), 0, 43, None), + Nfts::cancel_approval(Origin::signed(2), 0, 43, 3), Error::::UnknownCollection ); assert_noop!( - Nfts::cancel_approval(Origin::signed(3), 0, 42, None), + Nfts::cancel_approval(Origin::signed(3), 0, 42, 3), Error::::NoPermission ); assert_noop!( - Nfts::cancel_approval(Origin::signed(2), 0, 42, Some(4)), - Error::::WrongDelegate + Nfts::cancel_approval(Origin::signed(2), 0, 42, 4), + Error::::NotDelegate ); - assert_ok!(Nfts::cancel_approval(Origin::signed(2), 0, 42, Some(3))); + assert_ok!(Nfts::cancel_approval(Origin::signed(2), 0, 42, 3)); + assert_noop!( + Nfts::cancel_approval(Origin::signed(2), 0, 42, 3), + Error::::NotDelegate + ); + + let current_block = 1; + System::set_block_number(current_block); + assert_ok!(Nfts::mint(Origin::signed(1), 0, 69, 2)); + // approval expires after 2 blocks. + assert_ok!(Nfts::approve_transfer(Origin::signed(2), 0, 42, 3, Some(2))); assert_noop!( - Nfts::cancel_approval(Origin::signed(2), 0, 42, None), - Error::::NoDelegate + Nfts::cancel_approval(Origin::signed(5), 0, 42, 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(Origin::signed(5), 0, 42, 3)); + assert_eq!(approvals(0, 69), vec![]); + }); +} + +#[test] +fn approving_multiple_accounts_works() { + new_test_ext().execute_with(|| { + assert_ok!(Nfts::force_create(Origin::root(), 0, 1, true)); + assert_ok!(Nfts::mint(Origin::signed(1), 0, 42, 2)); + + let current_block = 1; + System::set_block_number(current_block); + assert_ok!(Nfts::approve_transfer(Origin::signed(2), 0, 42, 3, None)); + assert_ok!(Nfts::approve_transfer(Origin::signed(2), 0, 42, 4, None)); + assert_ok!(Nfts::approve_transfer(Origin::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::transfer(Origin::signed(4), 0, 42, 6)); + assert_noop!(Nfts::transfer(Origin::signed(3), 0, 42, 7), Error::::NoPermission); + assert_noop!(Nfts::transfer(Origin::signed(5), 0, 42, 8), Error::::NoPermission); + }); +} + +#[test] +fn approvals_limit_works() { + new_test_ext().execute_with(|| { + assert_ok!(Nfts::force_create(Origin::root(), 0, 1, true)); + assert_ok!(Nfts::mint(Origin::signed(1), 0, 42, 2)); + + for i in 3..13 { + assert_ok!(Nfts::approve_transfer(Origin::signed(2), 0, 42, i, None)); + } + // the limit is 10 + assert_noop!( + Nfts::approve_transfer(Origin::signed(2), 0, 42, 14, None), + Error::::ReachedApprovalLimit + ); + }); +} + +#[test] +fn approval_deadline_works() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + assert!(System::block_number().is_zero()); + + assert_ok!(Nfts::force_create(Origin::root(), 0, 1, true)); + assert_ok!(Nfts::mint(Origin::signed(1), 0, 42, 2)); + + // the approval expires after the 2nd block. + assert_ok!(Nfts::approve_transfer(Origin::signed(2), 0, 42, 3, Some(2))); + + System::set_block_number(3); + assert_noop!(Nfts::transfer(Origin::signed(3), 0, 42, 4), Error::::ApprovalExpired); + System::set_block_number(1); + assert_ok!(Nfts::transfer(Origin::signed(3), 0, 42, 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(Origin::signed(4), 0, 42, 6, Some(4))); + // this should still work. + System::set_block_number(5); + assert_ok!(Nfts::transfer(Origin::signed(6), 0, 42, 5)); }); } @@ -583,24 +667,24 @@ fn cancel_approval_works_with_admin() { assert_ok!(Nfts::force_create(Origin::root(), 0, 1, true)); assert_ok!(Nfts::mint(Origin::signed(1), 0, 42, 2)); - assert_ok!(Nfts::approve_transfer(Origin::signed(2), 0, 42, 3)); + assert_ok!(Nfts::approve_transfer(Origin::signed(2), 0, 42, 3, None)); assert_noop!( - Nfts::cancel_approval(Origin::signed(1), 1, 42, None), + Nfts::cancel_approval(Origin::signed(1), 1, 42, 1), Error::::UnknownCollection ); assert_noop!( - Nfts::cancel_approval(Origin::signed(1), 0, 43, None), + Nfts::cancel_approval(Origin::signed(1), 0, 43, 1), Error::::UnknownCollection ); assert_noop!( - Nfts::cancel_approval(Origin::signed(1), 0, 42, Some(4)), - Error::::WrongDelegate + Nfts::cancel_approval(Origin::signed(1), 0, 42, 4), + Error::::NotDelegate ); - assert_ok!(Nfts::cancel_approval(Origin::signed(1), 0, 42, Some(3))); + assert_ok!(Nfts::cancel_approval(Origin::signed(1), 0, 42, 3)); assert_noop!( - Nfts::cancel_approval(Origin::signed(1), 0, 42, None), - Error::::NoDelegate + Nfts::cancel_approval(Origin::signed(1), 0, 42, 1), + Error::::NotDelegate ); }); } @@ -611,22 +695,47 @@ fn cancel_approval_works_with_force() { assert_ok!(Nfts::force_create(Origin::root(), 0, 1, true)); assert_ok!(Nfts::mint(Origin::signed(1), 0, 42, 2)); - assert_ok!(Nfts::approve_transfer(Origin::signed(2), 0, 42, 3)); + assert_ok!(Nfts::approve_transfer(Origin::signed(2), 0, 42, 3, None)); assert_noop!( - Nfts::cancel_approval(Origin::root(), 1, 42, None), + Nfts::cancel_approval(Origin::root(), 1, 42, 1), Error::::UnknownCollection ); assert_noop!( - Nfts::cancel_approval(Origin::root(), 0, 43, None), + Nfts::cancel_approval(Origin::root(), 0, 43, 1), Error::::UnknownCollection ); + assert_noop!(Nfts::cancel_approval(Origin::root(), 0, 42, 4), Error::::NotDelegate); + + assert_ok!(Nfts::cancel_approval(Origin::root(), 0, 42, 3)); + assert_noop!(Nfts::cancel_approval(Origin::root(), 0, 42, 1), Error::::NotDelegate); + }); +} + +#[test] +fn clear_all_transfer_approvals_works() { + new_test_ext().execute_with(|| { + assert_ok!(Nfts::force_create(Origin::root(), 0, 1, true)); + assert_ok!(Nfts::mint(Origin::signed(1), 0, 42, 2)); + + assert_ok!(Nfts::approve_transfer(Origin::signed(2), 0, 42, 3, None)); + assert_ok!(Nfts::approve_transfer(Origin::signed(2), 0, 42, 4, None)); + assert_noop!( - Nfts::cancel_approval(Origin::root(), 0, 42, Some(4)), - Error::::WrongDelegate + Nfts::clear_all_transfer_approvals(Origin::signed(3), 0, 42), + Error::::NoPermission ); - assert_ok!(Nfts::cancel_approval(Origin::root(), 0, 42, Some(3))); - assert_noop!(Nfts::cancel_approval(Origin::root(), 0, 42, None), Error::::NoDelegate); + assert_ok!(Nfts::clear_all_transfer_approvals(Origin::signed(2), 0, 42)); + + assert!(events().contains(&Event::::AllApprovalsCancelled { + collection: 0, + item: 42, + owner: 2, + })); + assert_eq!(approvals(0, 42), vec![]); + + assert_noop!(Nfts::transfer(Origin::signed(3), 0, 42, 5), Error::::NoPermission); + assert_noop!(Nfts::transfer(Origin::signed(4), 0, 42, 5), Error::::NoPermission); }); } diff --git a/frame/nfts/src/types.rs b/frame/nfts/src/types.rs index 1081ec8110288..db1c351c4a9c5 100644 --- a/frame/nfts/src/types.rs +++ b/frame/nfts/src/types.rs @@ -29,7 +29,7 @@ pub(super) type DepositBalanceOf = pub(super) type CollectionDetailsFor = CollectionDetails<::AccountId, DepositBalanceOf>; pub(super) type ItemDetailsFor = - ItemDetails<::AccountId, DepositBalanceOf>; + ItemDetails<::AccountId, DepositBalanceOf, ApprovalsOf>; pub(super) type ItemPrice = <>::Currency as Currency<::AccountId>>::Balance; @@ -84,11 +84,11 @@ impl CollectionDetails { /// Information concerning the ownership of a single unique item. #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, TypeInfo, MaxEncodedLen)] -pub struct ItemDetails { +pub struct ItemDetails { /// The owner of this item. pub(super) owner: AccountId, /// The approved transferrer of this item, if one is set. - pub(super) approved: Option, + pub(super) approvals: Approvals, /// Whether the item can be transferred or not. pub(super) is_frozen: bool, /// The amount held in the pallet's default account for this item. Free-hold items will have diff --git a/frame/nfts/src/weights.rs b/frame/nfts/src/weights.rs index de518b8286665..2c90ab54fe9fb 100644 --- a/frame/nfts/src/weights.rs +++ b/frame/nfts/src/weights.rs @@ -18,12 +18,12 @@ //! Autogenerated weights for pallet_nfts //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-07-13, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! HOSTNAME: `test-bench-bot`, CPU: `Intel(R) Xeon(R) CPU @ 3.10GHz` +//! DATE: 2022-09-09, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/production/substrate +// /home/benchbot/cargo_target_dir/production/substrate // benchmark // pallet // --steps=50 @@ -68,6 +68,7 @@ pub trait WeightInfo { fn clear_collection_metadata() -> Weight; fn approve_transfer() -> Weight; fn cancel_approval() -> Weight; + fn clear_all_transfer_approvals() -> Weight; fn set_accept_ownership() -> Weight; fn set_collection_max_supply() -> Weight; fn set_price() -> Weight; @@ -77,39 +78,39 @@ pub trait WeightInfo { /// Weights for pallet_nfts using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques ClassAccount (r:0 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts ClassAccount (r:0 w:1) fn create() -> Weight { - Weight::from_ref_time(33_075_000 as u64) + Weight::from_ref_time(33_018_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques ClassAccount (r:0 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts ClassAccount (r:0 w:1) fn force_create() -> Weight { - Weight::from_ref_time(19_528_000 as u64) + Weight::from_ref_time(20_957_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques Asset (r:1 w:0) - // Storage: Uniques ClassAccount (r:0 w:1) - // Storage: Uniques Attribute (r:0 w:1000) - // Storage: Uniques ClassMetadataOf (r:0 w:1) - // Storage: Uniques InstanceMetadataOf (r:0 w:1000) - // Storage: Uniques CollectionMaxSupply (r:0 w:1) - // Storage: Uniques Account (r:0 w:20) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts Asset (r:1 w:0) + // Storage: Nfts ClassAccount (r:0 w:1) + // Storage: Nfts Attribute (r:0 w:1000) + // Storage: Nfts ClassMetadataOf (r:0 w:1) + // Storage: Nfts InstanceMetadataOf (r:0 w:1000) + // Storage: Nfts CollectionMaxSupply (r:0 w:1) + // Storage: Nfts Account (r:0 w:20) /// 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 { Weight::from_ref_time(0 as u64) - // Standard Error: 25_000 - .saturating_add(Weight::from_ref_time(13_639_000 as u64).saturating_mul(n as u64)) - // Standard Error: 25_000 - .saturating_add(Weight::from_ref_time(2_393_000 as u64).saturating_mul(m as u64)) - // Standard Error: 25_000 - .saturating_add(Weight::from_ref_time(2_217_000 as u64).saturating_mul(a as u64)) + // Standard Error: 12_000 + .saturating_add(Weight::from_ref_time(10_091_000 as u64).saturating_mul(n as u64)) + // Standard Error: 12_000 + .saturating_add(Weight::from_ref_time(1_748_000 as u64).saturating_mul(m as u64)) + // Standard Error: 12_000 + .saturating_add(Weight::from_ref_time(1_621_000 as u64).saturating_mul(a as u64)) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(n as u64))) .saturating_add(T::DbWeight::get().writes(4 as u64)) @@ -117,176 +118,183 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(m as u64))) .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(a as u64))) } - // Storage: Uniques Asset (r:1 w:1) - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques CollectionMaxSupply (r:1 w:0) - // Storage: Uniques Account (r:0 w:1) + // Storage: Nfts Asset (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts CollectionMaxSupply (r:1 w:0) + // Storage: Nfts Account (r:0 w:1) fn mint() -> Weight { - Weight::from_ref_time(42_146_000 as u64) + Weight::from_ref_time(43_007_000 as u64) .saturating_add(T::DbWeight::get().reads(3 as u64)) .saturating_add(T::DbWeight::get().writes(3 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques Asset (r:1 w:1) - // Storage: Uniques Account (r:0 w:1) - // Storage: Uniques ItemPriceOf (r:0 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts Asset (r:1 w:1) + // Storage: Nfts Account (r:0 w:1) + // Storage: Nfts ItemPriceOf (r:0 w:1) fn burn() -> Weight { - Weight::from_ref_time(42_960_000 as u64) + Weight::from_ref_time(43_922_000 as u64) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().writes(4 as u64)) } - // Storage: Uniques Class (r:1 w:0) - // Storage: Uniques Asset (r:1 w:1) - // Storage: Uniques Account (r:0 w:2) - // Storage: Uniques ItemPriceOf (r:0 w:1) + // Storage: Nfts Class (r:1 w:0) + // Storage: Nfts Asset (r:1 w:1) + // Storage: Nfts Account (r:0 w:2) + // Storage: Nfts ItemPriceOf (r:0 w:1) fn transfer() -> Weight { - Weight::from_ref_time(33_025_000 as u64) + Weight::from_ref_time(33_951_000 as u64) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().writes(4 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques Asset (r:100 w:100) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts Asset (r:102 w:102) /// The range of component `i` is `[0, 5000]`. fn redeposit(i: u32, ) -> Weight { Weight::from_ref_time(0 as u64) - // Standard Error: 24_000 - .saturating_add(Weight::from_ref_time(15_540_000 as u64).saturating_mul(i as u64)) + // Standard Error: 12_000 + .saturating_add(Weight::from_ref_time(11_194_000 as u64).saturating_mul(i as u64)) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(i as u64))) .saturating_add(T::DbWeight::get().writes(1 as u64)) .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(i as u64))) } - // Storage: Uniques Asset (r:1 w:1) - // Storage: Uniques Class (r:1 w:0) + // Storage: Nfts Asset (r:1 w:1) + // Storage: Nfts Class (r:1 w:0) fn freeze() -> Weight { - Weight::from_ref_time(25_194_000 as u64) + Weight::from_ref_time(26_745_000 as u64) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } - // Storage: Uniques Asset (r:1 w:1) - // Storage: Uniques Class (r:1 w:0) + // Storage: Nfts Asset (r:1 w:1) + // Storage: Nfts Class (r:1 w:0) fn thaw() -> Weight { - Weight::from_ref_time(25_397_000 as u64) + Weight::from_ref_time(27_466_000 as u64) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } - // Storage: Uniques Class (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) fn freeze_collection() -> Weight { - Weight::from_ref_time(19_278_000 as u64) + Weight::from_ref_time(22_591_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } - // Storage: Uniques Class (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) fn thaw_collection() -> Weight { - Weight::from_ref_time(19_304_000 as u64) + Weight::from_ref_time(22_392_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } - // Storage: Uniques OwnershipAcceptance (r:1 w:1) - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques ClassAccount (r:0 w:2) + // Storage: Nfts OwnershipAcceptance (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts ClassAccount (r:0 w:2) fn transfer_ownership() -> Weight { - Weight::from_ref_time(28_615_000 as u64) + Weight::from_ref_time(31_202_000 as u64) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().writes(4 as u64)) } - // Storage: Uniques Class (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) fn set_team() -> Weight { - Weight::from_ref_time(19_943_000 as u64) + Weight::from_ref_time(23_063_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques ClassAccount (r:0 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts ClassAccount (r:0 w:1) fn force_item_status() -> Weight { - Weight::from_ref_time(22_583_000 as u64) + Weight::from_ref_time(25_598_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques InstanceMetadataOf (r:1 w:0) - // Storage: Uniques Attribute (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts InstanceMetadataOf (r:1 w:0) + // Storage: Nfts Attribute (r:1 w:1) fn set_attribute() -> Weight { - Weight::from_ref_time(47_520_000 as u64) + Weight::from_ref_time(48_684_000 as u64) .saturating_add(T::DbWeight::get().reads(3 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques InstanceMetadataOf (r:1 w:0) - // Storage: Uniques Attribute (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts InstanceMetadataOf (r:1 w:0) + // Storage: Nfts Attribute (r:1 w:1) fn clear_attribute() -> Weight { - Weight::from_ref_time(45_316_000 as u64) + Weight::from_ref_time(47_267_000 as u64) .saturating_add(T::DbWeight::get().reads(3 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques InstanceMetadataOf (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts InstanceMetadataOf (r:1 w:1) fn set_metadata() -> Weight { - Weight::from_ref_time(38_391_000 as u64) + Weight::from_ref_time(40_174_000 as u64) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques InstanceMetadataOf (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts InstanceMetadataOf (r:1 w:1) fn clear_metadata() -> Weight { - Weight::from_ref_time(38_023_000 as u64) + Weight::from_ref_time(41_611_000 as u64) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques ClassMetadataOf (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts ClassMetadataOf (r:1 w:1) fn set_collection_metadata() -> Weight { - Weight::from_ref_time(37_398_000 as u64) + Weight::from_ref_time(40_073_000 as u64) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } - // Storage: Uniques Class (r:1 w:0) - // Storage: Uniques ClassMetadataOf (r:1 w:1) + // Storage: Nfts Class (r:1 w:0) + // Storage: Nfts ClassMetadataOf (r:1 w:1) fn clear_collection_metadata() -> Weight { - Weight::from_ref_time(35_621_000 as u64) + Weight::from_ref_time(38_191_000 as u64) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } - // Storage: Uniques Class (r:1 w:0) - // Storage: Uniques Asset (r:1 w:1) + // Storage: Nfts Class (r:1 w:0) + // Storage: Nfts Asset (r:1 w:1) fn approve_transfer() -> Weight { - Weight::from_ref_time(25_856_000 as u64) + Weight::from_ref_time(29_461_000 as u64) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } - // Storage: Uniques Class (r:1 w:0) - // Storage: Uniques Asset (r:1 w:1) + // Storage: Nfts Class (r:1 w:0) + // Storage: Nfts Asset (r:1 w:1) fn cancel_approval() -> Weight { - Weight::from_ref_time(26_098_000 as u64) + Weight::from_ref_time(29_690_000 as u64) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } - // Storage: Uniques OwnershipAcceptance (r:1 w:1) + // Storage: Nfts Class (r:1 w:0) + // Storage: Nfts Asset (r:1 w:1) + fn clear_all_transfer_approvals() -> Weight { + Weight::from_ref_time(27_758_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: Nfts OwnershipAcceptance (r:1 w:1) fn set_accept_ownership() -> Weight { - Weight::from_ref_time(24_076_000 as u64) + Weight::from_ref_time(26_425_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } - // Storage: Uniques CollectionMaxSupply (r:1 w:1) - // Storage: Uniques Class (r:1 w:0) + // Storage: Nfts CollectionMaxSupply (r:1 w:1) + // Storage: Nfts Class (r:1 w:0) fn set_collection_max_supply() -> Weight { - Weight::from_ref_time(22_035_000 as u64) + Weight::from_ref_time(24_533_000 as u64) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } - // Storage: Uniques Asset (r:1 w:0) - // Storage: Uniques ItemPriceOf (r:0 w:1) + // Storage: Nfts Asset (r:1 w:0) + // Storage: Nfts ItemPriceOf (r:0 w:1) fn set_price() -> Weight { - Weight::from_ref_time(22_534_000 as u64) + Weight::from_ref_time(24_745_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } - // Storage: Uniques Asset (r:1 w:1) - // Storage: Uniques ItemPriceOf (r:1 w:1) - // Storage: Uniques Class (r:1 w:0) - // Storage: Uniques Account (r:0 w:2) + // Storage: Nfts Asset (r:1 w:1) + // Storage: Nfts ItemPriceOf (r:1 w:1) + // Storage: Nfts Class (r:1 w:0) + // Storage: Nfts Account (r:0 w:2) fn buy_item() -> Weight { - Weight::from_ref_time(45_272_000 as u64) + Weight::from_ref_time(47_967_000 as u64) .saturating_add(T::DbWeight::get().reads(3 as u64)) .saturating_add(T::DbWeight::get().writes(4 as u64)) } @@ -294,39 +302,39 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques ClassAccount (r:0 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts ClassAccount (r:0 w:1) fn create() -> Weight { - Weight::from_ref_time(33_075_000 as u64) + Weight::from_ref_time(33_018_000 as u64) .saturating_add(RocksDbWeight::get().reads(1 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques ClassAccount (r:0 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts ClassAccount (r:0 w:1) fn force_create() -> Weight { - Weight::from_ref_time(19_528_000 as u64) + Weight::from_ref_time(20_957_000 as u64) .saturating_add(RocksDbWeight::get().reads(1 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques Asset (r:1 w:0) - // Storage: Uniques ClassAccount (r:0 w:1) - // Storage: Uniques Attribute (r:0 w:1000) - // Storage: Uniques ClassMetadataOf (r:0 w:1) - // Storage: Uniques InstanceMetadataOf (r:0 w:1000) - // Storage: Uniques CollectionMaxSupply (r:0 w:1) - // Storage: Uniques Account (r:0 w:20) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts Asset (r:1 w:0) + // Storage: Nfts ClassAccount (r:0 w:1) + // Storage: Nfts Attribute (r:0 w:1000) + // Storage: Nfts ClassMetadataOf (r:0 w:1) + // Storage: Nfts InstanceMetadataOf (r:0 w:1000) + // Storage: Nfts CollectionMaxSupply (r:0 w:1) + // Storage: Nfts Account (r:0 w:20) /// 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 { Weight::from_ref_time(0 as u64) - // Standard Error: 25_000 - .saturating_add(Weight::from_ref_time(13_639_000 as u64).saturating_mul(n as u64)) - // Standard Error: 25_000 - .saturating_add(Weight::from_ref_time(2_393_000 as u64).saturating_mul(m as u64)) - // Standard Error: 25_000 - .saturating_add(Weight::from_ref_time(2_217_000 as u64).saturating_mul(a as u64)) + // Standard Error: 12_000 + .saturating_add(Weight::from_ref_time(10_091_000 as u64).saturating_mul(n as u64)) + // Standard Error: 12_000 + .saturating_add(Weight::from_ref_time(1_748_000 as u64).saturating_mul(m as u64)) + // Standard Error: 12_000 + .saturating_add(Weight::from_ref_time(1_621_000 as u64).saturating_mul(a as u64)) .saturating_add(RocksDbWeight::get().reads(2 as u64)) .saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(n as u64))) .saturating_add(RocksDbWeight::get().writes(4 as u64)) @@ -334,176 +342,183 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(m as u64))) .saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(a as u64))) } - // Storage: Uniques Asset (r:1 w:1) - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques CollectionMaxSupply (r:1 w:0) - // Storage: Uniques Account (r:0 w:1) + // Storage: Nfts Asset (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts CollectionMaxSupply (r:1 w:0) + // Storage: Nfts Account (r:0 w:1) fn mint() -> Weight { - Weight::from_ref_time(42_146_000 as u64) + Weight::from_ref_time(43_007_000 as u64) .saturating_add(RocksDbWeight::get().reads(3 as u64)) .saturating_add(RocksDbWeight::get().writes(3 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques Asset (r:1 w:1) - // Storage: Uniques Account (r:0 w:1) - // Storage: Uniques ItemPriceOf (r:0 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts Asset (r:1 w:1) + // Storage: Nfts Account (r:0 w:1) + // Storage: Nfts ItemPriceOf (r:0 w:1) fn burn() -> Weight { - Weight::from_ref_time(42_960_000 as u64) + Weight::from_ref_time(43_922_000 as u64) .saturating_add(RocksDbWeight::get().reads(2 as u64)) .saturating_add(RocksDbWeight::get().writes(4 as u64)) } - // Storage: Uniques Class (r:1 w:0) - // Storage: Uniques Asset (r:1 w:1) - // Storage: Uniques Account (r:0 w:2) - // Storage: Uniques ItemPriceOf (r:0 w:1) + // Storage: Nfts Class (r:1 w:0) + // Storage: Nfts Asset (r:1 w:1) + // Storage: Nfts Account (r:0 w:2) + // Storage: Nfts ItemPriceOf (r:0 w:1) fn transfer() -> Weight { - Weight::from_ref_time(33_025_000 as u64) + Weight::from_ref_time(33_951_000 as u64) .saturating_add(RocksDbWeight::get().reads(2 as u64)) .saturating_add(RocksDbWeight::get().writes(4 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques Asset (r:100 w:100) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts Asset (r:102 w:102) /// The range of component `i` is `[0, 5000]`. fn redeposit(i: u32, ) -> Weight { Weight::from_ref_time(0 as u64) - // Standard Error: 24_000 - .saturating_add(Weight::from_ref_time(15_540_000 as u64).saturating_mul(i as u64)) + // Standard Error: 12_000 + .saturating_add(Weight::from_ref_time(11_194_000 as u64).saturating_mul(i as u64)) .saturating_add(RocksDbWeight::get().reads(1 as u64)) .saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(i as u64))) .saturating_add(RocksDbWeight::get().writes(1 as u64)) .saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(i as u64))) } - // Storage: Uniques Asset (r:1 w:1) - // Storage: Uniques Class (r:1 w:0) + // Storage: Nfts Asset (r:1 w:1) + // Storage: Nfts Class (r:1 w:0) fn freeze() -> Weight { - Weight::from_ref_time(25_194_000 as u64) + Weight::from_ref_time(26_745_000 as u64) .saturating_add(RocksDbWeight::get().reads(2 as u64)) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } - // Storage: Uniques Asset (r:1 w:1) - // Storage: Uniques Class (r:1 w:0) + // Storage: Nfts Asset (r:1 w:1) + // Storage: Nfts Class (r:1 w:0) fn thaw() -> Weight { - Weight::from_ref_time(25_397_000 as u64) + Weight::from_ref_time(27_466_000 as u64) .saturating_add(RocksDbWeight::get().reads(2 as u64)) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } - // Storage: Uniques Class (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) fn freeze_collection() -> Weight { - Weight::from_ref_time(19_278_000 as u64) + Weight::from_ref_time(22_591_000 as u64) .saturating_add(RocksDbWeight::get().reads(1 as u64)) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } - // Storage: Uniques Class (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) fn thaw_collection() -> Weight { - Weight::from_ref_time(19_304_000 as u64) + Weight::from_ref_time(22_392_000 as u64) .saturating_add(RocksDbWeight::get().reads(1 as u64)) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } - // Storage: Uniques OwnershipAcceptance (r:1 w:1) - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques ClassAccount (r:0 w:2) + // Storage: Nfts OwnershipAcceptance (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts ClassAccount (r:0 w:2) fn transfer_ownership() -> Weight { - Weight::from_ref_time(28_615_000 as u64) + Weight::from_ref_time(31_202_000 as u64) .saturating_add(RocksDbWeight::get().reads(2 as u64)) .saturating_add(RocksDbWeight::get().writes(4 as u64)) } - // Storage: Uniques Class (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) fn set_team() -> Weight { - Weight::from_ref_time(19_943_000 as u64) + Weight::from_ref_time(23_063_000 as u64) .saturating_add(RocksDbWeight::get().reads(1 as u64)) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques ClassAccount (r:0 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts ClassAccount (r:0 w:1) fn force_item_status() -> Weight { - Weight::from_ref_time(22_583_000 as u64) + Weight::from_ref_time(25_598_000 as u64) .saturating_add(RocksDbWeight::get().reads(1 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques InstanceMetadataOf (r:1 w:0) - // Storage: Uniques Attribute (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts InstanceMetadataOf (r:1 w:0) + // Storage: Nfts Attribute (r:1 w:1) fn set_attribute() -> Weight { - Weight::from_ref_time(47_520_000 as u64) + Weight::from_ref_time(48_684_000 as u64) .saturating_add(RocksDbWeight::get().reads(3 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques InstanceMetadataOf (r:1 w:0) - // Storage: Uniques Attribute (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts InstanceMetadataOf (r:1 w:0) + // Storage: Nfts Attribute (r:1 w:1) fn clear_attribute() -> Weight { - Weight::from_ref_time(45_316_000 as u64) + Weight::from_ref_time(47_267_000 as u64) .saturating_add(RocksDbWeight::get().reads(3 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques InstanceMetadataOf (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts InstanceMetadataOf (r:1 w:1) fn set_metadata() -> Weight { - Weight::from_ref_time(38_391_000 as u64) + Weight::from_ref_time(40_174_000 as u64) .saturating_add(RocksDbWeight::get().reads(2 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques InstanceMetadataOf (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts InstanceMetadataOf (r:1 w:1) fn clear_metadata() -> Weight { - Weight::from_ref_time(38_023_000 as u64) + Weight::from_ref_time(41_611_000 as u64) .saturating_add(RocksDbWeight::get().reads(2 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } - // Storage: Uniques Class (r:1 w:1) - // Storage: Uniques ClassMetadataOf (r:1 w:1) + // Storage: Nfts Class (r:1 w:1) + // Storage: Nfts ClassMetadataOf (r:1 w:1) fn set_collection_metadata() -> Weight { - Weight::from_ref_time(37_398_000 as u64) + Weight::from_ref_time(40_073_000 as u64) .saturating_add(RocksDbWeight::get().reads(2 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } - // Storage: Uniques Class (r:1 w:0) - // Storage: Uniques ClassMetadataOf (r:1 w:1) + // Storage: Nfts Class (r:1 w:0) + // Storage: Nfts ClassMetadataOf (r:1 w:1) fn clear_collection_metadata() -> Weight { - Weight::from_ref_time(35_621_000 as u64) + Weight::from_ref_time(38_191_000 as u64) .saturating_add(RocksDbWeight::get().reads(2 as u64)) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } - // Storage: Uniques Class (r:1 w:0) - // Storage: Uniques Asset (r:1 w:1) + // Storage: Nfts Class (r:1 w:0) + // Storage: Nfts Asset (r:1 w:1) fn approve_transfer() -> Weight { - Weight::from_ref_time(25_856_000 as u64) + Weight::from_ref_time(29_461_000 as u64) .saturating_add(RocksDbWeight::get().reads(2 as u64)) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } - // Storage: Uniques Class (r:1 w:0) - // Storage: Uniques Asset (r:1 w:1) + // Storage: Nfts Class (r:1 w:0) + // Storage: Nfts Asset (r:1 w:1) fn cancel_approval() -> Weight { - Weight::from_ref_time(26_098_000 as u64) + Weight::from_ref_time(29_690_000 as u64) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } + // Storage: Nfts Class (r:1 w:0) + // Storage: Nfts Asset (r:1 w:1) + fn clear_all_transfer_approvals() -> Weight { + Weight::from_ref_time(27_758_000 as u64) .saturating_add(RocksDbWeight::get().reads(2 as u64)) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } - // Storage: Uniques OwnershipAcceptance (r:1 w:1) + // Storage: Nfts OwnershipAcceptance (r:1 w:1) fn set_accept_ownership() -> Weight { - Weight::from_ref_time(24_076_000 as u64) + Weight::from_ref_time(26_425_000 as u64) .saturating_add(RocksDbWeight::get().reads(1 as u64)) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } - // Storage: Uniques CollectionMaxSupply (r:1 w:1) - // Storage: Uniques Class (r:1 w:0) + // Storage: Nfts CollectionMaxSupply (r:1 w:1) + // Storage: Nfts Class (r:1 w:0) fn set_collection_max_supply() -> Weight { - Weight::from_ref_time(22_035_000 as u64) + Weight::from_ref_time(24_533_000 as u64) .saturating_add(RocksDbWeight::get().reads(2 as u64)) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } - // Storage: Uniques Asset (r:1 w:0) - // Storage: Uniques ItemPriceOf (r:0 w:1) + // Storage: Nfts Asset (r:1 w:0) + // Storage: Nfts ItemPriceOf (r:0 w:1) fn set_price() -> Weight { - Weight::from_ref_time(22_534_000 as u64) + Weight::from_ref_time(24_745_000 as u64) .saturating_add(RocksDbWeight::get().reads(1 as u64)) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } - // Storage: Uniques Asset (r:1 w:1) - // Storage: Uniques ItemPriceOf (r:1 w:1) - // Storage: Uniques Class (r:1 w:0) - // Storage: Uniques Account (r:0 w:2) + // Storage: Nfts Asset (r:1 w:1) + // Storage: Nfts ItemPriceOf (r:1 w:1) + // Storage: Nfts Class (r:1 w:0) + // Storage: Nfts Account (r:0 w:2) fn buy_item() -> Weight { - Weight::from_ref_time(45_272_000 as u64) + Weight::from_ref_time(47_967_000 as u64) .saturating_add(RocksDbWeight::get().reads(3 as u64)) .saturating_add(RocksDbWeight::get().writes(4 as u64)) }