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)