Skip to content

Commit 87049f1

Browse files
committed
feat: nfts pallet optimization
1 parent 18704f1 commit 87049f1

11 files changed

+920
-619
lines changed

pallets/nfts/src/benchmarking.rs

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,27 @@ fn add_collection_metadata<T: Config<I>, I: 'static>() -> (T::AccountId, Account
6262
(caller, caller_lookup)
6363
}
6464

65+
fn approve_collection<T: Config<I>, I: 'static>(
66+
index: u32,
67+
) -> (T::AccountId, AccountIdLookupOf<T>) {
68+
let caller = Collection::<T, I>::get(T::Helper::collection(0)).unwrap().owner;
69+
if caller != whitelisted_caller() {
70+
whitelist_account!(caller);
71+
}
72+
let caller_lookup = T::Lookup::unlookup(caller.clone());
73+
let delegate: T::AccountId = account("delegate", 0, SEED + index);
74+
let delegate_lookup = T::Lookup::unlookup(delegate.clone());
75+
let deadline = BlockNumberFor::<T>::max_value();
76+
assert_ok!(Nfts::<T, I>::approve_transfer(
77+
SystemOrigin::Signed(caller.clone()).into(),
78+
T::Helper::collection(0),
79+
None,
80+
delegate_lookup.clone(),
81+
Some(deadline),
82+
));
83+
(caller, caller_lookup)
84+
}
85+
6586
fn mint_item<T: Config<I>, I: 'static>(
6687
index: u16,
6788
) -> (T::ItemId, T::AccountId, AccountIdLookupOf<T>) {
@@ -248,6 +269,8 @@ benchmarks_instance_pallet! {
248269
let m in 0 .. 1_000;
249270
let c in 0 .. 1_000;
250271
let a in 0 .. 1_000;
272+
let h in 0 .. 1_000;
273+
let l in 0 .. 1_000;
251274

252275
let (collection, caller, _) = create_collection::<T, I>();
253276
add_collection_metadata::<T, I>();
@@ -265,6 +288,13 @@ benchmarks_instance_pallet! {
265288
for i in 0..a {
266289
add_collection_attribute::<T, I>(i as u16);
267290
}
291+
for i in 0..h {
292+
mint_item::<T, I>(i as u16);
293+
burn_item::<T, I>(i as u16);
294+
}
295+
for i in 0..l {
296+
approve_collection::<T, I>(i);
297+
}
268298
let witness = Collection::<T, I>::get(collection).unwrap().destroy_witness();
269299
}: _(SystemOrigin::Signed(caller), collection, witness)
270300
verify {
@@ -571,27 +601,45 @@ benchmarks_instance_pallet! {
571601
}
572602

573603
approve_transfer {
604+
let i in 0..1;
605+
574606
let (collection, caller, _) = create_collection::<T, I>();
575607
let (item, ..) = mint_item::<T, I>(0);
576608
let delegate: T::AccountId = account("delegate", 0, SEED);
577609
let delegate_lookup = T::Lookup::unlookup(delegate.clone());
578-
let deadline = BlockNumberFor::<T>::max_value();
579-
}: _(SystemOrigin::Signed(caller.clone()), collection, item, delegate_lookup, Some(deadline))
610+
let maybe_deadline = if i == 0 {
611+
None
612+
} else {
613+
Some(BlockNumberFor::<T>::max_value())
614+
};
615+
let maybe_item = if i == 0 {
616+
None
617+
} else {
618+
Some(item)
619+
};
620+
}: _(SystemOrigin::Signed(caller.clone()), collection, maybe_item, delegate_lookup, maybe_deadline)
580621
verify {
581-
assert_last_event::<T, I>(Event::TransferApproved { collection, item, owner: caller, delegate, deadline: Some(deadline) }.into());
622+
assert_last_event::<T, I>(Event::TransferApproved { collection, item: maybe_item, owner: caller, delegate, deadline: maybe_deadline }.into());
582623
}
583624

584625
cancel_approval {
626+
let i in 0..1;
627+
585628
let (collection, caller, _) = create_collection::<T, I>();
586629
let (item, ..) = mint_item::<T, I>(0);
587630
let delegate: T::AccountId = account("delegate", 0, SEED);
588631
let delegate_lookup = T::Lookup::unlookup(delegate.clone());
589632
let origin = SystemOrigin::Signed(caller.clone()).into();
590633
let deadline = BlockNumberFor::<T>::max_value();
591-
Nfts::<T, I>::approve_transfer(origin, collection, item, delegate_lookup.clone(), Some(deadline))?;
592-
}: _(SystemOrigin::Signed(caller.clone()), collection, item, delegate_lookup)
634+
let maybe_item = if i == 0 {
635+
None
636+
} else {
637+
Some(item)
638+
};
639+
Nfts::<T, I>::approve_transfer(origin, collection, maybe_item, delegate_lookup.clone(), Some(deadline))?;
640+
}: _(SystemOrigin::Signed(caller.clone()), collection, maybe_item, delegate_lookup)
593641
verify {
594-
assert_last_event::<T, I>(Event::ApprovalCancelled { collection, item, owner: caller, delegate }.into());
642+
assert_last_event::<T, I>(Event::ApprovalCancelled { collection, item: maybe_item, owner: caller, delegate }.into());
595643
}
596644

597645
clear_all_transfer_approvals {
@@ -601,7 +649,7 @@ benchmarks_instance_pallet! {
601649
let delegate_lookup = T::Lookup::unlookup(delegate.clone());
602650
let origin = SystemOrigin::Signed(caller.clone()).into();
603651
let deadline = BlockNumberFor::<T>::max_value();
604-
Nfts::<T, I>::approve_transfer(origin, collection, item, delegate_lookup.clone(), Some(deadline))?;
652+
Nfts::<T, I>::approve_transfer(origin, collection, Some(item), delegate_lookup.clone(), Some(deadline))?;
605653
}: _(SystemOrigin::Signed(caller.clone()), collection, item)
606654
verify {
607655
assert_last_event::<T, I>(Event::AllApprovalsCancelled {collection, item, owner: caller}.into());

pallets/nfts/src/common_functions.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,24 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
3434
Collection::<T, I>::get(collection).map(|i| i.owner)
3535
}
3636

37+
/// Get the total number of items in the collection, if the collection exists.
38+
pub fn collection_items(collection: T::CollectionId) -> Option<u32> {
39+
Collection::<T, I>::get(collection).map(|i| i.items)
40+
}
41+
42+
/// Get the allowances to spend items within the collection.
43+
pub fn collection_allowances(collection: T::CollectionId) -> Option<u32> {
44+
Collection::<T, I>::get(collection).map(|i| i.allowances)
45+
}
46+
47+
/// Get the metadata of the collection item.
48+
pub fn item_metadata(
49+
collection: T::CollectionId,
50+
item: T::ItemId,
51+
) -> Option<BoundedVec<u8, T::StringLimit>> {
52+
ItemMetadataOf::<T, I>::get(collection, item).map(|metadata| metadata.data)
53+
}
54+
3755
/// Validates the signature of the given data with the provided signer's account ID.
3856
///
3957
/// # Errors

pallets/nfts/src/features/approvals.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
6464
if let Some(check_origin) = maybe_check_origin {
6565
ensure!(check_origin == details.owner, Error::<T, I>::NoPermission);
6666
}
67-
6867
let now = frame_system::Pallet::<T>::block_number();
6968
let deadline = maybe_deadline.map(|d| d.saturating_add(now));
7069

@@ -75,12 +74,11 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
7574
Item::<T, I>::insert(collection, item, &details);
7675
Self::deposit_event(Event::TransferApproved {
7776
collection,
78-
item,
77+
item: Some(item),
7978
owner: details.owner,
8079
delegate,
8180
deadline,
8281
});
83-
8482
Ok(())
8583
}
8684

@@ -126,7 +124,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
126124

127125
Self::deposit_event(Event::ApprovalCancelled {
128126
collection,
129-
item,
127+
item: Some(item),
130128
owner: details.owner,
131129
delegate,
132130
});

pallets/nfts/src/features/create_delete_collection.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
5454
items: 0,
5555
item_metadatas: 0,
5656
item_configs: 0,
57+
item_holders: 0,
5758
attributes: 0,
59+
allowances: 0,
5860
},
5961
);
6062
CollectionRoleOf::<T, I>::insert(
@@ -119,6 +121,11 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
119121
collection_details.item_configs == witness.item_configs,
120122
Error::<T, I>::BadWitness
121123
);
124+
ensure!(
125+
collection_details.item_holders == witness.item_holders,
126+
Error::<T, I>::BadWitness
127+
);
128+
ensure!(collection_details.allowances == witness.allowances, Error::<T, I>::BadWitness);
122129

