types.gno

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