Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(pallet-nfts): optimization #387

Open
wants to merge 102 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 97 commits
Commits
Show all changes
102 commits
Select commit Hold shift + click to select a range
c503f86
chore: fork pallet nfts
chungquantin Nov 13, 2024
b9fe4d8
chore: resolve feedback
chungquantin Nov 16, 2024
b63eda9
feat: nfts pallet optimization
chungquantin Nov 19, 2024
2c1fe5b
chore: fork pallet nfts (#382)
chungquantin Nov 18, 2024
b0fbeb3
chore: fork pallet nfts
chungquantin Nov 13, 2024
98217ae
chore: resolve feedback
chungquantin Nov 16, 2024
d954c70
feat: nfts pallet optimization
chungquantin Nov 19, 2024
b76dc4d
chore: fork pallet nfts (#382)
chungquantin Nov 18, 2024
aa829a7
Merge remote-tracking branch 'refs/remotes/origin/chungquantin/feat-n…
chungquantin Nov 19, 2024
9d1658e
feat: add new storage items and optimize
chungquantin Nov 19, 2024
69dd5f8
chore: resolve feedback
chungquantin Nov 19, 2024
4a5f17c
fix(nfts): clippy warnings
chungquantin Nov 21, 2024
37ec9ab
fix: clippy warnings
chungquantin Nov 21, 2024
3e886a9
fix: warnings
chungquantin Nov 22, 2024
8170b26
fix(nfts): rebase `feat-nfts` branch to fix clippy warnings (#392)
chungquantin Nov 22, 2024
363d06f
Merge branch 'chungquantin/fix-nfts_clippy' into chungquantin/feat-nfts
chungquantin Nov 22, 2024
f815bf2
fix: reformatting
chungquantin Nov 22, 2024
51bc52f
fix: remove unused storage fields from CollectionDetails (#393)
chungquantin Nov 22, 2024
8479203
Merge branch 'main' into chungquantin/feat-nfts
chungquantin Nov 22, 2024
d145029
fix: add comment & refactor cancel_collection
chungquantin Nov 22, 2024
0e1c2ab
chore: remove newline changes
chungquantin Nov 22, 2024
73f04da
chore: add comment for check allowance
chungquantin Nov 22, 2024
e8c5685
chore: register pallet_nfts benchmark
chungquantin Nov 22, 2024
a66ea2a
refactor(nfts): mapping with `ApprovalsOf` in the `Allowances` storag…
chungquantin Nov 26, 2024
cee5933
fix: weight path
chungquantin Nov 26, 2024
c7314c5
test: update pallet tests
chungquantin Nov 26, 2024
4b19ab5
test: expand cancel_approval test
chungquantin Nov 26, 2024
da2dc1c
refactor: do_approve_collection
chungquantin Nov 26, 2024
9dfe652
refactor: storate item names
chungquantin Nov 26, 2024
b39f1a1
refactor: allowances to approvals
chungquantin Nov 26, 2024
37b869a
refactor: approval methods
chungquantin Nov 26, 2024
a96a1f5
refactor: benchmarking
chungquantin Nov 26, 2024
5615f1b
chore: update weight file
chungquantin Nov 26, 2024
b7d620e
fix: resolve comments & collection approvals logic (#395)
chungquantin Nov 27, 2024
7b5e201
feat(nfts): collection approval deposit
chungquantin Nov 27, 2024
6cb7f05
refactor: update account balance in do_transfer()
chungquantin Nov 27, 2024
056ebc3
fix: clippy warnings
chungquantin Nov 27, 2024
0cba5fc
chore: update weights
chungquantin Nov 28, 2024
096e09c
fix: comments
chungquantin Nov 28, 2024
6ef07eb
chore: test no_account constant
chungquantin Nov 28, 2024
7f7a40f
refactor: remove `CollectionApprovalCount` storage item (#396)
chungquantin Nov 29, 2024
71d9d5c
fix: comments & test
chungquantin Nov 29, 2024
fe924ee
chore: check bad witness
chungquantin Nov 29, 2024
fa360a8
fix: test
chungquantin Nov 29, 2024
8d5155b
chore: resolve review comments (#398)
chungquantin Dec 2, 2024
9f6e159
fix: comments
chungquantin Dec 2, 2024
924d2d3
chore: update weights
chungquantin Dec 2, 2024
a9c2014
chore: comments & tests
chungquantin Dec 2, 2024
4404716
refactor: force origin
chungquantin Dec 3, 2024
0f1d960
chore: update weights
chungquantin Dec 4, 2024
e1226d6
chore: comments
chungquantin Dec 4, 2024
67f422a
chore: add integrity test
chungquantin Dec 4, 2024
60122d9
chore: update comment
chungquantin Dec 4, 2024
7d9c48f
chore: update comments
chungquantin Dec 4, 2024
e1b2b62
chore: update comments
chungquantin Dec 4, 2024
0656b4e
chore: resolve comments
chungquantin Dec 4, 2024
92d98ec
chore: add variables to tests
chungquantin Dec 5, 2024
b40d585
fix: tests
chungquantin Dec 5, 2024
86fcfa3
refactor: check_approval test
chungquantin Dec 5, 2024
62cd8fa
refactor: benchmarking code
chungquantin Dec 5, 2024
2acb01b
fix: tests
chungquantin Dec 5, 2024
ba33b7c
chore: revert clear_collection_approvals
chungquantin Dec 6, 2024
824978d
docs: pallet-nfts (#399)
chungquantin Dec 6, 2024
9b42bb7
refactor: approve_collection deposit
chungquantin Dec 6, 2024
f68a28e
chore: resolve review comments
chungquantin Dec 6, 2024
1da978d
refactor: clear_collection_approvals
chungquantin Dec 6, 2024
5b639f7
fix: comments
chungquantin Dec 6, 2024
1afd4ba
fix: comment
chungquantin Dec 6, 2024
672ceae
refactor: transfer_should_workd
chungquantin Dec 6, 2024
c62dd83
Revert "refactor: transfer_should_workd"
chungquantin Dec 6, 2024
c76f66b
chore: comments
chungquantin Dec 9, 2024
8f1c56d
chore: resolve review comments
chungquantin Dec 9, 2024
627a0e6
chore: update README
chungquantin Dec 10, 2024
4535a52
chore: comments
chungquantin Dec 10, 2024
6eb8928
refactor: test check_approval (#403)
Daanvdplas Dec 11, 2024
25e58d3
chore: resolve feedback comments (#404)
chungquantin Dec 11, 2024
ca27938
chore: fix comment
chungquantin Dec 11, 2024
fafb988
chore: update weight and test
chungquantin Dec 12, 2024
e88b6ad
chore: remove TODO
chungquantin Dec 12, 2024
abc54e8
chore: resolve comments
chungquantin Dec 12, 2024
6ef9b32
chore: verify benchmarks with storage checks
chungquantin Dec 13, 2024
0076a3b
refactor: tests (#405)
Daanvdplas Dec 13, 2024
4cd8dd5
chore: revert formatting
chungquantin Dec 13, 2024
2ea60c0
chore: revert unnecessary change
chungquantin Dec 16, 2024
829b433
refactor: dispatchables & events
chungquantin Dec 16, 2024
9af5e24
chore: add new field in ApprovalsCancelled and refactored events
chungquantin Dec 16, 2024
87aa08e
chore: comments
chungquantin Dec 16, 2024
c1b46c1
chore: remove zero collection approvals
chungquantin Dec 16, 2024
11d60a1
chore: resolve comments
chungquantin Dec 17, 2024
24c0c2d
chore: revert test changes
chungquantin Dec 18, 2024
cac4bed
chore: update tests
chungquantin Dec 30, 2024
4b4cd22
chore: update tests
chungquantin Dec 31, 2024
97450fa
chore: apply suggestion
chungquantin Dec 31, 2024
881a04c
refactor: tests for collection approval (#419)
Daanvdplas Jan 7, 2025
504d0f0
feat: allow admin to force cancel approvals
chungquantin Jan 9, 2025
1158143
chore: rename destroy test method
chungquantin Jan 9, 2025
05c16f7
feat: allow admin to force cancel approvals
chungquantin Jan 9, 2025
68a86c6
refactor: force_cancel_collection_approval_works_with_admin
chungquantin Jan 9, 2025
1cdad44
feat(nfts): `AccountBalance` deposit (#413)
chungquantin Jan 9, 2025
5d350b1
fix: deposit saturation
chungquantin Jan 10, 2025
3e2620a
chore: revert admin permission on collection approvals
chungquantin Jan 10, 2025
f83bdc5
feat: not require deposit for force_approve_collection_transfer
chungquantin Jan 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pallets/nfts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ The NFTs pallet in Substrate is designed to make the following possible:
* `transfer`: Send an item to a new owner.
* `redeposit`: Update the deposit amount of an item, potentially freeing funds.
* `approve_transfer`: Name a delegate who may authorize a transfer.
* `approve_collection_transfer`: Name a delegate who may authorize a transfer of all collection items owned by the account.
* `cancel_approval`: Revert the effects of a previous `approve_transfer`.
* `cancel_collection_approval`: Revert the effects of a previous `approve_collection_transfer`.
* `approve_item_attributes`: Name a delegate who may change item's attributes within a namespace.
* `cancel_item_attributes_approval`: Revert the effects of a previous `approve_item_attributes`.
* `set_price`: Set the price for an item.
Expand All @@ -70,6 +72,7 @@ The NFTs pallet in Substrate is designed to make the following possible:
* `lock_item_transfer`: Prevent an individual item from being transferred.
* `unlock_item_transfer`: Revert the effects of a previous `lock_item_transfer`.
* `clear_all_transfer_approvals`: Clears all transfer approvals set by calling the `approve_transfer`.
* `clear_collection_approvals`: Clears collection approvals set by calling the `approve_collection_transfer`.
* `lock_collection`: Prevent all items within a collection from being transferred (making them all `soul bound`).
* `lock_item_properties`: Lock item's metadata or attributes.
* `transfer_ownership`: Alter the owner of a collection, moving all associated deposits. (Ownership of individual items
Expand All @@ -95,6 +98,9 @@ The NFTs pallet in Substrate is designed to make the following possible:
* `force_collection_owner`: Change collection's owner.
* `force_collection_config`: Change collection's config.
* `force_set_attribute`: Set an attribute.
* `force_approve_collection_transfer`: Name a delegate who may authorize a transfer of all collection items owned by the specified account.
* `force_cancel_collection_approval`: Revert the effects of a previous `approve_collection_transfer`.
* `force_clear_collection_approvals`: Revert the effects of all previous `approve_collection_transfer` calls for the collection.

Please refer to the [`Call`](https://paritytech.github.io/substrate/master/pallet_nfts/pallet/enum.Call.html) enum and
its associated variants for documentation on each function.
Expand Down
89 changes: 87 additions & 2 deletions pallets/nfts/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ benchmarks_instance_pallet! {
let deadline = BlockNumberFor::<T>::max_value();
}: _(SystemOrigin::Signed(caller.clone()), collection, item, delegate_lookup, Some(deadline))
verify {
assert_last_event::<T, I>(Event::TransferApproved { collection, item, owner: caller, delegate, deadline: Some(deadline) }.into());
assert_last_event::<T, I>(Event::TransferApproved { collection, item: Some(item), owner: caller, delegate, deadline: Some(deadline) }.into());
}

cancel_approval {
Expand All @@ -591,7 +591,7 @@ benchmarks_instance_pallet! {
Nfts::<T, I>::approve_transfer(origin, collection, item, delegate_lookup.clone(), Some(deadline))?;
}: _(SystemOrigin::Signed(caller.clone()), collection, item, delegate_lookup)
verify {
assert_last_event::<T, I>(Event::ApprovalCancelled { collection, item, owner: caller, delegate }.into());
assert_last_event::<T, I>(Event::ApprovalCancelled { collection, item: Some(item), owner: caller, delegate }.into());
}

clear_all_transfer_approvals {
Expand Down Expand Up @@ -876,5 +876,90 @@ benchmarks_instance_pallet! {
);
}

approve_collection_transfer {
let (collection, caller, _) = create_collection::<T, I>();
mint_item::<T, I>(0);
let delegate: T::AccountId = account("delegate", 0, SEED);
let delegate_lookup = T::Lookup::unlookup(delegate.clone());
let deadline = BlockNumberFor::<T>::max_value();
}: _(SystemOrigin::Signed(caller.clone()), collection, delegate_lookup, Some(deadline))
verify {
assert_last_event::<T, I>(Event::TransferApproved { collection, item: None, owner: caller, delegate, deadline: Some(deadline) }.into());
}

force_approve_collection_transfer {
let (collection, caller, caller_lookup) = create_collection::<T, I>();
mint_item::<T, I>(0);
let delegate: T::AccountId = account("delegate", 0, SEED);
let delegate_lookup = T::Lookup::unlookup(delegate.clone());
let deadline = BlockNumberFor::<T>::max_value();
}: _(SystemOrigin::Root, caller_lookup, collection, delegate_lookup, Some(deadline))
verify {
assert_last_event::<T, I>(Event::TransferApproved { collection, item: None, owner: caller, delegate, deadline: Some(deadline) }.into());
}

cancel_collection_approval {
let (collection, caller, _) = create_collection::<T, I>();
mint_item::<T, I>(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 = BlockNumberFor::<T>::max_value();
Nfts::<T, I>::approve_collection_transfer(origin, collection, delegate_lookup.clone(), Some(deadline))?;
}: _(SystemOrigin::Signed(caller.clone()), collection, delegate_lookup)
verify {
assert_last_event::<T, I>(Event::ApprovalCancelled { collection, item: None, owner: caller, delegate }.into());
}

force_cancel_collection_approval {
let (collection, caller, caller_lookup) = create_collection::<T, I>();
mint_item::<T, I>(0);
let delegate: T::AccountId = account("delegate", 0, SEED);
let delegate_lookup = T::Lookup::unlookup(delegate.clone());
let deadline = BlockNumberFor::<T>::max_value();
Nfts::<T, I>::approve_collection_transfer(SystemOrigin::Signed(caller.clone()).into(), collection, delegate_lookup.clone(), Some(deadline))?;
}: _(SystemOrigin::Root, caller_lookup, collection, delegate_lookup)
verify {
assert_last_event::<T, I>(Event::ApprovalCancelled { collection, item: None, owner: caller, delegate }.into());
}

clear_collection_approvals {
let n in 1 .. 1_000;
let (collection, caller, _) = create_collection::<T, I>();
mint_item::<T, I>(0);
for i in 0 .. n {
let delegate: T::AccountId = account("delegate", i, SEED);
Nfts::<T, I>::approve_collection_transfer(
SystemOrigin::Signed(caller.clone()).into(),
collection,
T::Lookup::unlookup(delegate),
Some(BlockNumberFor::<T>::max_value()),
)?;
}
}: _(SystemOrigin::Signed(caller.clone()), collection, n)
verify {
assert_last_event::<T, I>(Event::ApprovalsCancelled {collection, owner: caller.clone(), approvals: n}.into());
assert!(CollectionApprovals::<T, I>::iter_prefix((collection, caller,)).take(1).next().is_none());
}

force_clear_collection_approvals {
let n in 1 .. 1_000;
let (collection, caller, caller_lookup) = create_collection::<T, I>();
mint_item::<T, I>(0);
for i in 0 .. n {
let delegate: T::AccountId = account("delegate", i, SEED);
Nfts::<T, I>::approve_collection_transfer(
SystemOrigin::Signed(caller.clone()).into(),
collection,
T::Lookup::unlookup(delegate),
Some(BlockNumberFor::<T>::max_value()),
)?;
}
}: _(SystemOrigin::Root, caller_lookup, collection, n)
verify {
assert_last_event::<T, I>(Event::ApprovalsCancelled {collection, owner: caller.clone(), approvals: n}.into());
assert!(CollectionApprovals::<T, I>::iter_prefix((collection, caller,)).take(1).next().is_none());
}

impl_benchmark_test_suite!(Nfts, crate::mock::new_test_ext(), crate::mock::Test);
}
23 changes: 23 additions & 0 deletions pallets/nfts/src/common_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,38 @@ use crate::*;

impl<T: Config<I>, I: 'static> Pallet<T, I> {
/// Get the owner of the item, if the item exists.
///
/// - `collection`: The identifier of the collection.
/// - `item`: The identifier of the collection item.
pub fn owner(collection: T::CollectionId, item: T::ItemId) -> Option<T::AccountId> {
Item::<T, I>::get(collection, item).map(|i| i.owner)
}

/// Get the owner of the collection, if the collection exists.
///
/// - `collection`: The identifier of the collection.
pub fn collection_owner(collection: T::CollectionId) -> Option<T::AccountId> {
Collection::<T, I>::get(collection).map(|i| i.owner)
}

/// Get the total number of items in the collection, if the collection exists.
chungquantin marked this conversation as resolved.
Show resolved Hide resolved
///
/// - `collection`: The identifier of the collection.
pub fn collection_items(collection: T::CollectionId) -> Option<u32> {
Collection::<T, I>::get(collection).map(|i| i.items)
}

/// Get the metadata of the collection item.
///
/// - `collection`: The identifier of the collection.
/// - `item`: The identifier of the collection item.
pub fn item_metadata(
collection: T::CollectionId,
item: T::ItemId,
) -> Option<BoundedVec<u8, T::StringLimit>> {
ItemMetadataOf::<T, I>::get(collection, item).map(|metadata| metadata.data)
}

/// Validates the signature of the given data with the provided signer's account ID.
///
/// # Errors
Expand Down
Loading
Loading