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

item_test.gno

12.85 Kb · 341 lines
  1package item
  2
  3import (
  4	"chain"
  5	"testing"
  6
  7	"gno.land/p/nt/testutils/v0"
  8	"gno.land/p/nt/uassert/v0"
  9	"gno.land/r/akkadia/beta/admin"
 10)
 11
 12var itemTest = struct {
 13	Admin, Operator, Owner, Other address
 14	SetupDone                     bool
 15}{
 16	Admin:    testutils.TestAddress("itemAdmin"),
 17	Operator: testutils.TestAddress("itemOperator"),
 18	Owner:    testutils.TestAddress("itemOwner"),
 19	Other:    testutils.TestAddress("itemOther"),
 20}
 21
 22func setupItemTest(cur realm, t *testing.T) {
 23	t.Helper()
 24	resetItemState()
 25	testing.SetOriginSend(chain.Coins{})
 26	if itemTest.SetupDone {
 27		return
 28	}
 29	originalAdmin := admin.GetAdmin()
 30	testing.SetOriginCaller(originalAdmin)
 31	testing.SetRealm(testing.NewUserRealm(originalAdmin))
 32	admin.TransferAdmin(cross(cur), itemTest.Admin)
 33	testing.SetOriginCaller(itemTest.Admin)
 34	testing.SetRealm(testing.NewUserRealm(itemTest.Admin))
 35	admin.AcceptAdmin(cross(cur))
 36	admin.SetOperator(cross(cur), itemTest.Operator)
 37	itemTest.SetupDone = true
 38}
 39
 40func TestSafeMintTracksSupply(cur realm, t *testing.T) {
 41	setupItemTest(cross(cur), t)
 42	testing.SetOriginCaller(itemTest.Operator)
 43	testing.SetRealm(testing.NewUserRealm(itemTest.Operator))
 44	SafeMint(cross(cur), itemTest.Owner, "42", 5)
 45	uassert.Equal(t, int64(5), BalanceOf(itemTest.Owner, "42"))
 46	uassert.Equal(t, int64(5), TotalSupply("42"))
 47	SafeMint(cross(cur), itemTest.Owner, "42", 1)
 48	SafeMint(cross(cur), itemTest.Other, "42", 2)
 49	uassert.Equal(t, int64(6), BalanceOf(itemTest.Owner, "42"))
 50	uassert.Equal(t, int64(2), BalanceOf(itemTest.Other, "42"))
 51	uassert.Equal(t, int64(8), TotalSupply("42"))
 52}
 53
 54func TestItemTokenIDAcceptsOpaqueStrings(cur realm, t *testing.T) {
 55	setupItemTest(cross(cur), t)
 56	testing.SetOriginCaller(itemTest.Operator)
 57	testing.SetRealm(testing.NewUserRealm(itemTest.Operator))
 58	SafeMint(cross(cur), itemTest.Owner, "0", 1)
 59	SafeMint(cross(cur), itemTest.Owner, "4294967295", 2)
 60	SafeMint(cross(cur), itemTest.Owner, "sword", 3)
 61	uassert.Equal(t, int64(1), BalanceOf(itemTest.Owner, "0"))
 62	uassert.Equal(t, int64(2), TotalSupply("4294967295"))
 63	uassert.Equal(t, int64(3), TotalSupply("sword"))
 64	uassert.AbortsWithMessage(t, cur, "token id is required", func() {
 65		SafeMint(cross(cur), itemTest.Owner, "", 1)
 66	})
 67}
 68
 69func TestItemTransferAndBurnUpdateSupply(cur realm, t *testing.T) {
 70	setupItemTest(cross(cur), t)
 71	testing.SetOriginCaller(itemTest.Operator)
 72	testing.SetRealm(testing.NewUserRealm(itemTest.Operator))
 73	SafeMint(cross(cur), itemTest.Owner, "42", 5)
 74	testing.SetOriginCaller(itemTest.Owner)
 75	testing.SetRealm(testing.NewUserRealm(itemTest.Owner))
 76	SafeTransferFrom(cross(cur), itemTest.Owner, itemTest.Other, "42", 2)
 77	Burn(cross(cur), itemTest.Owner, "42", 1)
 78	uassert.Equal(t, int64(2), BalanceOf(itemTest.Owner, "42"))
 79	uassert.Equal(t, int64(2), BalanceOf(itemTest.Other, "42"))
 80	uassert.Equal(t, int64(4), TotalSupply("42"))
 81}
 82
 83func TestItemApprovalAllowsTransferAndBurn(cur realm, t *testing.T) {
 84	setupItemTest(cross(cur), t)
 85	testing.SetOriginCaller(itemTest.Operator)
 86	testing.SetRealm(testing.NewUserRealm(itemTest.Operator))
 87	SafeMint(cross(cur), itemTest.Owner, "42", 5)
 88	testing.SetOriginCaller(itemTest.Owner)
 89	testing.SetRealm(testing.NewUserRealm(itemTest.Owner))
 90	SetApprovalForAll(cross(cur), itemTest.Other, true)
 91	testing.SetOriginCaller(itemTest.Other)
 92	testing.SetRealm(testing.NewUserRealm(itemTest.Other))
 93	SafeTransferFrom(cross(cur), itemTest.Owner, itemTest.Admin, "42", 2)
 94	Burn(cross(cur), itemTest.Owner, "42", 1)
 95	uassert.Equal(t, int64(2), BalanceOf(itemTest.Owner, "42"))
 96	uassert.Equal(t, int64(2), BalanceOf(itemTest.Admin, "42"))
 97	uassert.Equal(t, int64(4), TotalSupply("42"))
 98}
 99
100func TestSafeMintSecurity(cur realm, t *testing.T) {
101	setupItemTest(cross(cur), t)
102	testing.SetOriginCaller(itemTest.Owner)
103	testing.SetRealm(testing.NewUserRealm(itemTest.Owner))
104	uassert.AbortsWithMessage(t, cur, "admin or operator access required", func() {
105		SafeMint(cross(cur), itemTest.Owner, "1", 1)
106	})
107	testing.SetOriginCaller(itemTest.Operator)
108	testing.SetRealm(testing.NewCodeRealm("gno.land/r/example/item_relay"))
109	uassert.AbortsWithMessage(t, cur, "admin or operator access required", func() {
110		SafeMint(cross(cur), itemTest.Owner, "1", 1)
111	})
112	testing.SetRealm(testing.NewUserRealm(itemTest.Operator))
113	testing.SetOriginSend(chain.Coins{{"ugnot", 1}})
114	uassert.AbortsWithMessage(t, cur, "attached coins not allowed", func() {
115		SafeMint(cross(cur), itemTest.Owner, "1", 1)
116	})
117}
118
119func TestItemOwnedList(cur realm, t *testing.T) {
120	setupItemTest(cross(cur), t)
121	testing.SetOriginCaller(itemTest.Operator)
122	testing.SetRealm(testing.NewUserRealm(itemTest.Operator))
123	uassert.Equal(t, 0, GetOwnedCount(itemTest.Owner))
124	uassert.Equal(t, 0, len(ListByOwner(itemTest.Owner, 1, 10)))
125	uassert.PanicsWithMessage(t, cur, "invalid item owner", func() {
126		GetOwnedCount(address(""))
127	})
128	uassert.PanicsWithMessage(t, cur, "page must be at least 1", func() {
129		ListByOwner(itemTest.Owner, 0, 1)
130	})
131	uassert.PanicsWithMessage(t, cur, "count must be at least 1", func() {
132		ListByOwner(itemTest.Owner, 1, 0)
133	})
134	uassert.PanicsWithMessage(t, cur, "count exceeds listLimit (max: 100)", func() {
135		ListByOwner(itemTest.Owner, 1, 101)
136	})
137	uassert.Equal(t, 100, GetListLimit())
138
139	SafeMint(cross(cur), itemTest.Owner, "10", 5)
140	SafeMint(cross(cur), itemTest.Owner, "20", 3)
141	SafeMint(cross(cur), itemTest.Owner, "30", 1)
142	uassert.Equal(t, 3, GetOwnedCount(itemTest.Owner))
143	page1 := ListByOwner(itemTest.Owner, 1, 2)
144	uassert.Equal(t, 2, len(page1))
145	uassert.Equal(t, "10", page1[0]["tokenId"])
146	uassert.Equal(t, "5", page1[0]["amount"])
147	uassert.Equal(t, "20", page1[1]["tokenId"])
148	page2 := ListByOwner(itemTest.Owner, 2, 2)
149	uassert.Equal(t, 1, len(page2))
150	uassert.Equal(t, "30", page2[0]["tokenId"])
151	uassert.Equal(t, 0, len(ListByOwner(itemTest.Owner, 3, 2)))
152	page1[0]["amount"] = "hacked"
153	uassert.Equal(t, "5", ListByOwner(itemTest.Owner, 1, 1)[0]["amount"])
154
155	testing.SetOriginCaller(itemTest.Owner)
156	testing.SetRealm(testing.NewUserRealm(itemTest.Owner))
157	SafeTransferFrom(cross(cur), itemTest.Owner, itemTest.Other, "10", 2)
158	uassert.Equal(t, 3, GetOwnedCount(itemTest.Owner))
159	uassert.Equal(t, 1, GetOwnedCount(itemTest.Other))
160	uassert.Equal(t, "3", ListByOwner(itemTest.Owner, 1, 10)[0]["amount"])
161	uassert.Equal(t, "2", ListByOwner(itemTest.Other, 1, 10)[0]["amount"])
162	SafeTransferFrom(cross(cur), itemTest.Owner, itemTest.Other, "10", 3)
163	uassert.Equal(t, 2, GetOwnedCount(itemTest.Owner))
164	uassert.Equal(t, 1, GetOwnedCount(itemTest.Other))
165	Burn(cross(cur), itemTest.Owner, "20", 3)
166	uassert.Equal(t, 1, GetOwnedCount(itemTest.Owner))
167	uassert.Equal(t, "30", ListByOwner(itemTest.Owner, 1, 10)[0]["tokenId"])
168
169	testing.SetOriginCaller(itemTest.Operator)
170	testing.SetRealm(testing.NewUserRealm(itemTest.Operator))
171	SafeMint(cross(cur), itemTest.Owner, "30", 2)
172	uassert.Equal(t, 1, GetOwnedCount(itemTest.Owner))
173	uassert.Equal(t, "3", ListByOwner(itemTest.Owner, 1, 10)[0]["amount"])
174}
175
176func TestSetListLimit(cur realm, t *testing.T) {
177	setupItemTest(cross(cur), t)
178
179	testing.SetOriginCaller(itemTest.Admin)
180	testing.SetRealm(testing.NewUserRealm(itemTest.Admin))
181	SetListLimit(cross(cur), 50)
182	uassert.Equal(t, 50, GetListLimit())
183
184	SetListLimit(cross(cur), 1)
185	uassert.PanicsWithMessage(t, cur, "count exceeds listLimit (max: 1)", func() {
186		ListByOwner(itemTest.Owner, 1, 2)
187	})
188
189	uassert.AbortsWithMessage(t, cur, "limit must be at least 1", func() {
190		SetListLimit(cross(cur), 0)
191	})
192	uassert.AbortsWithMessage(t, cur, "limit must be at least 1", func() {
193		SetListLimit(cross(cur), -1)
194	})
195
196	testing.SetOriginCaller(itemTest.Operator)
197	testing.SetRealm(testing.NewUserRealm(itemTest.Operator))
198	uassert.AbortsWithMessage(t, cur, "admin access required", func() {
199		SetListLimit(cross(cur), 50)
200	})
201
202	testing.SetOriginCaller(itemTest.Owner)
203	testing.SetRealm(testing.NewUserRealm(itemTest.Owner))
204	uassert.AbortsWithMessage(t, cur, "admin access required", func() {
205		SetListLimit(cross(cur), 50)
206	})
207
208	testing.SetOriginCaller(itemTest.Admin)
209	testing.SetRealm(testing.NewCodeRealm("gno.land/r/example/item_admin_relay"))
210	uassert.AbortsWithMessage(t, cur, "admin access required", func() {
211		SetListLimit(cross(cur), 50)
212	})
213}
214
215func TestSetMinterRealm(cur realm, t *testing.T) {
216	setupItemTest(cross(cur), t)
217	minterPath := "gno.land/r/example/item_minter"
218	minter := testing.NewCodeRealm(minterPath)
219	minterAddr := minter.Address()
220
221	uassert.Equal(t, minterAddr.String(), chain.PackageAddress(minterPath).String())
222	uassert.Equal(t, false, IsMinterRealm(minterAddr))
223
224	testing.SetOriginCaller(itemTest.Operator)
225	testing.SetRealm(testing.NewUserRealm(itemTest.Operator))
226	uassert.AbortsWithMessage(t, cur, "admin access required", func() {
227		SetMinterRealm(cross(cur), minterPath)
228	})
229
230	testing.SetOriginCaller(itemTest.Admin)
231	testing.SetRealm(testing.NewUserRealm(itemTest.Admin))
232	uassert.AbortsWithMessage(t, cur, "package path is required", func() {
233		SetMinterRealm(cross(cur), "")
234	})
235	uassert.AbortsWithMessage(t, cur, "invalid package path", func() {
236		SetMinterRealm(cross(cur), "gno.land/p/akkadia/beta/item")
237	})
238	SetMinterRealm(cross(cur), minterPath)
239	uassert.Equal(t, true, IsMinterRealm(minterAddr))
240	SetMinterRealm(cross(cur), minterPath)
241	uassert.Equal(t, true, IsMinterRealm(minterAddr))
242
243	UnsetMinterRealm(cross(cur), minterPath)
244	uassert.Equal(t, false, IsMinterRealm(minterAddr))
245	uassert.AbortsWithMessage(t, cur, "package path is not a minter realm", func() {
246		UnsetMinterRealm(cross(cur), minterPath)
247	})
248	uassert.AbortsWithMessage(t, cur, "package path is required", func() {
249		UnsetMinterRealm(cross(cur), "")
250	})
251
252	testing.SetRealm(testing.NewCodeRealm("gno.land/r/example/item_admin_relay"))
253	uassert.AbortsWithMessage(t, cur, "admin access required", func() {
254		SetMinterRealm(cross(cur), minterPath)
255	})
256}
257
258func TestSafeMintFromRealm(cur realm, t *testing.T) {
259	setupItemTest(cross(cur), t)
260	minter := testing.NewCodeRealm("gno.land/r/example/item_minter")
261	unregistered := testing.NewCodeRealm("gno.land/r/example/item_minter_other")
262
263	testing.SetOriginCaller(itemTest.Owner)
264	testing.SetRealm(testing.NewUserRealm(itemTest.Owner))
265	uassert.AbortsWithMessage(t, cur, "user calls not allowed: function must be called by a realm", func() {
266		SafeMintFromRealm(cross(cur), itemTest.Owner, "1", 1)
267	})
268
269	testing.SetRealm(unregistered)
270	uassert.AbortsWithMessage(t, cur, "minter realm required", func() {
271		SafeMintFromRealm(cross(cur), itemTest.Owner, "1", 1)
272	})
273
274	testing.SetOriginCaller(itemTest.Admin)
275	testing.SetRealm(testing.NewUserRealm(itemTest.Admin))
276	SetMinterRealm(cross(cur), "gno.land/r/example/item_minter")
277
278	testing.SetOriginCaller(itemTest.Owner)
279	testing.SetRealm(minter)
280	SafeMintFromRealm(cross(cur), itemTest.Owner, "7", 3)
281	uassert.Equal(t, int64(3), BalanceOf(itemTest.Owner, "7"))
282	uassert.Equal(t, int64(3), TotalSupply("7"))
283	uassert.Equal(t, 1, GetOwnedCount(itemTest.Owner))
284
285	uassert.AbortsWithMessage(t, cur, "item recipient must be origin caller", func() {
286		SafeMintFromRealm(cross(cur), itemTest.Other, "8", 1)
287	})
288	uassert.Equal(t, int64(0), TotalSupply("8"))
289
290	testing.SetOriginSend(chain.Coins{{"ugnot", 1}})
291	SafeMintFromRealm(cross(cur), itemTest.Owner, "9", 1)
292	testing.SetOriginSend(chain.Coins{})
293	uassert.Equal(t, int64(1), BalanceOf(itemTest.Owner, "9"))
294}
295
296func TestBurnFromRealm(cur realm, t *testing.T) {
297	setupItemTest(cross(cur), t)
298	minter := testing.NewCodeRealm("gno.land/r/example/item_minter")
299
300	testing.SetOriginCaller(itemTest.Operator)
301	testing.SetRealm(testing.NewUserRealm(itemTest.Operator))
302	SafeMint(cross(cur), itemTest.Owner, "42", 5)
303
304	testing.SetOriginCaller(itemTest.Admin)
305	testing.SetRealm(testing.NewUserRealm(itemTest.Admin))
306	SetMinterRealm(cross(cur), "gno.land/r/example/item_minter")
307
308	testing.SetOriginCaller(itemTest.Owner)
309	testing.SetRealm(testing.NewUserRealm(itemTest.Owner))
310	uassert.AbortsWithMessage(t, cur, "user calls not allowed: function must be called by a realm", func() {
311		BurnFromRealm(cross(cur), itemTest.Owner, "42", 1)
312	})
313
314	testing.SetRealm(minter)
315	uassert.AbortsWithMessage(t, cur, "item owner must be origin caller", func() {
316		BurnFromRealm(cross(cur), itemTest.Other, "42", 1)
317	})
318	uassert.Equal(t, int64(5), BalanceOf(itemTest.Owner, "42"))
319
320	BurnFromRealm(cross(cur), itemTest.Owner, "42", 2)
321	uassert.Equal(t, int64(3), BalanceOf(itemTest.Owner, "42"))
322	uassert.Equal(t, int64(3), TotalSupply("42"))
323
324	uassert.AbortsWithMessage(t, cur, "item amount must be positive", func() {
325		SafeMintFromRealm(cross(cur), itemTest.Owner, "99", 0)
326	})
327	uassert.Equal(t, int64(3), BalanceOf(itemTest.Owner, "42"))
328	uassert.Equal(t, int64(3), TotalSupply("42"))
329	uassert.Equal(t, int64(0), TotalSupply("99"))
330	uassert.Equal(t, 1, GetOwnedCount(itemTest.Owner))
331
332	testing.SetOriginCaller(itemTest.Admin)
333	testing.SetRealm(testing.NewUserRealm(itemTest.Admin))
334	UnsetMinterRealm(cross(cur), "gno.land/r/example/item_minter")
335	testing.SetOriginCaller(itemTest.Owner)
336	testing.SetRealm(minter)
337	uassert.AbortsWithMessage(t, cur, "minter realm required", func() {
338		BurnFromRealm(cross(cur), itemTest.Owner, "42", 1)
339	})
340	uassert.Equal(t, int64(3), BalanceOf(itemTest.Owner, "42"))
341}