types.gno

3.94 Kb ยท 117 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() int64
 22
 23	// Returns the amount of tokens owned by `account`.
 24	BalanceOf(account std.Address) int64
 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 int64) 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) int64
 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 int64) 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 int64) 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 int
 72	// Pointer to the PrivateLedger that manages balances and allowances.
 73	ledger *PrivateLedger
 74}
 75
 76// PrivateLedger is a struct that holds the balances and allowances for the
 77// token. It provides administrative functions for minting, burning,
 78// transferring tokens, and managing allowances.
 79//
 80// The PrivateLedger is not safe to expose publicly, as it contains sensitive
 81// information regarding token balances and allowances, and allows direct,
 82// unrestricted access to all administrative functions.
 83type PrivateLedger struct {
 84	// Total supply of the token managed by this ledger.
 85	totalSupply int64
 86	// std.Address -> int64
 87	balances avl.Tree
 88	// owner.(std.Address)+":"+spender.(std.Address)) -> int64
 89	allowances avl.Tree
 90	// Pointer to the associated Token struct
 91	token *Token
 92}
 93
 94var (
 95	ErrInsufficientBalance   = errors.New("insufficient balance")
 96	ErrInsufficientAllowance = errors.New("insufficient allowance")
 97	ErrInvalidAddress        = errors.New("invalid address")
 98	ErrCannotTransferToSelf  = errors.New("cannot send transfer to self")
 99	ErrReadonly              = errors.New("banker is readonly")
100	ErrRestrictedTokenOwner  = errors.New("restricted to bank owner")
101	ErrMintOverflow          = errors.New("mint overflow")
102	ErrInvalidAmount         = errors.New("invalid amount")
103)
104
105const (
106	MintEvent     = "Mint"
107	BurnEvent     = "Burn"
108	TransferEvent = "Transfer"
109	ApprovalEvent = "Approval"
110)
111
112type fnTeller struct {
113	accountFn func() std.Address
114	*Token
115}
116
117var _ Teller = (*fnTeller)(nil)