PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/p/nt/grc721/v0

Package
Open in gnoweb ↗

Overview

Kind
Pure package
Name
v0
Namespace
nt / grc721
Files
8 (gnomod.toml)
Exported functions
n/a — not supported for pure packages by the node (vm/qfuncs)
Module
gno.land/p/nt/grc721/v0
gno
0.9

Files (8)

  • gnomod.tomltoml
  • tellers.gnogno
  • token.gnogno
  • types.gnogno
  • newtoken_event_filetest.gnogno
  • tellers_test.gnogno
  • token_test.gnogno
  • veto_no_event_filetest.gnogno
  • types.gnogno
    1package grc72123import (4	"errors"56	"gno.land/p/nt/avl/v0"7)8

    Functions

    not supported for pure packages by the node (vm/qfuncs)

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    9type TokenID string
    10
    11func (t TokenID) String() string { return string(t) }
    12
    13// A Teller is a capability that acts as some account whenever it writes.
    14// IsCanonicalTeller confirms a Teller was minted by this package — an embedding
    15// forgery fails the check — but it does NOT reveal which account the Teller acts
    16// as: a caller-scoped CallerTeller and the admin-grade ImpersonateTeller (which
    17// acts as an arbitrary address) are both canonical. So it is an authenticity
    18// check on the implementation, not an authorization guard on the acting account;
    19// a caller accepting a Teller from outside must still establish, out of band, what
    20// account that Teller is entitled to act as.
    21// safeTransferFrom is omitted: EIP-721's receiver check needs a registry, and aliasing it would imply false safety.
    22type Teller interface {
    23 GetName() string
    24 GetSymbol() string
    25 ID() string
    26 TotalSupply() int64
    27 BalanceOf(owner address) (int64, error)
    28 OwnerOf(tid TokenID) (address, error)
    29 GetApproved(tid TokenID) (address, error)
    30 IsApprovedForAll(owner, operator address) bool
    31
    32 Approve(_ int, rlm realm, to address, tid TokenID) error
    33 SetApprovalForAll(_ int, rlm realm, operator address, approved bool) error
    34 TransferFrom(_ int, rlm realm, from, to address, tid TokenID) error
    35}
    36
    37// Extension hooks fire on every mint/transfer/burn. This is a trust grant to the
    38// issuer, not an EIP-721 feature: only the issuer can attach one (RegisterExtension
    39// holds the PrivateLedger), but once attached the hook runs arbitrary issuer code on
    40// every movement, a panic in OnMint/OnTransfer/OnBurn aborts the transaction before
    41// the movement is announced — an implicit veto over transfers — and gas scales
    42// linearly with the extension count. Hooks run after the ledger write so they observe
    43// the post-movement state; only a caller that recovers from the panic keeps that write.
    44// Holders of a collection's tokens are therefore trusting the issuer not to freeze or
    45// tax movement through this surface. Hooks take no rlm params (they cannot capture cur);
    46// attach only via RegisterExtension.
    47type Extension interface {
    48 ExtensionKind() string // unique; duplicates rejected at register
    49 OnMint(to address, tid TokenID)
    50 OnTransfer(from, to address, tid TokenID)
    51 OnBurn(tid TokenID)
    52}
    53
    54type ExtensionView interface {
    55 ExtensionKind() string
    56 TokenID() string // core Token.ID
    57}
    58
    59type Token struct {
    60 id string // origRealm + "." + symbol + "." + id
    61 name string
    62 symbol string
    63 ledger *PrivateLedger
    64 // origRealm is the PkgPath of the realm that created the token, captured
    65 // unforgeably in NewToken. A frame-relative teller only works there.
    66 origRealm string
    67}
    68
    69type PrivateLedger struct {
    70 token *Token
    71 totalSupply int64
    72 owners avl.Tree // TokenID -> owner address
    73 balances avl.Tree // owner address -> int64
    74 tokenApprovals avl.Tree // TokenID -> approved address
    75 operatorApprovals avl.Tree // "owner:operator" -> bool
    76 extensions []Extension
    77}
    78
    79var (
    80 ErrInvalidTokenId = errors.New("invalid token id")
    81 ErrInvalidAddress = errors.New("invalid address")
    82 ErrTokenIdNotApproved = errors.New("token id not approved for anyone")
    83 ErrApprovalToCurrentOwner = errors.New("approval to current owner")
    84 ErrCallerIsNotOwner = errors.New("caller is not token owner")
    85 ErrCannotTransferToSelf = errors.New("cannot send transfer to self")
    86 ErrTransferFromIncorrectOwner = errors.New("transfer from incorrect owner")
    87 ErrCallerIsNotOwnerOrApproved = errors.New("caller is not token owner or approved")
    88 ErrTokenIdAlreadyExists = errors.New("token id already exists")
    89 ErrReadonly = errors.New("teller is readonly")
    90 ErrSpoofedRealm = errors.New("rlm does not match the current crossing frame")
    91 ErrForeignCallerTeller = errors.New("frame-relative teller used outside the token's realm")
    92 ErrNotRealm = errors.New("rlm must be a realm (got EOA/origin)")
    93 ErrInvalidName = errors.New("invalid token name (empty, too long, or contains control chars)")
    94 ErrInvalidSymbol = errors.New("invalid token symbol (empty, too long, or contains chars outside [A-Za-z0-9_-])")
    95)
    96
    97// Symbol charset matches grc20reg slug (embedded in Token.ID / events).
    98const (
    99 MaxNameLen = 64
    100 MaxSymbolLen = 11
    101)
    102
    103const (
    104 // NewToken announces every token creation; see NewToken for why it is a
    105 // complete provenance signal.
    106 NewTokenEvent = "NewToken"
    107 // Mint emits from empty addr; burn emits to empty addr (EIP-721).
    108 TransferEvent = "Transfer"
    109 ApprovalEvent = "Approval"
    110 ApprovalForAllEvent = "ApprovalForAll"
    111)
    112
    113var zeroAddress = address("")
    114
    115type fnTeller struct {
    116 accountFn func(_ int, rlm realm) address
    117 // homeGuard marks a frame-relative teller, whose writes are confined to
    118 // the token's own realm. See fnTeller.guardHome.
    119 homeGuard bool
    120 *Token
    121}
    122
    123var _ Teller = (*fnTeller)(nil)
    124
    125// IsCanonicalTeller reports whether t was minted by this package, rejecting Tellers
    126// forged by embedding *fnTeller in a wrapper. It does NOT discriminate by capability
    127// grade: CallerTeller, ReadonlyTeller, RealmTeller, RealmSubTeller and the admin-grade
    128// ImpersonateTeller all return true. Do not treat a true result as proof that a Teller
    129// is a caller-scoped capability — establish the acting account separately.
    130func IsCanonicalTeller(t Teller) bool {
    131 _, ok := t.(*fnTeller)
    132 return ok
    133}
    134