PRC-721: Non-Fungible Token Standard

Status: Draft
Panda analogue: EIP-721 (ERC-721)


Copyright

Copyright and related rights waived via CC0.


Simple Summary

A standard interface for non-fungible tokens on Panda: unique token_id values, per-token ownership, transfers, approvals, and optional metadata URIs—so marketplaces, games, and wallets can treat every compliant NFT contract uniformly.


Abstract

The following standard defines a minimal API for NFT collections implemented as Panda smart contracts. It follows the intent of ERC-721: enumeration of ownership, owner_of, transfer_from / safe transfer patterns, single-token and operator approvals, and Transfer, Approval, and ApprovalForAll events. Panda uses Python, str accounts, and int token IDs; failures MUST be signaled by raising, not a bool return.


Motivation

NFTs need a common surface so indexers, explorers, and composable contracts can resolve “who owns token N”, move tokens with consent, and delegate spending—without custom glue per collection.


Specification

Conventions

ERC-721 (Solidity)PRC-721 (Panda)
addressstr
uint256 tokenIdint (token_id)
returns (bool)success if call returns; else raise
view@query
state-changing@call

Required behavior

A PRC-721-compliant contract SHOULD implement the following (Python snake_case names).

Queries

  • balance_of(owner: str) -> int
    Number of NFTs owned by owner.

  • owner_of(token_id: int) -> str
    Owner of token_id; MUST fail if the token does not exist.

  • get_approved(token_id: int) -> str
    Address approved to manage token_id (zero / empty if none). Implementations MAY use a dedicated “no approval” sentinel.

  • is_approved_for_all(owner: str, operator: str) -> bool
    Whether operator is set for all tokens of owner.

  • token_uri(token_id: int) -> str (optional)
    Metadata URI or inline payload string for token_id.

Calls

  • transfer_from(ctx, from_addr: str, to_addr: str, token_id: int)
    Transfers token_id from from_addr to to_addr.
    Caller MUST be from_addr, a single-token approved spender, or an operator approved for all.
    MUST emit Transfer.

  • safe_transfer_from(ctx, from_addr: str, to_addr: str, token_id: int)
    Same as transfer_from for environments without contract-code checks; Panda contracts MAY alias this to transfer_from or add extra validation.

  • approve(ctx, to: str, token_id: int)
    Sets single-token approval for token_id to to (caller is current owner or authorized).

  • set_approval_for_all(ctx, operator: str, approved: bool)
    Sets or clears operator approval for ctx.sender.

Events

Transfer

MUST fire when token_id is moved or created (mint: _from is zero / burn: _to is zero per implementation policy).

  • _from: str
  • _to: str
  • _token_id: int

Approval

MUST fire when approved address for token_id changes (including reset).

  • _owner: str
  • _approved: str
  • _token_id: int

ApprovalForAll

MUST fire when operator approval is set or cleared.

  • _owner: str
  • _operator: str
  • _approved: bool

Notes

  • Enumeration (tokenByIndex, etc.) is optional; indexers can still scan Transfer events if emitted consistently.
  • Reference contract: contracts/tokens/prc721_collection.py.

Implementation

Collections typically store token_id -> { owner, ... } and per-owner token lists. Minting is contract-defined (e.g. @constructor or @call).

panda deploy contracts/tokens/prc721_collection.py \
  --rpc http://localhost:8545 \
  --args '{"name":"My NFT","symbol":"MNFT","base_uri":""}'

History

  • Inspired by EIP-721 (William Entriken, Dieter Shirley, Jacob Evans, Nastassia Sachs).

Citation

Please cite this document as:

Panda Protocol. PRC-721: Non-Fungible Token Standard. Panda documentation: docs/PRC721.md.

Historical ERC-721 reference:

William Entriken, Dieter Shirley, Jacob Evans, Nastassia Sachs. EIP-721: Non-Fungible Token Standard. https://eips.ethereum.org/EIPS/eip-721