PathrockNetwork Gno Explorer
HomeBlocksTransactionsRealmsPackagesValidatorsAnalytics

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/r/moul/x/daily/erc721/v0

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v0
Namespace
moul / x / daily / erc721
Files
3 (README)(gnomod.toml)
Exported functions
7
Module
gno.land/r/moul/x/daily/erc721/v0
gno
0.9

Files (3)

  • README.mdmarkdown
  • gnomod.tomltoml
  • erc721.gnogno
erc721.gnogno
1// Package erc721 is an idiomatic gno.land port of the Solidity ERC-7212// non-fungible token standard. Each token has a unique integer id owned by3// exactly one address; ids are minted sequentially. Ownership, per-owner4// balances and single-token approvals are kept in ordered avl trees so that5// Render can iterate deterministically.6package erc72178import (9	"strconv"1011	"chain"12	"chain/runtime/unsafe"1314	"gno.land/p/nt/avl/v0"15)1617const (18	name   = "Gno NFT"19	symbol = "GNFT"20)2122var (23	owners    avl.Tree // tokenID (zero-padded string) -> address24	balances  avl.Tree // owner address (string) -> uint6425	approvals avl.Tree // tokenID (zero-padded string) -> approved address26	nextID    int64    = 127	minted    int64    // total tokens ever minted (== live supply, no burn)28)2930// key formats a token id into a zero-padded, lexicographically-sortable key.31func key(id int64) string {32	s := strconv.FormatInt(id, 10)33	for len(s) < 12 {34		s = "0" + s35	}36	return s37}3839// Mint creates the next token id and assigns it to `to`. Only sequential40// minting is supported (id is returned via the Mint event).41func Mint(cur realm, to address) int64 {42	if !to.IsValid() {43		panic("erc721: mint to invalid address")44	}45	id := nextID46	nextID++47	minted++4849	owners.Set(key(id), to)50	balances.Set(to.String(), balanceOf(to)+1)5152	chain.Emit("Mint", "to", to.String(), "tokenID", strconv.FormatInt(id, 10))53	return id54}5556// Transfer moves token `id` from the caller to `to`. The caller must own the57// token (approvals are cleared on transfer).58func Transfer(cur realm, to address, id int64) {59	if !to.IsValid() {60		panic("erc721: transfer to invalid address")61	}62	caller := unsafe.PreviousRealm().Address()63	from := ownerOf(id) // panics if the token does not exist6465	if caller != from {66		// allow the single-token approved operator too67		if approvedOf(id) != caller {68			panic("erc721: caller is neither owner nor approved")69		}70	}71	if from == to {72		panic("erc721: transfer to current owner")73	}7475	owners.Set(key(id), to)76	balances.Set(from.String(), balanceOf(from)-1)77	balances.Set(to.String(), balanceOf(to)+1)78	approvals.Remove(key(id)) // clear approval on transfer7980	chain.Emit("Transfer", "from", from.String(), "to", to.String(),81		"tokenID", strconv.FormatInt(id, 10))82}8384// Approve grants `spender` the right to transfer token `id`. Only the current85// owner may approve.86func Approve(cur realm, spender address, id int64) {87	caller := unsafe.PreviousRealm().Address()88	owner := ownerOf(id)89	if caller != owner {90		panic("erc721: approve caller is not owner")91	}92	approvals.Set(key(id), spender)93	chain.Emit("Approval", "owner", owner.String(), "spender", spender.String(),94		"tokenID", strconv.FormatInt(id, 10))95}9697// --- read-only helpers (safe to call from tests and Render) ---9899// ownerOf returns the owner of token `id`, panicking if it does not exist.100func ownerOf(id int64) address {101	v := owners.Get(key(id))102	if v == nil {103		panic("erc721: query for nonexistent token")104	}105	return v.(address)106}107108// approvedOf returns the approved address for token `id`, or the zero address.109func approvedOf(id int64) address {110	v := approvals.Get(key(id))111	if v == nil {112		return address("")113	}114	return v.(address)115}116117// balanceOf returns how many tokens `owner` holds.118func balanceOf(owner address) uint64 {119	v := balances.Get(owner.String())120	if v == nil {121		return 0122	}123	return v.(uint64)124}125126// exists reports whether token `id` has been minted (and not since moved away).127func exists(id int64) bool {128	return owners.Has(key(id))129}130131// totalSupply returns the number of tokens in circulation.132func totalSupply() int64 { return minted }133134// OwnerOf is the exported read-only accessor for ownerOf.135func OwnerOf(id int64) address { return ownerOf(id) }136137// BalanceOf is the exported read-only accessor for balanceOf.138func BalanceOf(owner address) uint64 { return balanceOf(owner) }139140// TotalSupply is the exported read-only accessor for totalSupply.141func TotalSupply() int64 { return totalSupply() }142143// Render displays collection metadata and a token -> owner table.144func Render(path string) string {145	out := "# " + name + " (" + symbol + ")\n\n"146	out += "**Total supply:** " + strconv.FormatInt(totalSupply(), 10) + "\n\n"147148	if owners.Size() == 0 {149		out += "_No tokens minted yet._\n"150		return out151	}152153	out += "| Token ID | Owner | Approved |\n"154	out += "|---------:|-------|----------|\n"155	owners.Iterate("", "", func(k string, v interface{}) bool {156		owner := v.(address)157		id, _ := strconv.ParseInt(k, 10, 64)158		appr := approvedOf(id)159		apprStr := "—"160		if appr != address("") {161			apprStr = appr.String()162		}163		out += "| " + strconv.FormatInt(id, 10) + " | " +164			owner.String() + " | " + apprStr + " |\n"165		return false166	})167	return out168}169

Functions

  • Approve(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, spender string, id int64)

  • BalanceOf(owner string) uint64

  • Mint(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, to string) int64

  • OwnerOf(id int64) string

  • Render(path string) string

  • TotalSupply() int64

  • Transfer(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, to string, id int64)

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

Rendered

RenderedRawgnoweb ↗

vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.