NFT Lifecycle Management
Relevant source files
The following files were used as context for generating this wiki page:
NFT Lifecycle Management within the Aztec Standards project encompasses the deployment, minting, multi-state transfer, and burning of non-fungible tokens. This system is designed to provide ERC-721-like functionality while leveraging Aztec's privacy extensions, allowing assets to exist in either private or public states.
The management logic facilitates seamless transitions between these states—such as moving an NFT from a private balance to a public one or vice versa—while maintaining cryptographic proofs of ownership. It also integrates with specialized components like Escrow Standard Contract & Library for delegated spending and authorized release logic.
Sources: README.md:43-46, src/nft_contract/README.md:1-10
Core Contract Architecture
The NFT contract is built as a standardized Aztec contract that manages unique digital assets. It utilizes specialized storage structures to handle dual-state ownership and metadata.
Storage and Configuration
The contract maintains several key storage fields to track the lifecycle and properties of the NFT collection:
| Field | Type | Description |
|---|---|---|
name | FieldCompressedString | The compressed name of the NFT collection. |
symbol | FieldCompressedString | The compressed symbol of the NFT collection. |
private_nfts | Map<AztecAddress, PrivateSet<NFTNote>> | Mapping of accounts to their private NFT notes. |
nft_exists | Map<Field, bool> | Tracking of minted token IDs to ensure uniqueness. |
public_owners | Map<Field, AztecAddress> | Mapping of token IDs to their current public owner. |
minter | AztecAddress | Authorized address allowed to mint new tokens. |
Sources: src/nft_contract/README.md:12-19
Implementation Diagram
The following diagram illustrates the relationship between the contract's storage and the different ownership states:
The contract utilizes PrivateSet<NFTNote> for confidential ownership and a standard Map for public visibility.
Sources: src/nft_contract/README.md:14-18
Minting and Initialization
The lifecycle begins with deployment and the assignment of a minter. The contract supports two primary minting paths: mint_to_private and mint_to_public.
Initialization
Deployment requires specifying the collection metadata and authorities.
constructor_with_minter: Initializes the name, symbol, authorized minter, and an optional upgrade authority.
Minting Logic
Minting creates a new token ID that did not previously exist.
- Private Minting: Uses
mint_to_private(to, token_id)to create a new private NFT note for the recipient. - Public Minting: Uses
mint_to_public(to, token_id)to update the public mapping, making the ownership visible on-chain.
Sources: src/nft_contract/README.md:21-35, src/nft_contract/README.md:118-124
Transfer Mechanisms
NFTs can be moved between four different ownership state combinations. All transfers (except those initiated by the owner in public) typically require an authorization witness (authwit) to ensure secure delegated or self-initiated spending.
Transfer State Matrix
The contract provides specific functions for every possible state transition:
| From | To | Function | Implementation Detail |
|---|---|---|---|
| Private | Private | transfer_private_to_private | Destroys sender's note; creates recipient's note. |
| Private | Public | transfer_private_to_public | Destroys note; enqueues public owner update. |
| Public | Private | transfer_public_to_private | Removes public owner; emits private note. |
| Public | Public | transfer_public_to_public | Updates public owner mapping directly. |
Sources: src/nft_contract/README.md:39-95, src/nft_contract/README.md:105-115
Commitment-Based Transfers
To support "privacy entrances" or asynchronous completions, the contract implements a commitment flow:
- Initialize:
initialize_transfer_commitment(from, to)generates a partial NFT note. - Transfer:
transfer_private_to_commitment(from, token_id, commitment, nonce)moves the NFT into a pending state. - Completion: A public call completes the commitment, finalizing the transfer.
Sources: src/nft_contract/README.md:73-82, src/ts/test/nft.test.ts:79-106
Transfer Flow Diagram
The following sequence diagram shows the interaction for a Private to Public transfer involving an authorization witness:
Escrow Integration
The NFT lifecycle can include periods where the asset is held by an Escrow contract. This is particularly useful for logic-gated releases (e.g., vesting or swaps).
Escrow Features
- Withdrawal: The
Escrowcontract provides awithdraw_nft(nft, token_id, recipient)function. - Private Release: Withdrawals from escrow are performed via private functions to ensure the destination balance remains confidential.
- Logic Delegation: A separate
Logiccontract manages the conditions under which theEscrowcalls its withdrawal methods.
Sources: src/escrow_contract/README.md:14-35, src/ts/test/escrow.test.ts:251-274
Termination: Burning
The final stage of an NFT's lifecycle is burning, which permanently removes the token from existence.
burn_private(from, token_id, nonce):- Asserts the caller is the owner.
- Removes the private note.
- Enqueues a public call to update the existence status.
burn_public(from, token_id, nonce):- Asserts the token exists and the caller is the owner.
- Removes the public ownership entry.
- Marks the token as non-existent.
Sources: src/nft_contract/README.md:126-140, benchmarks/nft_contract.benchmark.ts:67-74
Summary
NFT Lifecycle Management in Aztec Standards provides a robust framework for handling unique assets with privacy. By supporting four transfer modes between public and private states, integrating with escrowed logic, and enforcing strict minter/owner controls, the system ensures that NFT movements are both secure and flexible. The use of commitment-based flows further enables complex privacy-preserving interactions required for advanced decentralized applications.