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(nfts): AccountBalance deposit #413

Merged
merged 45 commits into from
Jan 9, 2025

Conversation

chungquantin
Copy link
Collaborator

@chungquantin chungquantin commented Dec 18, 2024

Problem

This PR addresses the deposit issue with the AccountBalance storage type as outlined in #387. Currently, storage for each AccountBalance record created does not reserve the necessary deposit. Below are the cases where AccountBalance records are created or destroyed:

Related Functions

  • do_mint: Creates an AccountBalance record for mint_to when a new collection item is minted.
  • do_transfer: Transfers a collection item from the owner to the dest account. If the dest account does not have enough balance (including does not exist), an AccountBalance record is created. If the sender's AccountBalance becomes zero after the transfer, their AccountBalance record is removed.
  • do_burn: Removes the AccountBalance of the owner, if they only have one item and that item is burned.
  • do_mint_pre_signed: Calls do_mint.

Description for do_mint_pre_signed: This function allows minting a new item using a pre-signed message. The minting process is similar to the regular minting process, but it is performed by a pre-authorized account. The mint_to account receives the newly minted item. The minting process is configurable through the provided mint_data. The attributes, metadata, and price of the item are set according to the provided mint_data. The with_details_and_config closure is called to validate the provided collection_details and collection_config before minting the item.

  • do_buy_item: Calls do_transfer to transfer an item from the seller to the buyer.
  • do_claim_swap: Calls do_transfer twice—once to transfer from A to B, and then from B to A.

Solution

Refactor the AccountBalance storage value type to store a tuple (u32, AccountDepositOf<T>), representing:

  • u32: Tracks the total number of items in the collection owned by the account.
  • AccountDepositOf<T>: A tuple of (AccountId, DepositBalance)
    • AccountId: The depositor who reserves funds for creating the AccountBalance record.
    • DepositBalance: The amount reserved from the depositor for creating the AccountBalance record.

Reserve Logic

  • do_mint:

    • Depositor = Collection owner.
    • If minting to a new mint_to account, the collection owner reserves the funds to create the AccountBalance record.
    • If the account already exists in AccountBalance, the value of AccountBalance is simply incremented.
  • do_transfer:

    • Depositor = Provided depositor or the transferred collection item owner.
    • Decrements the AccountBalance of the sender and increments that of the recipient.
    • If transferring to a non-existing destination account (dest), the depositor or the collection item owner (if provided) reserves the funds to create the AccountBalance record.
    • If the destination account already exists, the account itself is responsible for reserving the funds for its AccountBalance record.
  • do_buy_item: Call do_transfer with the caller as the buyer account.

  • do_claim_swap:

    • Executes two do_transfer operations:
      1. From A to B: Call do_transfer with the depositor as the receive_item.owner
      2. From B to A: Call do_transfer with the caller as the send_item.owner

Unreserve Logic

  • do_transfer:
    • Decrements the AccountBalance of the sender account.
    • If the sender's AccountBalance value reaches zero, the AccountBalance is removed, and the deposited funds are unreserved and returned to the depositor.
  • do_burn:
    • Decrements the AccountBalance of the item owner.
    • If the owner's AccountBalance value reaches zero, the AccountBalance is removed, and the deposited funds are unreserved and returned to the depositor.

@chungquantin chungquantin changed the title refactor: account balance deposit refactor(nfts): AccountBalance deposit Dec 19, 2024
@chungquantin chungquantin self-assigned this Dec 19, 2024
@codecov-commenter
Copy link

codecov-commenter commented Dec 19, 2024

Codecov Report

Attention: Patch coverage is 53.28467% with 320 lines in your changes missing coverage. Please review.

Project coverage is 71.38%. Comparing base (881a04c) to head (d5b1a02).

Files with missing lines Patch % Lines
pallets/nfts/src/weights.rs 6.66% 308 Missing ⚠️
pallets/nfts/src/impl_nonfungibles.rs 0.00% 5 Missing ⚠️
pallets/nfts/src/features/create_delete_item.rs 83.33% 0 Missing and 3 partials ⚠️
pallets/nfts/src/features/transfer.rs 81.81% 0 Missing and 2 partials ⚠️
pallets/nfts/src/common_functions.rs 99.04% 0 Missing and 1 partial ⚠️
pallets/nfts/src/features/atomic_swap.rs 87.50% 0 Missing and 1 partial ⚠️
@@                    Coverage Diff                     @@
##           chungquantin/feat-nfts     #413      +/-   ##
==========================================================
+ Coverage                   70.93%   71.38%   +0.45%     
==========================================================
  Files                          72       72              
  Lines                       13313    13561     +248     
  Branches                    13313    13561     +248     
==========================================================
+ Hits                         9443     9680     +237     
- Misses                       3600     3608       +8     
- Partials                      270      273       +3     
Files with missing lines Coverage Δ
pallets/nfts/src/benchmarking.rs 85.79% <ø> (ø)
pallets/nfts/src/features/approvals.rs 96.19% <100.00%> (+0.07%) ⬆️
pallets/nfts/src/features/buy_sell.rs 90.69% <100.00%> (ø)
pallets/nfts/src/lib.rs 71.85% <100.00%> (+0.33%) ⬆️
pallets/nfts/src/mock.rs 100.00% <ø> (ø)
pallets/nfts/src/tests.rs 99.91% <100.00%> (+<0.01%) ⬆️
pallets/nfts/src/types.rs 67.11% <ø> (ø)
runtime/devnet/src/config/assets.rs 100.00% <100.00%> (ø)
runtime/testnet/src/config/assets.rs 100.00% <100.00%> (ø)
pallets/nfts/src/common_functions.rs 90.25% <99.04%> (+18.83%) ⬆️
... and 5 more