123130
for (_, metadata) in ItemMetadataOf::<T, I>::drain_prefix(collection) {
124131
if let Some(depositor) = metadata.deposit.account {
@@ -137,6 +144,9 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
137144
}
138145
}
139146

147+
let _ =
148+
AccountBalance::<T, I>::clear_prefix(collection, collection_details.items, None);
149+
let _ = Allowances::<T, I>::clear_prefix((collection,), collection_details.items, None);
140150
CollectionAccount::<T, I>::remove(&collection_details.owner, &collection);
141151
T::Currency::unreserve(&collection_details.owner, collection_details.owner_deposit);
142152
CollectionConfigOf::<T, I>::remove(collection);
@@ -147,7 +157,9 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
147157
Ok(DestroyWitness {
148158
item_metadatas: collection_details.item_metadatas,
149159
item_configs: collection_details.item_configs,
160+
item_holders: collection_details.item_holders,
150161
attributes: collection_details.attributes,
162+
allowances: collection_details.allowances,
151163
})
152164
})
153165
}

pallets/nfts/src/features/create_delete_item.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
259259
}
260260
}
261261

262+
if AccountBalance::<T, I>::get(collection, &details.owner) == 1 {
263+
collection_details.item_holders.saturating_dec();
264+
}
265+
262266
Ok(details.owner)
263267
},
264268
)?;
@@ -268,6 +272,9 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
268272
ItemPriceOf::<T, I>::remove(&collection, &item);
269273
PendingSwapOf::<T, I>::remove(&collection, &item);
270274
ItemAttributesApprovalsOf::<T, I>::remove(&collection, &item);
275+
AccountBalance::<T, I>::mutate(collection, &owner, |balance| {
276+
balance.saturating_dec();
277+
});
271278

