Search Apps Documentation Source Content File Folder Download Copy

types.gno

4.27 Kb ยท 123 lines
  1package grc20
  2
  3import (
  4	"errors"
  5	"std"
  6
  7	"gno.land/p/demo/avl"
  8	"gno.land/p/demo/grc/exts"
  9)
 10
 11// Teller interface defines the methods that a GRC20 token must implement. It
 12// extends the TokenMetadata interface to include methods for managing token
 13// transfers, allowances, and querying balances.
 14//
 15// The Teller interface is designed to ensure that any token adhering to this
 16// standard provides a consistent API for interacting with fungible tokens.
 17type Teller interface {
 18	exts.TokenMetadata
 19
 20	// Returns the amount of tokens in existence.
 21	TotalSupply() uint64
 22
 23	// Returns the amount of tokens owned by `account`.
 24	BalanceOf(account std.Address) uint64
 25
 26	// Moves `amount` tokens from the caller's account to `to`.
 27	//
 28	// Returns an error if the operation failed.
 29	Transfer(to std.Address, amount uint64) error
 30
 31	// Returns the remaining number of tokens that `spender` will be
 32	// allowed to spend on behalf of `owner` through {transferFrom}. This is
 33	// zero by default.
 34	//
 35	// This value changes when {approve} or {transferFrom} are called.
 36	Allowance(owner, spender std.Address) uint64
 37
 38	// Sets `amount` as the allowance of `spender` over the caller's tokens.
 39	//
 40	// Returns an error if the operation failed.
 41	//
 42	// IMPORTANT: Beware that changing an allowance with this method brings
 43	// the risk that someone may use both the old and the new allowance by
 44	// unfortunate transaction ordering. One possible solution to mitigate
 45	// this race condition is to first reduce the spender's allowance to 0
 46	// and set the desired value afterwards:
 47	// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
 48	Approve(spender std.Address, amount uint64) error
 49
 50	// Moves `amount` tokens from `from` to `to` using the
 51	// allowance mechanism. `amount` is then deducted from the caller's
 52	// allowance.
 53	//
 54	// Returns an error if the operation failed.
 55	TransferFrom(from, to std.Address, amount uint64) error
 56}
 57
 58// Token represents a fungible token with a name, symbol, and a certain number
 59// of decimal places. It maintains a ledger for tracking balances and allowances
 60// of addresses.
 61//
 62// The Token struct provides methods for retrieving token metadata, such as the
 63// name, symbol, and decimals, as well as methods for interacting with the
 64// ledger, including checking balances and allowances.
 65type Token struct {
 66	// Name of the token (e.g., "Dummy Token").
 67	name string
 68	// Symbol of the token (e.g., "DUMMY").
 69	symbol string
 70	// Number of decimal places used for the token's precision.
 71	decimals uint
 72	// Pointer to the PrivateLedger that manages balances and allowances.
 73	ledger *PrivateLedger
 74}
 75
 76// TokenGetter is a function type that returns a Token pointer. This type allows
 77// bypassing a limitation where we cannot directly pass Token pointers between
 78// realms. Instead, we pass this function which can then be called to get the
 79// Token pointer. For more details on this limitation and workaround, see:
 80// https://github.com/gnolang/gno/pull/3135
 81type TokenGetter func() *Token
 82
 83// PrivateLedger is a struct that holds the balances and allowances for the
 84// token. It provides administrative functions for minting, burning,
 85// transferring tokens, and managing allowances.
 86//
 87// The PrivateLedger is not safe to expose publicly, as it contains sensitive
 88// information regarding token balances and allowances, and allows direct,
 89// unrestricted access to all administrative functions.
 90type PrivateLedger struct {
 91	// Total supply of the token managed by this ledger.
 92	totalSupply uint64
 93	// std.Address -> uint64
 94	balances avl.Tree
 95	// owner.(std.Address)+":"+spender.(std.Address)) -> uint64
 96	allowances avl.Tree
 97	// Pointer to the associated Token struct
 98	token *Token
 99}
100
101var (
102	ErrInsufficientBalance   = errors.New("insufficient balance")
103	ErrInsufficientAllowance = errors.New("insufficient allowance")
104	ErrInvalidAddress        = errors.New("invalid address")
105	ErrCannotTransferToSelf  = errors.New("cannot send transfer to self")
106	ErrReadonly              = errors.New("banker is readonly")
107	ErrRestrictedTokenOwner  = errors.New("restricted to bank owner")
108	ErrOverflow              = errors.New("Mint overflow")
109)
110
111const (
112	MintEvent     = "Mint"
113	BurnEvent     = "Burn"
114	TransferEvent = "Transfer"
115	ApprovalEvent = "Approval"
116)
117
118type fnTeller struct {
119	accountFn func() std.Address
120	*Token
121}
122
123var _ Teller = (*fnTeller)(nil)