@chungquantin
Copy link
Collaborator Author

[sc-1989]

@chungquantin chungquantin force-pushed the frank/nfts-balance-deposit branch from 72cddd5 to 5015e90 Compare December 19, 2024 07:59
Copy link
Collaborator

@evilrobot-01 evilrobot-01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking nice and clean! Have made some improvement suggestions, mostly minor, along with a few general questions.

Note that I did not review the tests yet owing to time. I took a quick look at https://app.codecov.io/gh/r0gue-io/pop-node/pull/413 and it seems as though there is some stuff added which is not covered by tests. They might be false positives, but please could you double check? I will check the tests on the next pass and then we should be good to go from my perspective.

pallets/nfts/src/lib.rs Outdated Show resolved Hide resolved
pallets/nfts/src/benchmarking.rs Outdated Show resolved Hide resolved
pallets/nfts/src/benchmarking.rs Outdated Show resolved Hide resolved
pallets/nfts/src/common_functions.rs Outdated Show resolved Hide resolved
pallets/nfts/src/common_functions.rs Outdated Show resolved Hide resolved
@@ -795,19 +799,21 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
/// Storage: `Nfts::ItemConfigOf` (r:2 w:0)
/// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`)
/// Storage: `Nfts::AccountBalance` (r:2 w:2)
/// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`)
/// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:1 w:1)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above.

Copy link
Collaborator Author

@chungquantin chungquantin Dec 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: Interesting to see that there is only 1 read and 1 write to the System::Account. From my understanding, the do_transfer is called twice from A to B and then B to A so it must be 2 reads and 2 writes.

Answer: Confirmed that this is correct. The claim_swap() method is called by caller while caller is allowlisted. Hence, there is no read / write taken on the caller account. Break it down we have:

  • Transfer from caller to destination: Read destination and write to dest because it has sufficient balance.
  • Transfer from destination to caller: Read caller and write to the caller because it has sufficient balance. (ignore read / write)

pallets/nfts/src/weights.rs Show resolved Hide resolved
pallets/nfts/src/weights.rs Outdated Show resolved Hide resolved
runtime/devnet/src/config/assets.rs Outdated Show resolved Hide resolved
runtime/testnet/src/config/assets.rs Outdated Show resolved Hide resolved
@al3mart
Copy link
Collaborator

al3mart commented Dec 20, 2024

I'll dedicate more time later to do a proper review, but reserve and unreserve logic seems solid.

Before I was more of the opinion of centralizing the responsibilities for the existence of the assets into the minter / owner of the collection.

But I gotta say that I'm pretty convinced with the current approach. For instance moving DepositBalance on transfers could be pretty beneficial for the asset creators. Being able to absorb a cost up front that is later shared with their users might be a pretty good incentive.

@chungquantin chungquantin force-pushed the frank/nfts-balance-deposit branch from 29988be to d3ae740 Compare December 22, 2024 05:20
@chungquantin chungquantin force-pushed the frank/nfts-balance-deposit branch from 08c9259 to 6c8d5b6 Compare December 31, 2024 03:40
@chungquantin chungquantin force-pushed the chungquantin/feat-nfts branch 2 times, most recently from dc2c68f to 4b4cd22 Compare December 31, 2024 03:57
@chungquantin chungquantin force-pushed the frank/nfts-balance-deposit branch from 6c8d5b6 to df965e1 Compare December 31, 2024 04:05
Copy link
Collaborator

@peterwht peterwht left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall pretty clean! Was nice diving into the NFT pallets some. However, there is a security flaw introduced with transfer. Please review comments.

Also, can we please rename the PR title to feat(nfts): AccountBalance deposit. We are introducing new functionality, so it should be a feature.

pallets/nfts/src/common_functions.rs Outdated Show resolved Hide resolved
pallets/nfts/src/lib.rs Show resolved Hide resolved
pallets/nfts/src/lib.rs Show resolved Hide resolved
pallets/nfts/src/features/approvals.rs Outdated Show resolved Hide resolved
pallets/nfts/src/lib.rs Outdated Show resolved Hide resolved
pallets/nfts/src/features/transfer.rs Outdated Show resolved Hide resolved
pallets/nfts/src/features/transfer.rs Outdated Show resolved Hide resolved
Copy link
Collaborator

@Daanvdplas Daanvdplas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! LGTM!

pallets/nfts/src/features/approvals.rs Show resolved Hide resolved
Copy link
Collaborator

@peterwht peterwht left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Wasn't able to find much to change ;) Left two tiny comments. After those, I am good to approve.

pallets/nfts/src/features/transfer.rs Outdated Show resolved Hide resolved
pallets/nfts/src/impl_nonfungibles.rs Outdated Show resolved Hide resolved
@chungquantin chungquantin force-pushed the frank/nfts-balance-deposit branch from d5b1a02 to fefb7bc Compare January 9, 2025 07:07
@chungquantin chungquantin requested a review from peterwht January 9, 2025 07:29
@chungquantin chungquantin changed the title refactor(nfts): AccountBalance deposit feat(nfts): AccountBalance deposit Jan 9, 2025
@chungquantin chungquantin force-pushed the frank/nfts-balance-deposit branch from fefb7bc to f4c02f7 Compare January 9, 2025 07:30
@chungquantin chungquantin force-pushed the frank/nfts-balance-deposit branch from f4c02f7 to 1aa79f3 Compare January 9, 2025 07:31
@chungquantin chungquantin merged commit 1cdad44 into chungquantin/feat-nfts Jan 9, 2025
9 of 13 checks passed
@chungquantin chungquantin deleted the frank/nfts-balance-deposit branch January 9, 2025 15:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants