token_test.gno

5.55 Kb ยท 191 lines
  1package grc20
  2
  3import (
  4	"math"
  5	"std"
  6	"testing"
  7
  8	"gno.land/p/demo/testutils"
  9	"gno.land/p/demo/uassert"
 10	"gno.land/p/demo/ufmt"
 11	"gno.land/p/demo/urequire"
 12)
 13
 14func TestTestImpl(t *testing.T) {
 15	bank, _ := NewToken("Dummy", "DUMMY", 4)
 16	urequire.False(t, bank == nil, "dummy should not be nil")
 17}
 18
 19func TestToken(t *testing.T) {
 20	var (
 21		alice = testutils.TestAddress("alice")
 22		bob   = testutils.TestAddress("bob")
 23		carl  = testutils.TestAddress("carl")
 24	)
 25
 26	bank, adm := NewToken("Dummy", "DUMMY", 6)
 27
 28	checkBalances := func(aliceEB, bobEB, carlEB int64) {
 29		t.Helper()
 30		exp := ufmt.Sprintf("alice=%d bob=%d carl=%d", aliceEB, bobEB, carlEB)
 31		aliceGB := bank.BalanceOf(alice)
 32		bobGB := bank.BalanceOf(bob)
 33		carlGB := bank.BalanceOf(carl)
 34		got := ufmt.Sprintf("alice=%d bob=%d carl=%d", aliceGB, bobGB, carlGB)
 35		uassert.Equal(t, got, exp, "invalid balances")
 36	}
 37	checkAllowances := func(abEB, acEB, baEB, bcEB, caEB, cbEB int64) {
 38		t.Helper()
 39		exp := ufmt.Sprintf("ab=%d ac=%d ba=%d bc=%d ca=%d cb=%s", abEB, acEB, baEB, bcEB, caEB, cbEB)
 40		abGB := bank.Allowance(alice, bob)
 41		acGB := bank.Allowance(alice, carl)
 42		baGB := bank.Allowance(bob, alice)
 43		bcGB := bank.Allowance(bob, carl)
 44		caGB := bank.Allowance(carl, alice)
 45		cbGB := bank.Allowance(carl, bob)
 46		got := ufmt.Sprintf("ab=%d ac=%d ba=%d bc=%d ca=%d cb=%s", abGB, acGB, baGB, bcGB, caGB, cbGB)
 47		uassert.Equal(t, got, exp, "invalid allowances")
 48	}
 49
 50	checkBalances(0, 0, 0)
 51	checkAllowances(0, 0, 0, 0, 0, 0)
 52
 53	urequire.NoError(t, adm.Mint(alice, 1000))
 54	urequire.NoError(t, adm.Mint(alice, 100))
 55	checkBalances(1100, 0, 0)
 56	checkAllowances(0, 0, 0, 0, 0, 0)
 57
 58	urequire.NoError(t, adm.Approve(alice, bob, 99999999))
 59	checkBalances(1100, 0, 0)
 60	checkAllowances(99999999, 0, 0, 0, 0, 0)
 61
 62	urequire.NoError(t, adm.Approve(alice, bob, 400))
 63	checkBalances(1100, 0, 0)
 64	checkAllowances(400, 0, 0, 0, 0, 0)
 65
 66	urequire.Error(t, adm.TransferFrom(alice, bob, carl, 100000000))
 67	checkBalances(1100, 0, 0)
 68	checkAllowances(400, 0, 0, 0, 0, 0)
 69
 70	urequire.NoError(t, adm.TransferFrom(alice, bob, carl, 100))
 71	checkBalances(1000, 0, 100)
 72	checkAllowances(300, 0, 0, 0, 0, 0)
 73
 74	urequire.Error(t, adm.SpendAllowance(alice, bob, 2000000))
 75	checkBalances(1000, 0, 100)
 76	checkAllowances(300, 0, 0, 0, 0, 0)
 77
 78	urequire.NoError(t, adm.SpendAllowance(alice, bob, 100))
 79	checkBalances(1000, 0, 100)
 80	checkAllowances(200, 0, 0, 0, 0, 0)
 81}
 82
 83func TestMintOverflow(t *testing.T) {
 84	alice := testutils.TestAddress("alice")
 85	bob := testutils.TestAddress("bob")
 86	tok, adm := NewToken("Dummy", "DUMMY", 6)
 87
 88	safeValue := int64(1 << 62)
 89	urequire.NoError(t, adm.Mint(alice, safeValue))
 90	urequire.Equal(t, tok.BalanceOf(alice), safeValue)
 91
 92	err := adm.Mint(bob, safeValue)
 93	uassert.Error(t, err, "expected ErrMintOverflow")
 94}
 95
 96func TestTransferFromAtomicity(t *testing.T) {
 97	var (
 98		owner   = testutils.TestAddress("owner")
 99		spender = testutils.TestAddress("spender")
100
101		invalidRecipient = std.Address("")
102	)
103
104	token, admin := NewToken("Test", "TEST", 6)
105
106	// owner has 100 tokens, spender has 50 allowance
107	initialBalance := int64(100)
108	initialAllowance := int64(50)
109
110	urequire.NoError(t, admin.Mint(owner, initialBalance))
111	urequire.NoError(t, admin.Approve(owner, spender, initialAllowance))
112
113	// transfer to an invalid address to force a transfer failure
114	transferAmount := int64(30)
115	err := admin.TransferFrom(owner, spender, invalidRecipient, transferAmount)
116	uassert.Error(t, err, "transfer should fail due to invalid address")
117
118	ownerBalance := token.BalanceOf(owner)
119	uassert.Equal(t, ownerBalance, initialBalance, "owner balance should remain unchanged")
120
121	// check if allowance was incorrectly reduced
122	remainingAllowance := token.Allowance(owner, spender)
123	uassert.Equal(t, remainingAllowance, initialAllowance,
124		"allowance should not be reduced when transfer fails")
125}
126
127func TestMintUntilOverflow(t *testing.T) {
128	alice := testutils.TestAddress("alice")
129	bob := testutils.TestAddress("bob")
130	tok, adm := NewToken("Dummy", "DUMMY", 6)
131
132	tests := []struct {
133		name           string
134		address_XXX    std.Address
135		amount         int64
136		expectedError  error
137		expectedSupply int64
138		description    string
139	}{
140		{
141			name:           "mint negative value",
142			address_XXX:    alice,
143			amount:         -1,
144			expectedError:  ErrInvalidAmount,
145			expectedSupply: 0,
146			description:    "minting a negative number should fail with ErrInvalidAmount",
147		},
148		{
149			name:           "mint MaxInt64",
150			address_XXX:    alice,
151			amount:         math.MaxInt64 - 1000,
152			expectedError:  nil,
153			expectedSupply: math.MaxInt64 - 1000,
154			description:    "minting almost MaxInt64 should succeed",
155		},
156		{
157			name:           "mint small value",
158			address_XXX:    bob,
159			amount:         1000,
160			expectedError:  nil,
161			expectedSupply: math.MaxInt64,
162			description:    "minting a small value when close to MaxInt64 should succeed",
163		},
164		{
165			name:           "mint value that would exceed MaxInt64",
166			address_XXX:    bob,
167			amount:         1,
168			expectedError:  ErrMintOverflow,
169			expectedSupply: math.MaxInt64,
170			description:    "minting any value when at MaxInt64 should fail with ErrMintOverflow",
171		},
172	}
173
174	for _, tt := range tests {
175		t.Run(tt.name, func(t *testing.T) {
176			err := adm.Mint(tt.address_XXX, tt.amount)
177
178			if tt.expectedError != nil {
179				uassert.Error(t, err, tt.description)
180				if err == nil || err.Error() != tt.expectedError.Error() {
181					t.Errorf("expected error %v, got %v", tt.expectedError, err)
182				}
183			} else {
184				uassert.NoError(t, err, tt.description)
185			}
186
187			totalSupply := tok.TotalSupply()
188			uassert.Equal(t, totalSupply, tt.expectedSupply, "totalSupply should match expected value")
189		})
190	}
191}