Note
It is based on use-ink/ink-examples
This is an implementation of the ERC-721 Non-Fungible Token (NFT) standard using ink! smart contract language for the Polkadot/Substrate ecosystem. The contract provides functionality for creating, managing, and transferring unique tokens on the blockchain.
- Mint new unique tokens
- Transfer tokens between accounts
- Approve specific accounts to transfer tokens
- Set operators with broader transfer rights
- Burn (destroy) tokens
- Manage token metadata URIs
- Query token ownership and balances
The contract maintains several key mappings:
token_owner: Maps token IDs to their ownerstoken_approvals: Maps tokens to approved transfer addressesowned_tokens_count: Tracks how many tokens each address ownsoperator_approvals: Tracks approved operators for ownerscontract_uri: Stores contract-level metadata URIbase_uri: Stores base URI for token metadata
- Rust and Cargo installed
- ink! toolchain set up
- A Substrate-based chain supporting ink! contracts
cargo contract buildcargo testWhen you are ready to deploy
cargo contract build --release// Initialize contract
let mut erc721 = Erc721::new();
// Mint a new token with ID 1
erc721.mint(1)?;// Direct transfer by owner
erc721.transfer(recipient_account, token_id)?;
// Transfer using approval
erc721.transfer_from(from_account, to_account, token_id)?;// Approve single token transfer
erc721.approve(operator_account, token_id)?;
// Approve all tokens
erc721.set_approval_for_all(operator_account, true)?;Returns the number of tokens owned by an account.
Returns the owner of a specific token.
Returns the approved account for a token.
Checks if an operator is approved for all tokens of an owner.
Returns the contract-level metadata URI.
Returns the metadata URI for a specific token.
Creates a new token with the specified ID.
Destroys an existing token (only callable by owner).
Transfers a token to a new owner.
Approves an account to transfer a specific token.
Approves or revokes an operator for all tokens.
Sets the base URI for token metadata.
Sets the contract-level metadata URI.
The contract defines several error types:
NotOwner: Operation requires token ownershipNotApproved: Caller not approved for operationTokenExists: Token ID already existsTokenNotFound: Token ID does not existCannotInsert: Failed to insert new dataCannotFetchValue: Failed to fetch existing dataNotAllowed: Operation not permitted
The contract emits the following events:
Emitted when a token is transferred, including minting and burning.
from: Previous owner (None for minting)to: New owner (None for burning)id: Token ID
Emitted when a token is approved for transfer.
from: Token ownerto: Approved accountid: Token ID
Emitted when an operator is approved/disapproved.
owner: Token owneroperator: Operator accountapproved: Approval status
- Fork the repository
- Create a feature branch
- Commit your changes
- Push to the branch
- Create a Pull Request
The contract includes comprehensive unit tests covering:
- Token minting
- Token transfers
- Approval management
- Error conditions
- Edge cases
Run the tests using:
cargo test