Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

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}