security_test.gno
6.43 Kb · 147 lines
1package abt
2
3import (
4 "chain"
5 "chain/runtime"
6 "testing"
7
8 "gno.land/p/nt/uassert/v0"
9 "gno.land/r/akkadia/beta/admin"
10)
11
12func TestUnauthorizedMintAndFreeze(cur realm, t *testing.T) {
13 setupABT(cross(cur), t)
14 testing.SetOriginCaller(abtTest.Owner)
15 testing.SetRealm(testing.NewUserRealm(abtTest.Owner))
16 uassert.AbortsWithMessage(t, cur, "admin or operator access required", func() { Mint(cross(cur), abtTest.Owner, 1) })
17 for _, caller := range []address{abtTest.Owner, abtTest.Operator} {
18 testing.SetOriginCaller(caller)
19 testing.SetRealm(testing.NewUserRealm(caller))
20 for _, value := range []bool{true, false} {
21 uassert.AbortsWithMessage(t, cur, "admin access required", func() { SetFrozen(cross(cur), value) })
22 }
23 }
24 for _, signer := range []address{abtTest.Admin, abtTest.Operator} {
25 testing.SetOriginCaller(signer)
26 testing.SetRealm(testing.NewCodeRealm("gno.land/r/example/abt_relay"))
27 uassert.AbortsWithMessage(t, cur, "admin or operator access required", func() { Mint(cross(cur), abtTest.Owner, 1) })
28 uassert.AbortsWithMessage(t, cur, "admin access required", func() { SetFrozen(cross(cur), false) })
29 }
30 uassert.True(t, IsFrozen())
31 uassert.Equal(t, int64(0), TotalSupply())
32 uassert.Equal(t, int64(0), BalanceOf(abtTest.Owner))
33}
34
35func TestFrozenRejectsAllCallers(cur realm, t *testing.T) {
36 setupABT(cross(cur), t)
37 for _, caller := range []address{abtTest.Admin, abtTest.Operator, abtTest.Owner} {
38 testing.SetOriginCaller(abtTest.Admin)
39 testing.SetRealm(testing.NewUserRealm(abtTest.Admin))
40 Mint(cross(cur), caller, 10)
41 testing.SetOriginCaller(caller)
42 testing.SetRealm(testing.NewUserRealm(caller))
43 uassert.AbortsWithMessage(t, cur, "abt is frozen", func() { Transfer(cross(cur), abtTest.Other, 1) })
44 uassert.AbortsWithMessage(t, cur, "abt is frozen", func() { Approve(cross(cur), abtTest.Other, 1) })
45 uassert.AbortsWithMessage(t, cur, "abt is frozen", func() { Approve(cross(cur), abtTest.Other, 0) })
46 uassert.AbortsWithMessage(t, cur, "abt is frozen", func() { TransferFrom(cross(cur), caller, abtTest.Other, 1) })
47 uassert.Equal(t, int64(10), BalanceOf(caller))
48 uassert.Equal(t, int64(0), Allowance(caller, abtTest.Other))
49 }
50 uassert.Equal(t, int64(30), TotalSupply())
51 uassert.Equal(t, int64(0), BalanceOf(abtTest.Other))
52}
53
54func TestAttachedCoinsRejected(cur realm, t *testing.T) {
55 cases := []struct {
56 name string
57 call func(_ int, rlm realm)
58 }{
59 {"mint", func(_ int, rlm realm) { Mint(cross(rlm), abtTest.Owner, 1) }},
60 {"freeze", func(_ int, rlm realm) { SetFrozen(cross(rlm), true) }},
61 {"freeze no-op", func(_ int, rlm realm) { SetFrozen(cross(rlm), false) }},
62 {"transfer", func(_ int, rlm realm) { Transfer(cross(rlm), abtTest.Other, 1) }},
63 {"approve", func(_ int, rlm realm) { Approve(cross(rlm), abtTest.Other, 1) }},
64 {"transferFrom", func(_ int, rlm realm) { TransferFrom(cross(rlm), abtTest.Owner, abtTest.Other, 1) }},
65 }
66 for _, tc := range cases {
67 t.Run(tc.name, func(cur realm, t *testing.T) {
68 setupABT(cross(cur), t)
69 testing.SetRealm(testing.NewUserRealm(abtTest.Admin))
70 Mint(cross(cur), abtTest.Admin, 10)
71 SetFrozen(cross(cur), false)
72 for _, caller := range []runtime.Realm{
73 testing.NewUserRealm(abtTest.Admin),
74 runtime.NewRealm(abtTest.Admin, "gno.land/e/"+abtTest.Admin.String()+"/run"),
75 } {
76 testing.SetRealm(caller)
77 testing.SetOriginSend(chain.Coins{{"ugnot", 1}})
78 uassert.AbortsWithMessage(t, cur, "attached coins not allowed", func() { tc.call(0, cur) })
79 uassert.False(t, IsFrozen())
80 uassert.Equal(t, int64(10), TotalSupply())
81 uassert.Equal(t, int64(10), BalanceOf(abtTest.Admin))
82 uassert.Equal(t, int64(0), BalanceOf(abtTest.Other))
83 uassert.Equal(t, int64(0), Allowance(abtTest.Admin, abtTest.Other))
84 }
85 })
86 }
87}
88
89func TestRelayUsesOwnBalanceAndAllowance(cur realm, t *testing.T) {
90 setupABT(cross(cur), t)
91 relay := testing.NewCodeRealm("gno.land/r/example/abt_relay")
92 testing.SetRealm(testing.NewUserRealm(abtTest.Admin))
93 Mint(cross(cur), abtTest.Owner, 100)
94 Mint(cross(cur), relay.Address(), 20)
95 SetFrozen(cross(cur), false)
96 testing.SetOriginCaller(abtTest.Owner)
97 testing.SetRealm(testing.NewUserRealm(abtTest.Owner))
98 Approve(cross(cur), relay.Address(), 7)
99 Approve(cross(cur), abtTest.Owner, 30)
100 // These coins belong to the relay's origin call, not to ABT.
101 testing.SetOriginSend(chain.Coins{{"ugnot", 1}})
102 testing.SetRealm(relay)
103 Transfer(cross(cur), abtTest.Other, 5)
104 Approve(cross(cur), abtTest.Other, 3)
105 TransferFrom(cross(cur), abtTest.Owner, abtTest.Other, 7)
106 uassert.AbortsWithMessage(t, cur, "abt transfer failed: insufficient allowance", func() {
107 TransferFrom(cross(cur), abtTest.Owner, abtTest.Other, 1)
108 })
109 uassert.Equal(t, int64(93), BalanceOf(abtTest.Owner))
110 uassert.Equal(t, int64(15), BalanceOf(relay.Address()))
111 uassert.Equal(t, int64(12), BalanceOf(abtTest.Other))
112 uassert.Equal(t, int64(3), Allowance(relay.Address(), abtTest.Other))
113 uassert.Equal(t, int64(0), Allowance(abtTest.Owner, abtTest.Other))
114 uassert.Equal(t, int64(0), Allowance(abtTest.Owner, relay.Address()))
115 uassert.Equal(t, int64(30), Allowance(abtTest.Owner, abtTest.Owner))
116 uassert.Equal(t, int64(120), TotalSupply())
117 testing.SetOriginSend(chain.Coins{})
118 testing.SetOriginCaller(abtTest.Admin)
119 testing.SetRealm(testing.NewUserRealm(abtTest.Admin))
120 SetFrozen(cross(cur), true)
121 testing.SetRealm(relay)
122 uassert.AbortsWithMessage(t, cur, "abt is frozen", func() { Transfer(cross(cur), abtTest.Other, 1) })
123 uassert.AbortsWithMessage(t, cur, "abt is frozen", func() { Approve(cross(cur), abtTest.Other, 0) })
124 uassert.AbortsWithMessage(t, cur, "abt is frozen", func() { TransferFrom(cross(cur), abtTest.Owner, abtTest.Other, 1) })
125}
126
127func TestOperatorRealmCanMintWithOwnAuthority(cur realm, t *testing.T) {
128 setupABT(cross(cur), t)
129 relay := testing.NewCodeRealm("gno.land/r/example/abt_operator")
130 testing.SetRealm(testing.NewUserRealm(abtTest.Admin))
131 admin.SetOperator(cross(cur), relay.Address())
132 testing.SetOriginCaller(abtTest.Owner)
133 testing.SetOriginSend(chain.Coins{{"ugnot", 1}})
134 testing.SetRealm(relay)
135 Mint(cross(cur), abtTest.Owner, 2)
136 uassert.AbortsWithMessage(t, cur, "admin access required", func() { SetFrozen(cross(cur), false) })
137 uassert.Equal(t, int64(2), TotalSupply())
138 uassert.True(t, IsFrozen())
139}
140
141func TestSpoofedRealmRejected(cur realm, t *testing.T) {
142 setupABT(cross(cur), t)
143 stale := captureABTRealm(cross(cur))
144 uassert.PanicsWithMessage(t, cur, "spoofed realm", func() { assertCanTransfer(0, stale) })
145 uassert.True(t, IsFrozen())
146 uassert.Equal(t, int64(0), TotalSupply())
147}