types.gno

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