Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit e2d414e

Browse files
committedOct 17, 2024·
chore: fixup
Signed-off-by: moul <[email protected]>
1 parent 1ac96f9 commit e2d414e

File tree

6 files changed

+167
-26
lines changed

6 files changed

+167
-26
lines changed
 

‎examples/gno.land/p/demo/grc/grc20/bank.gno

+28-12
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import (
77
"gno.land/p/demo/ufmt"
88
)
99

10+
// NewBank creates a new Bank.
11+
// It returns a pointer to the Bank and a pointer to the AdminBanker.
12+
// Expected usage: Bank, admin := NewBank("Dummy", "DUMMY", 4)
1013
func NewBank(name, symbol string, decimals uint) (*Bank, *AdminBanker) {
1114
if name == "" {
1215
panic("name should not be empty")
@@ -26,16 +29,27 @@ func NewBank(name, symbol string, decimals uint) (*Bank, *AdminBanker) {
2629
return bank, adm
2730
}
2831

29-
func (b Bank) GetName() string { return b.name }
30-
func (b Bank) GetSymbol() string { return b.symbol }
31-
func (b Bank) GetDecimals() uint { return b.decimals }
32+
// GetName returns the name of the token.
33+
func (b Bank) GetName() string { return b.name }
34+
35+
// GetSymbol returns the symbol of the token.
36+
func (b Bank) GetSymbol() string { return b.symbol }
37+
38+
// GetDecimals returns the number of decimals used to get the token's precision.
39+
func (b Bank) GetDecimals() uint { return b.decimals }
40+
41+
// TotalSupply returns the total supply of the token.
3242
func (b Bank) TotalSupply() uint64 { return b.adm.totalSupply }
33-
func (b Bank) KnownAccounts() int { return b.adm.balances.Size() }
3443

44+
// KnownAccounts returns the number of known accounts in the bank.
45+
func (b Bank) KnownAccounts() int { return b.adm.balances.Size() }
46+
47+
// BalanceOf returns the balance of the specified address.
3548
func (b Bank) BalanceOf(address std.Address) uint64 {
3649
return b.adm.balanceOf(address)
3750
}
3851

52+
// Allowance returns the allowance of the specified owner and spender.
3953
func (b Bank) Allowance(owner, spender std.Address) uint64 {
4054
return b.adm.allowance(owner, spender)
4155
}
@@ -49,6 +63,7 @@ func (b *Bank) RenderHome() string {
4963
return str
5064
}
5165

66+
// SpendAllowance decreases the allowance of the specified owner and spender.
5267
func (b *AdminBanker) SpendAllowance(owner, spender std.Address, amount uint64) error {
5368
if !owner.IsValid() {
5469
return ErrInvalidAddress
@@ -74,6 +89,7 @@ func (b *AdminBanker) SpendAllowance(owner, spender std.Address, amount uint64)
7489
return nil
7590
}
7691

92+
// Transfer transfers tokens from the specified from address to the specified to address.
7793
func (b *AdminBanker) Transfer(from, to std.Address, amount uint64) error {
7894
if !from.IsValid() {
7995
return ErrInvalidAddress
@@ -108,6 +124,8 @@ func (b *AdminBanker) Transfer(from, to std.Address, amount uint64) error {
108124
return nil
109125
}
110126

127+
// TransferFrom transfers tokens from the specified owner to the specified to address.
128+
// It first checks if the owner has sufficient balance and then decreases the allowance.
111129
func (b *AdminBanker) TransferFrom(owner, spender, to std.Address, amount uint64) error {
112130
if b.balanceOf(owner) < amount {
113131
return ErrInsufficientBalance
@@ -119,6 +137,7 @@ func (b *AdminBanker) TransferFrom(owner, spender, to std.Address, amount uint64
119137
return b.Transfer(owner, to, amount)
120138
}
121139

140+
// Approve sets the allowance of the specified owner and spender.
122141
func (b *AdminBanker) Approve(owner, spender std.Address, amount uint64) error {
123142
if !owner.IsValid() {
124143
return ErrInvalidAddress
@@ -139,6 +158,7 @@ func (b *AdminBanker) Approve(owner, spender std.Address, amount uint64) error {
139158
return nil
140159
}
141160

161+
// Mint increases the total supply of the token and adds the specified amount to the specified address.
142162
func (a *AdminBanker) Mint(address std.Address, amount uint64) error {
143163
if !address.IsValid() {
144164
return ErrInvalidAddress
@@ -162,6 +182,7 @@ func (a *AdminBanker) Mint(address std.Address, amount uint64) error {
162182
return nil
163183
}
164184

185+
// Burn decreases the total supply of the token and subtracts the specified amount from the specified address.
165186
func (a *AdminBanker) Burn(address std.Address, amount uint64) error {
166187
if !address.IsValid() {
167188
return ErrInvalidAddress
@@ -188,6 +209,7 @@ func (a *AdminBanker) Burn(address std.Address, amount uint64) error {
188209
return nil
189210
}
190211

212+
// balanceOf returns the balance of the specified address.
191213
func (b AdminBanker) balanceOf(address std.Address) uint64 {
192214
balance, found := b.balances.Get(address.String())
193215
if !found {
@@ -196,6 +218,7 @@ func (b AdminBanker) balanceOf(address std.Address) uint64 {
196218
return balance.(uint64)
197219
}
198220

221+
// allowance returns the allowance of the specified owner and spender.
199222
func (b AdminBanker) allowance(owner, spender std.Address) uint64 {
200223
allowance, found := b.allowances.Get(allowanceKey(owner, spender))
201224
if !found {
@@ -204,14 +227,7 @@ func (b AdminBanker) allowance(owner, spender std.Address) uint64 {
204227
return allowance.(uint64)
205228
}
206229

230+
// allowanceKey returns the key for the allowance of the specified owner and spender.
207231
func allowanceKey(owner, spender std.Address) string {
208232
return owner.String() + ":" + spender.String()
209233
}
210-
211-
func AccountSlugAddr(addr std.Address, slug string) std.Address {
212-
if slug == "" {
213-
return addr
214-
}
215-
key := addr.String() + "/" + slug
216-
return std.DerivePkgAddr(key) // temporarily using this helper
217-
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package grc20
2+
3+
import (
4+
"testing"
5+
6+
"gno.land/p/demo/testutils"
7+
"gno.land/p/demo/uassert"
8+
"gno.land/p/demo/ufmt"
9+
"gno.land/p/demo/urequire"
10+
)
11+
12+
func TestBankImpl(t *testing.T) {
13+
bank, _ := NewBank("Dummy", "DUMMY", 4)
14+
urequire.False(t, bank == nil, "dummy should not be nil")
15+
}
16+
17+
func TestBank(t *testing.T) {
18+
var (
19+
alice = testutils.TestAddress("alice")
20+
bob = testutils.TestAddress("bob")
21+
carl = testutils.TestAddress("carl")
22+
)
23+
24+
bank, adm := NewBank("Dummy", "DUMMY", 6)
25+
26+
checkBalances := func(aliceEB, bobEB, carlEB uint64) {
27+
t.Helper()
28+
exp := ufmt.Sprintf("alice=%d bob=%d carl=%d", aliceEB, bobEB, carlEB)
29+
aliceGB := bank.BalanceOf(alice)
30+
bobGB := bank.BalanceOf(bob)
31+
carlGB := bank.BalanceOf(carl)
32+
got := ufmt.Sprintf("alice=%d bob=%d carl=%d", aliceGB, bobGB, carlGB)
33+
uassert.Equal(t, got, exp, "invalid balances")
34+
}
35+
checkAllowances := func(abEB, acEB, baEB, bcEB, caEB, cbEB uint64) {
36+
t.Helper()
37+
exp := ufmt.Sprintf("ab=%d ac=%d ba=%d bc=%d ca=%d cb=%s", abEB, acEB, baEB, bcEB, caEB, cbEB)
38+
abGB := bank.Allowance(alice, bob)
39+
acGB := bank.Allowance(alice, carl)
40+
baGB := bank.Allowance(bob, alice)
41+
bcGB := bank.Allowance(bob, carl)
42+
caGB := bank.Allowance(carl, alice)
43+
cbGB := bank.Allowance(carl, bob)
44+
got := ufmt.Sprintf("ab=%d ac=%d ba=%d bc=%d ca=%d cb=%s", abGB, acGB, baGB, bcGB, caGB, cbGB)
45+
uassert.Equal(t, got, exp, "invalid allowances")
46+
}
47+
48+
checkBalances(0, 0, 0)
49+
checkAllowances(0, 0, 0, 0, 0, 0)
50+
51+
urequire.NoError(t, adm.Mint(alice, 1000))
52+
urequire.NoError(t, adm.Mint(alice, 100))
53+
checkBalances(1100, 0, 0)
54+
checkAllowances(0, 0, 0, 0, 0, 0)
55+
56+
urequire.NoError(t, adm.Approve(alice, bob, 99999999))
57+
checkBalances(1100, 0, 0)
58+
checkAllowances(99999999, 0, 0, 0, 0, 0)
59+
60+
urequire.NoError(t, adm.Approve(alice, bob, 400))
61+
checkBalances(1100, 0, 0)
62+
checkAllowances(400, 0, 0, 0, 0, 0)
63+
64+
urequire.Error(t, adm.TransferFrom(alice, bob, carl, 100000000))
65+
checkBalances(1100, 0, 0)
66+
checkAllowances(400, 0, 0, 0, 0, 0)
67+
68+
urequire.NoError(t, adm.TransferFrom(alice, bob, carl, 100))
69+
checkBalances(1000, 0, 100)
70+
checkAllowances(300, 0, 0, 0, 0, 0)
71+
72+
urequire.Error(t, adm.SpendAllowance(alice, bob, 2000000))
73+
checkBalances(1000, 0, 100)
74+
checkAllowances(300, 0, 0, 0, 0, 0)
75+
76+
urequire.NoError(t, adm.SpendAllowance(alice, bob, 100))
77+
checkBalances(1000, 0, 100)
78+
checkAllowances(200, 0, 0, 0, 0, 0)
79+
}

‎examples/gno.land/p/demo/grc/grc20/bankers.gno

+29-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import (
55
)
66

77
func PrevRealmBanker(b *Bank) GRC20 {
8+
if b == nil {
9+
panic("Bank cannot be nil")
10+
}
11+
812
return &fnBanker{
913
accountFn: func() std.Address {
1014
caller := std.PrevRealm().Addr()
@@ -14,16 +18,39 @@ func PrevRealmBanker(b *Bank) GRC20 {
1418
}
1519
}
1620

21+
func RealmBanker(b *Bank) GRC20 {
22+
if b == nil {
23+
panic("Bank cannot be nil")
24+
}
25+
26+
return &fnBanker{
27+
accountFn: func() std.Address {
28+
caller := std.CurrentRealm().Addr()
29+
return caller
30+
},
31+
Bank: b,
32+
}
33+
}
34+
1735
func ReadonlyBanker(b *Bank) GRC20 {
36+
if b == nil {
37+
panic("Bank cannot be nil")
38+
}
39+
1840
return &fnBanker{
1941
accountFn: nil,
2042
Bank: b,
2143
}
2244
}
2345

24-
func AccountBanker(b *Bank, slug string) GRC20 {
46+
func SubAccountBanker(b *Bank, slug string) GRC20 {
47+
if b == nil {
48+
panic("Bank cannot be nil")
49+
}
50+
2551
caller := std.CurrentRealm().Addr()
26-
account := AccountSlugAddr(caller, slug)
52+
account := accountSlugAddr(caller, slug)
53+
2754
return &fnBanker{
2855
accountFn: func() std.Address {
2956
return account

‎examples/gno.land/p/demo/grc/grc20/examples_test.gno

+15-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,25 @@
11
package grc20
22

3+
// XXX: write Examples
4+
5+
func ExampleInit() {}
6+
func ExampleExposeBankForMaketxRunOrImports() {}
7+
func ExampleCustomGRC20Impl() {}
8+
func ExampleAllowance() {}
9+
func ExampleRealmBanker() {}
10+
func ExamplePrevRealmBanker() {}
11+
func ExampleAccountBanker() {}
12+
func ExampleTransfer() {}
13+
func ExampleApprove() {}
14+
func ExampleTransferFrom() {}
15+
func ExampleMint() {}
16+
func ExampleBurn() {}
17+
318
/*
419
Users
520
- token creator (root)
621
- token holder / enduser / basic realm (GRC20)
722
- dao/intermediary-realm (vault) contracts
8-
Some challenges I've in mind:
9-
- making a `GRC20` interface that is an interface. -> CHECK
10-
- making a `grc20.XXX` structure which provides the best suggested implementation.
11-
- encouraging realms to store an admin Banker while exposing other things (TBD).
1223
- user banker. (prevrealm)
1324
- realm banker.
1425
- compatible with govdao. (and async closures).

‎examples/gno.land/p/demo/grc/grc20/types.gno

+16-8
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ var (
1717
ErrRestrictedBankOwner = errors.New("restricted to bank owner")
1818
)
1919

20+
const (
21+
MintEvent = "Mint"
22+
BurnEvent = "Burn"
23+
TransferEvent = "Transfer"
24+
ApprovalEvent = "Approval"
25+
)
26+
2027
// Bank represents a token's bank, including its name, symbol,
2128
// decimals, and administrative functions.
2229
type Bank struct {
@@ -75,8 +82,6 @@ type GRC20 interface {
7582
TransferFrom(from, to std.Address, amount uint64) error
7683
}
7784

78-
// fnBanker is a wrapper around Bank that provides a custom account address
79-
// through a function. This allows for dynamic account addressing in GRC20 operations.
8085
type fnBanker struct {
8186
accountFn func() std.Address
8287
*Bank
@@ -89,9 +94,12 @@ type adminBanker struct {
8994
bank *Bank
9095
}
9196

92-
const (
93-
MintEvent = "Mint"
94-
BurnEvent = "Burn"
95-
TransferEvent = "Transfer"
96-
ApprovalEvent = "Approval"
97-
)
97+
// accountSlugAddr returns the address derived from the specified address and slug.
98+
func accountSlugAddr(addr std.Address, slug string) std.Address {
99+
// XXX: use a new `std.XXX` call for this.
100+
if slug == "" {
101+
return addr
102+
}
103+
key := addr.String() + "/" + slug
104+
return std.DerivePkgAddr(key) // temporarily using this helper
105+
}

0 commit comments

Comments
 (0)
Please sign in to comment.