erc20_test.gno
3.07 Kb · 111 lines
1package erc20
2
3import (
4 "strings"
5 "testing"
6
7 "gno.land/p/nt/testutils/v0"
8 "gno.land/p/nt/uassert/v0"
9)
10
11// Fixed test addresses. testutils.TestAddress derives real, valid-length
12// addresses; literal strings would fail address.IsValid() and trip the realm's
13// zero-address guard.
14var (
15 alice = testutils.TestAddress("alice")
16 bob = testutils.TestAddress("bob")
17 spender = testutils.TestAddress("spender")
18 dest = testutils.TestAddress("dest")
19)
20
21// reset clears package state between tests so cases stay independent.
22func reset() {
23 balances = map[address]uint64{}
24 allowances = map[address]map[address]uint64{}
25 totalSupply = 0
26}
27
28// TestMintAndTransfer mints to alice, then transfers alice -> bob.
29func TestMintAndTransfer(cur realm, t *testing.T) {
30 reset()
31
32 testing.SetRealm(testing.NewUserRealm(alice))
33 Mint(cross(cur), alice, 1000)
34
35 if got := TotalSupply(); got != 1000 {
36 t.Fatalf("total supply = %d, want 1000", got)
37 }
38 if got := BalanceOf(alice); got != 1000 {
39 t.Fatalf("alice balance = %d, want 1000", got)
40 }
41
42 testing.SetRealm(testing.NewUserRealm(alice))
43 Transfer(cross(cur), bob, 400)
44
45 if got := BalanceOf(alice); got != 600 {
46 t.Errorf("alice balance = %d, want 600", got)
47 }
48 if got := BalanceOf(bob); got != 400 {
49 t.Errorf("bob balance = %d, want 400", got)
50 }
51 if got := TotalSupply(); got != 1000 {
52 t.Errorf("total supply changed on transfer: %d, want 1000", got)
53 }
54}
55
56// TestApproveAndTransferFrom exercises the allowance path.
57func TestApproveAndTransferFrom(cur realm, t *testing.T) {
58 reset()
59
60 testing.SetRealm(testing.NewUserRealm(alice))
61 Mint(cross(cur), alice, 500)
62
63 testing.SetRealm(testing.NewUserRealm(alice))
64 Approve(cross(cur), spender, 300)
65 if got := Allowance(alice, spender); got != 300 {
66 t.Fatalf("allowance = %d, want 300", got)
67 }
68
69 testing.SetRealm(testing.NewUserRealm(spender))
70 TransferFrom(cross(cur), alice, dest, 200)
71
72 if got := BalanceOf(alice); got != 300 {
73 t.Errorf("owner balance = %d, want 300", got)
74 }
75 if got := BalanceOf(dest); got != 200 {
76 t.Errorf("dest balance = %d, want 200", got)
77 }
78 if got := Allowance(alice, spender); got != 100 {
79 t.Errorf("remaining allowance = %d, want 100", got)
80 }
81}
82
83// TestTransferInsufficientPanics asserts an over-transfer reverts.
84func TestTransferInsufficientPanics(cur realm, t *testing.T) {
85 reset()
86
87 testing.SetRealm(testing.NewUserRealm(alice))
88 Mint(cross(cur), alice, 10)
89
90 // Aborts from a cross(cur) call cannot be caught by a plain recover();
91 // assert on the abort message instead.
92 testing.SetRealm(testing.NewUserRealm(alice))
93 uassert.AbortsWithMessage(t, cur, "erc20: insufficient balance", func() {
94 Transfer(cross(cur), bob, 100) // more than balance -> panic
95 })
96}
97
98// TestRenderContainsMetadata checks the Markdown view exposes name/symbol/supply.
99func TestRenderContainsMetadata(cur realm, t *testing.T) {
100 reset()
101
102 testing.SetRealm(testing.NewUserRealm(alice))
103 Mint(cross(cur), alice, 42)
104
105 out := Render("")
106 for _, want := range []string{"MiniToken", "MINI", "Total supply", "42"} {
107 if !strings.Contains(out, want) {
108 t.Errorf("render output missing %q\n%s", want, out)
109 }
110 }
111}