272279
if remove_config {
273280
ItemConfigOf::<T, I>::remove(collection, item);

pallets/nfts/src/features/transfer.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
5454
) -> DispatchResult,
5555
) -> DispatchResult {
5656
// Retrieve collection details.
57-
let collection_details =
57+
let mut collection_details =
5858
Collection::<T, I>::get(&collection).ok_or(Error::<T, I>::UnknownCollection)?;
5959

6060
// Ensure the item is not locked.
@@ -86,6 +86,24 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
8686
// Perform the transfer with custom details using the provided closure.
8787
with_details(&collection_details, &mut details)?;
8888

89+
// Update account balance of the owner.
90+
let owner_balance =
91+
AccountBalance::<T, I>::mutate(collection, &details.owner, |balance| -> u32 {
92+
balance.saturating_dec();
93+
*balance
94+
});
95+
if owner_balance == 0 {
96+
collection_details.item_holders.saturating_dec();
97+
}
98+
// Update account balance of the destination account.
99+
let dest_balance = AccountBalance::<T, I>::mutate(collection, &dest, |balance| -> u32 {
100+
balance.saturating_inc();
101+
*balance
102+
});
103+
if dest_balance == 1 {
104+
collection_details.item_holders.saturating_inc();
105+
}
106+
89107
// Update account ownership information.
90108
Account::<T, I>::remove((&details.owner, &collection, &item));
91109
Account::<T, I>::insert((&dest, &collection, &item), ());

0 commit comments

Comments
 (0)