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

Realm
Open in gnoweb ↗

Overview

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

Files (3)

  • README.mdmarkdown
  • gnomod.tomltoml
  • erc20.gnogno
erc20.gnogno
1// Package erc20 implements MiniToken, a minimal fungible token modeled on the2// Solidity ERC-20 idea, ported to gno.land (gno 0.9 / sapphire).3//4// State is package-level and persistent. All state-mutating exported functions5// are crossing functions (they take `cur realm` as the first parameter) per the6// gno 0.9 interrealm convention, and identify the caller via7// cur.Previous().Address() after checking cur.IsCurrent().8package erc20910import (11	"errors"12	"sort"13	"strconv"14	"strings"15)1617const (18	name   = "MiniToken"19	symbol = "MINI"20)2122var (23	// balances maps holder address -> token balance.24	balances = map[address]uint64{}25	// allowances[owner][spender] = amount the spender may pull from owner.26	allowances = map[address]map[address]uint64{}27	// totalSupply is the sum of all balances.28	totalSupply uint6429)3031var (32	errZeroAddress  = errors.New("erc20: zero address")33	errInsufficient = errors.New("erc20: insufficient balance")34	errAllowanceLow = errors.New("erc20: insufficient allowance")35	errOverflow     = errors.New("erc20: supply overflow")36	errSpoofedRealm = errors.New("erc20: spoofed realm")37	errNotUser      = errors.New("erc20: caller is not a user account")38)3940// caller returns the immediate caller's address for a crossing function.41// It enforces the gno 0.9 authentication primitive: cur must be the live42// crossing frame before its Previous() is trusted.43func caller(cur realm) address {44	if !cur.IsCurrent() {45		panic(errSpoofedRealm)46	}47	prev := cur.Previous()48	if !prev.IsUser() {49		panic(errNotUser)50	}51	return prev.Address()52}5354// Mint creates `amount` new tokens and credits them to `to`, increasing the55// total supply. Crossing function.56func Mint(cur realm, to address, amount uint64) {57	_ = caller(cur) // authenticate the crossing frame; anyone may mint in this demo58	if !to.IsValid() {59		panic(errZeroAddress)60	}61	if amount == 0 {62		return63	}64	if totalSupply+amount < totalSupply {65		panic(errOverflow)66	}67	totalSupply += amount68	balances[to] += amount69}7071// Transfer moves `amount` tokens from the caller to `to`. Crossing function.72func Transfer(cur realm, to address, amount uint64) {73	from := caller(cur)74	if !to.IsValid() {75		panic(errZeroAddress)76	}77	if err := transfer(from, to, amount); err != nil {78		panic(err)79	}80}8182// Approve authorizes `spender` to pull up to `amount` tokens from the caller.83// Crossing function.84func Approve(cur realm, spender address, amount uint64) {85	owner := caller(cur)86	if !spender.IsValid() {87		panic(errZeroAddress)88	}89	m := allowances[owner]90	if m == nil {91		m = map[address]uint64{}92		allowances[owner] = m93	}94	m[spender] = amount95}9697// TransferFrom moves `amount` tokens from `from` to `to`, spending the caller's98// allowance granted by `from`. Crossing function.99func TransferFrom(cur realm, from, to address, amount uint64) {100	spender := caller(cur)101	if !from.IsValid() || !to.IsValid() {102		panic(errZeroAddress)103	}104	allowed := allowances[from][spender]105	if allowed < amount {106		panic(errAllowanceLow)107	}108	if err := transfer(from, to, amount); err != nil {109		panic(err)110	}111	allowances[from][spender] = allowed - amount112}113114// transfer is the internal, non-crossing balance mover. Pure logic on package115// state; returns an error rather than panicking so callers control reverts.116func transfer(from, to address, amount uint64) error {117	if amount == 0 {118		return nil119	}120	if balances[from] < amount {121		return errInsufficient122	}123	balances[from] -= amount124	balances[to] += amount125	return nil126}127128// BalanceOf returns the token balance of `holder`. Read-only, non-crossing.129func BalanceOf(holder address) uint64 {130	return balances[holder]131}132133// Allowance returns how much `spender` may still pull from `owner`.134func Allowance(owner, spender address) uint64 {135	return allowances[owner][spender]136}137138// TotalSupply returns the total number of tokens in existence.139func TotalSupply() uint64 {140	return totalSupply141}142143// Name returns the token name.144func Name() string { return name }145146// Symbol returns the token symbol.147func Symbol() string { return symbol }148149// Render produces the gnoweb Markdown view of the token: metadata plus a150// deterministically-ordered table of non-zero balances. Render is NOT a151// crossing function (no `cur realm` parameter).152func Render(path string) string {153	var b strings.Builder154155	b.WriteString("# " + name + " (" + symbol + ")\n\n")156	b.WriteString("A minimal ERC-20-style fungible token on gno.land.\n\n")157	b.WriteString("- **Name:** " + name + "\n")158	b.WriteString("- **Symbol:** " + symbol + "\n")159	b.WriteString("- **Total supply:** " + strconv.FormatUint(totalSupply, 10) + "\n\n")160161	// Collect and sort holder addresses for deterministic output. Map iteration162	// order is not a stable contract, so we sort the string keys (gno's sort163	// package has no generic Slice; Strings is the deterministic primitive).164	keys := make([]string, 0, len(balances))165	byKey := make(map[string]uint64, len(balances))166	for addr, bal := range balances {167		if bal == 0 {168			continue169		}170		s := addr.String()171		keys = append(keys, s)172		byKey[s] = bal173	}174	sort.Strings(keys)175176	b.WriteString("## Balances\n\n")177	if len(keys) == 0 {178		b.WriteString("_No holders yet — call `Mint` to create tokens._\n")179		return b.String()180	}181182	b.WriteString("| Address | Amount |\n")183	b.WriteString("| --- | ---: |\n")184	for _, k := range keys {185		b.WriteString("| `" + k + "` | " +186			strconv.FormatUint(byKey[k], 10) + " |\n")187	}188189	return b.String()190}191

Functions

  • Allowance(owner string, spender string) uint64

  • 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, amount uint64)

  • BalanceOf(holder 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, amount uint64)

  • Name() string

  • Render(path string) string

  • Symbol() string

  • TotalSupply() uint64

  • 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, amount uint64)

  • TransferFrom(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}, from string, to string, amount uint64)

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.