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

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

arena_test.gno

17.61 Kb · 575 lines
  1package gnocial
  2
  3import (
  4	"chain"
  5	"chain/banker"
  6	"strconv"
  7	"strings"
  8	"testing"
  9
 10	"gno.land/p/nt/testutils/v0"
 11	"gno.land/p/nt/uassert/v0"
 12	"gno.land/p/nt/urequire/v0"
 13)
 14
 15func resetArena() {
 16	state = newStore()
 17	state.admin = testutils.TestAddress("admin")
 18	state.treasury = testutils.TestAddress("treasury")
 19}
 20
 21func ugnots(n int64) chain.Coins {
 22	if n == 0 {
 23		return nil
 24	}
 25	return chain.Coins{chain.NewCoin("ugnot", n)}
 26}
 27
 28func bal(a address) int64 {
 29	return banker.NewReadonlyBanker().GetCoins(a).AmountOf("ugnot")
 30}
 31
 32func mustAbort(t *testing.T, rlm realm, msg string, fn func()) {
 33	if !uassert.AbortsWithMessage(t, rlm, msg, fn) {
 34		t.FailNow()
 35	}
 36}
 37
 38func TestCurveMath(t *testing.T) {
 39	urequire.Equal(t, int64(1), sumSq(1))
 40	urequire.Equal(t, int64(5), sumSq(2))
 41	urequire.Equal(t, int64(14), sumSq(3))
 42	var want int64
 43	for i := int64(1); i <= 40; i++ {
 44		want += i * i
 45		urequire.Equal(t, want, sumSq(i))
 46	}
 47	urequire.Equal(t, int64(10_000), curveCost(0, 1))
 48	urequire.Equal(t, int64(50_000), curveCost(0, 2))
 49	urequire.Equal(t, int64(40_000), curveCost(1, 1))
 50	urequire.Equal(t, int64(140_000), curveCost(0, 3))
 51}
 52
 53func TestSocial(cur realm, t *testing.T) {
 54	resetArena()
 55	alice := testutils.TestAddress("alice")
 56	bob := testutils.TestAddress("bob")
 57
 58	testing.SetRealm(testing.NewUserRealm(alice))
 59	testing.SetOriginSend(nil)
 60	mustAbort(t, cur, "bad handle", func() {
 61		Register(cross(cur), "ab", "", "", "")
 62	})
 63	testing.SetRealm(testing.NewUserRealm(alice))
 64	testing.SetOriginSend(nil)
 65	mustAbort(t, cur, "bad handle", func() {
 66		Register(cross(cur), "admin", "", "", "")
 67	})
 68	testing.SetRealm(testing.NewUserRealm(alice))
 69	testing.SetOriginSend(nil)
 70	mustAbort(t, cur, "bad handle", func() {
 71		Register(cross(cur), "gnocial", "", "", "")
 72	})
 73	testing.SetRealm(testing.NewUserRealm(alice))
 74	testing.SetOriginSend(ugnots(1))
 75	mustAbort(t, cur, "this call takes no payment", func() {
 76		Register(cross(cur), "alice", "", "", "")
 77	})
 78
 79	testing.SetRealm(testing.NewUserRealm(alice))
 80	testing.SetOriginSend(nil)
 81	Register(cross(cur), "alice", "Alice", "xin chao", "")
 82
 83	testing.SetRealm(testing.NewUserRealm(alice))
 84	testing.SetOriginSend(nil)
 85	mustAbort(t, cur, "already registered", func() {
 86		Register(cross(cur), "alice2", "", "", "")
 87	})
 88	testing.SetRealm(testing.NewUserRealm(bob))
 89	testing.SetOriginSend(nil)
 90	mustAbort(t, cur, "self referral", func() {
 91		Register(cross(cur), "bob", "", "", bob.String())
 92	})
 93
 94	_, ok := ProfileOf(bob)
 95	urequire.Equal(t, false, ok)
 96
 97	testing.SetRealm(testing.NewUserRealm(bob))
 98	testing.SetOriginSend(nil)
 99	Register(cross(cur), "bob", "", "", alice.String())
100
101	testing.SetRealm(testing.NewUserRealm(testutils.TestAddress("carol")))
102	testing.SetOriginSend(nil)
103	mustAbort(t, cur, "handle taken", func() {
104		Register(cross(cur), "alice", "", "", "")
105	})
106
107	testing.SetRealm(testing.NewUserRealm(alice))
108	testing.SetOriginSend(nil)
109	id := Post(cross(cur), "chao-arena", "")
110
111	got, ok := GetPost(id)
112	urequire.Equal(t, true, ok)
113	got.Body = "mutated"
114	again, _ := GetPost(id)
115	urequire.Equal(t, "chao-arena", again.Body)
116
117	testing.SetRealm(testing.NewUserRealm(bob))
118	testing.SetOriginSend(nil)
119	Like(cross(cur), id)
120	testing.SetRealm(testing.NewUserRealm(bob))
121	testing.SetOriginSend(nil)
122	mustAbort(t, cur, "already liked", func() {
123		Like(cross(cur), id)
124	})
125	Follow(cross(cur), "alice")
126	replyID := Reply(cross(cur), id, "tra loi")
127
128	aliceP, _ := ProfileByHandle("alice")
129	urequire.Equal(t, 1, aliceP.Followers)
130	urequire.Equal(t, 1, aliceP.Posts)
131	bobP, _ := ProfileByHandle("bob")
132	urequire.Equal(t, 1, bobP.Following)
133	post, _ := GetPost(id)
134	urequire.Equal(t, 1, post.Likes)
135	urequire.Equal(t, 1, post.Replies)
136	urequire.Equal(t, true, Following(bob, "alice"))
137
138	feed := Feed(0, 8)
139	urequire.Equal(t, "chao-arena", feed[0].Body)
140	urequire.Equal(t, false, strings.Contains(Render(""), "chao-arena"))
141
142	testing.SetRealm(testing.NewUserRealm(bob))
143	testing.SetOriginSend(nil)
144	Unlike(cross(cur), id)
145	Unfollow(cross(cur), "alice")
146	post, _ = GetPost(id)
147	urequire.Equal(t, 0, post.Likes)
148	aliceP, _ = ProfileByHandle("alice")
149	urequire.Equal(t, 0, aliceP.Followers)
150
151	testing.SetRealm(testing.NewUserRealm(alice))
152	testing.SetOriginSend(nil)
153	Delete(cross(cur), id)
154	post, _ = GetPost(id)
155	urequire.Equal(t, true, post.Deleted)
156	urequire.Equal(t, "", post.Body)
157	urequire.Equal(t, false, strings.Contains(Render(""), "chao-arena"))
158	reply, ok := GetPost(replyID)
159	urequire.Equal(t, true, ok)
160	urequire.Equal(t, "tra loi", reply.Body)
161
162	urequire.Equal(t, true, strings.Contains(Render(""), "Gnocial"))
163}
164
165func TestGatedBody(cur realm, t *testing.T) {
166	resetArena()
167	realmAddr := cur.Address()
168	alice := testutils.TestAddress("alice")
169	bob := testutils.TestAddress("bob")
170	const secret = "bi-mat-ve-99"
171
172	testing.SetRealm(testing.NewUserRealm(alice))
173	testing.SetOriginSend(nil)
174	Register(cross(cur), "alice", "", "", "")
175	id := Post(cross(cur), secret, "yes")
176
177	urequire.Equal(t, false, strings.Contains(Render(""), secret))
178	urequire.Equal(t, false, strings.Contains(Render("p/"+strconv.Itoa(id)), secret))
179
180	testing.SetRealm(testing.NewUserRealm(bob))
181	testing.SetOriginSend(nil)
182	Register(cross(cur), "bob", "", "", "")
183	testing.SetRealm(testing.NewUserRealm(bob))
184	testing.SetOriginSend(nil)
185	mustAbort(t, cur, "need a ticket", func() {
186		GatedBody(cross(cur), id)
187	})
188
189	testing.SetRealm(testing.NewUserRealm(alice))
190	testing.SetOriginSend(nil)
191	urequire.Equal(t, secret, GatedBody(cross(cur), id))
192
193	due, _, _, _, _ := QuoteBuy("alice", 1)
194	testing.IssueCoins(realmAddr, ugnots(due))
195	testing.SetRealm(testing.NewUserRealm(bob))
196	testing.SetOriginSend(ugnots(due))
197	Buy(cross(cur), "alice", 1)
198	testing.SetOriginSend(nil)
199	urequire.Equal(t, secret, GatedBody(cross(cur), id))
200
201	testing.SetRealm(testing.NewUserRealm(bob))
202	testing.SetOriginSend(nil)
203	Sell(cross(cur), "alice", 1)
204	testing.SetRealm(testing.NewUserRealm(bob))
205	testing.SetOriginSend(nil)
206	mustAbort(t, cur, "need a ticket", func() {
207		GatedBody(cross(cur), id)
208	})
209}
210
211func TestTicketRoundTrip(cur realm, t *testing.T) {
212	resetArena()
213	realmAddr := cur.Address()
214	alice := testutils.TestAddress("alice")
215	bob := testutils.TestAddress("bob")
216	carol := testutils.TestAddress("carol")
217	treasury := testutils.TestAddress("treasury")
218
219	testing.SetRealm(testing.NewUserRealm(alice))
220	testing.SetOriginSend(nil)
221	Register(cross(cur), "alice", "", "", "")
222	testing.SetRealm(testing.NewUserRealm(bob))
223	testing.SetOriginSend(nil)
224	Register(cross(cur), "bob", "", "", alice.String())
225	testing.SetRealm(testing.NewUserRealm(carol))
226	testing.SetOriginSend(nil)
227	Register(cross(cur), "carol", "", "", "")
228
229	dueA, curveA, _, _, refA := QuoteBuy("alice", 1)
230	urequire.Equal(t, int64(10_000), curveA)
231	urequire.Equal(t, int64(0), refA)
232	urequire.Equal(t, int64(11_000), dueA)
233
234	due, curve, creatorFee, protocolFee, referralFee := QuoteBuy("bob", 1)
235	urequire.Equal(t, int64(10_000), curve)
236	urequire.Equal(t, int64(500), creatorFee)
237	urequire.Equal(t, int64(450), protocolFee)
238	urequire.Equal(t, int64(50), referralFee)
239	urequire.Equal(t, int64(11_000), due)
240
241	startRealm := bal(realmAddr)
242	startAlice := bal(alice)
243	startBob := bal(bob)
244	startTreasury := bal(treasury)
245
246	testing.IssueCoins(realmAddr, ugnots(due))
247	testing.SetRealm(testing.NewUserRealm(carol))
248	testing.SetOriginSend(ugnots(due))
249	Buy(cross(cur), "bob", 1)
250
251	urequire.Equal(t, 1, SharesOf(carol, "bob"))
252	supply, reserve, holders := SupplyOf("bob")
253	urequire.Equal(t, 1, supply)
254	urequire.Equal(t, int64(10_000), reserve)
255	urequire.Equal(t, 1, holders)
256	urequire.Equal(t, int64(10_000), TotalReserve())
257	urequire.Equal(t, startAlice+50, bal(alice))
258	urequire.Equal(t, startBob+500, bal(bob))
259	urequire.Equal(t, startTreasury+450, bal(treasury))
260	urequire.Equal(t, startRealm+10_000, bal(realmAddr))
261
262	proceeds, _, _, _, _ := QuoteSell("bob", 1)
263	urequire.Equal(t, int64(9_000), proceeds)
264	startCarol := bal(carol)
265	testing.SetRealm(testing.NewUserRealm(carol))
266	testing.SetOriginSend(nil)
267	Sell(cross(cur), "bob", 1)
268
269	urequire.Equal(t, 0, SharesOf(carol, "bob"))
270	supply, reserve, holders = SupplyOf("bob")
271	urequire.Equal(t, 0, supply)
272	urequire.Equal(t, int64(0), reserve)
273	urequire.Equal(t, 0, holders)
274	urequire.Equal(t, int64(0), TotalReserve())
275	urequire.Equal(t, startCarol+proceeds, bal(carol))
276	urequire.Equal(t, startAlice+100, bal(alice))
277	urequire.Equal(t, startBob+1_000, bal(bob))
278	urequire.Equal(t, startTreasury+900, bal(treasury))
279	urequire.Equal(t, startRealm, bal(realmAddr))
280
281	testing.SetRealm(testing.NewUserRealm(carol))
282	testing.SetOriginSend(nil)
283	mustAbort(t, cur, "not enough tickets", func() {
284		Sell(cross(cur), "bob", 1)
285	})
286}
287
288func TestTipForwards(cur realm, t *testing.T) {
289	resetArena()
290	realmAddr := cur.Address()
291	alice := testutils.TestAddress("alice")
292	bob := testutils.TestAddress("bob")
293
294	testing.SetRealm(testing.NewUserRealm(alice))
295	testing.SetOriginSend(nil)
296	Register(cross(cur), "alice", "", "", "")
297	id := Post(cross(cur), "tip me", "")
298	testing.SetRealm(testing.NewUserRealm(bob))
299	testing.SetOriginSend(nil)
300	Register(cross(cur), "bob", "", "", "")
301
302	startRealm := bal(realmAddr)
303	startAlice := bal(alice)
304	testing.IssueCoins(realmAddr, ugnots(25_000))
305	testing.SetRealm(testing.NewUserRealm(bob))
306	testing.SetOriginSend(ugnots(25_000))
307	Tip(cross(cur), id)
308
309	urequire.Equal(t, startRealm, bal(realmAddr))
310	urequire.Equal(t, startAlice+25_000, bal(alice))
311	post, _ := GetPost(id)
312	urequire.Equal(t, int64(25_000), post.Tips)
313	aliceP, _ := ProfileByHandle("alice")
314	urequire.Equal(t, int64(25_000), aliceP.TipsIn)
315	bobP, _ := ProfileByHandle("bob")
316	urequire.Equal(t, int64(25_000), bobP.TipsOut)
317}
318
319func TestPaymentGuards(cur realm, t *testing.T) {
320	resetArena()
321	alice := testutils.TestAddress("alice")
322	bob := testutils.TestAddress("bob")
323
324	testing.SetRealm(testing.NewCodeRealm("gno.land/r/evil/proxy"))
325	testing.SetOriginSend(ugnots(11_000))
326	mustAbort(t, cur, "direct user call only", func() {
327		Buy(cross(cur), "alice", 1)
328	})
329
330	testing.SetRealm(testing.NewUserRealm(alice))
331	testing.SetOriginSend(nil)
332	Register(cross(cur), "alice", "", "", "")
333	testing.SetRealm(testing.NewUserRealm(bob))
334	testing.SetOriginSend(nil)
335	Register(cross(cur), "bob", "", "", "")
336
337	due, _, _, _, _ := QuoteBuy("alice", 1)
338	testing.SetRealm(testing.NewUserRealm(bob))
339	testing.SetOriginSend(ugnots(1))
340	mustAbort(t, cur, "send exactly "+strconv.FormatInt(due, 10)+"ugnot", func() {
341		Buy(cross(cur), "alice", 1)
342	})
343	testing.SetRealm(testing.NewUserRealm(bob))
344	testing.SetOriginSend(chain.Coins{chain.NewCoin("atom", due)})
345	mustAbort(t, cur, "send ugnot only", func() {
346		Buy(cross(cur), "alice", 1)
347	})
348	testing.SetRealm(testing.NewUserRealm(bob))
349	testing.SetOriginSend(chain.Coins{
350		chain.NewCoin("atom", 1),
351		chain.NewCoin("ugnot", due),
352	})
353	mustAbort(t, cur, "send ugnot only", func() {
354		Buy(cross(cur), "alice", 1)
355	})
356
357	// A rejected buy must not mint tickets.
358	urequire.Equal(t, 0, SharesOf(bob, "alice"))
359	urequire.Equal(t, int64(0), TotalReserve())
360}
361
362func TestPauseStillSells(cur realm, t *testing.T) {
363	resetArena()
364	realmAddr := cur.Address()
365	alice := testutils.TestAddress("alice")
366	bob := testutils.TestAddress("bob")
367	admin := testutils.TestAddress("admin")
368
369	testing.SetRealm(testing.NewUserRealm(alice))
370	testing.SetOriginSend(nil)
371	Register(cross(cur), "alice", "", "", "")
372	testing.SetRealm(testing.NewUserRealm(bob))
373	testing.SetOriginSend(nil)
374	Register(cross(cur), "bob", "", "", "")
375
376	due, _, _, _, _ := QuoteBuy("alice", 1)
377	testing.IssueCoins(realmAddr, ugnots(due))
378	testing.SetRealm(testing.NewUserRealm(bob))
379	testing.SetOriginSend(ugnots(due))
380	Buy(cross(cur), "alice", 1)
381
382	testing.SetRealm(testing.NewUserRealm(admin))
383	testing.SetOriginSend(nil)
384	SetPaused(cross(cur), "yes")
385	urequire.Equal(t, true, Paused())
386
387	testing.SetRealm(testing.NewUserRealm(alice))
388	testing.SetOriginSend(nil)
389	mustAbort(t, cur, "paused", func() {
390		Post(cross(cur), "nope", "")
391	})
392	testing.SetRealm(testing.NewUserRealm(bob))
393	testing.SetOriginSend(ugnots(due))
394	mustAbort(t, cur, "paused", func() {
395		Buy(cross(cur), "alice", 1)
396	})
397
398	testing.SetRealm(testing.NewUserRealm(bob))
399	testing.SetOriginSend(nil)
400	Sell(cross(cur), "alice", 1)
401	urequire.Equal(t, 0, SharesOf(bob, "alice"))
402	urequire.Equal(t, int64(0), TotalReserve())
403}
404
405func TestSweepKeepsReserve(cur realm, t *testing.T) {
406	resetArena()
407	realmAddr := cur.Address()
408	alice := testutils.TestAddress("alice")
409	bob := testutils.TestAddress("bob")
410	admin := testutils.TestAddress("admin")
411	treasury := testutils.TestAddress("treasury")
412
413	testing.SetRealm(testing.NewUserRealm(alice))
414	testing.SetOriginSend(nil)
415	Register(cross(cur), "alice", "", "", "")
416	testing.SetRealm(testing.NewUserRealm(bob))
417	testing.SetOriginSend(nil)
418	Register(cross(cur), "bob", "", "", "")
419
420	due, _, _, _, _ := QuoteBuy("alice", 1)
421	testing.IssueCoins(realmAddr, ugnots(due))
422	testing.SetRealm(testing.NewUserRealm(bob))
423	testing.SetOriginSend(ugnots(due))
424	Buy(cross(cur), "alice", 1)
425	urequire.Equal(t, int64(10_000), TotalReserve())
426
427	testing.SetRealm(testing.NewUserRealm(bob))
428	testing.SetOriginSend(nil)
429	mustAbort(t, cur, "admin only", func() {
430		Sweep(cross(cur), "sweep")
431	})
432	testing.SetRealm(testing.NewUserRealm(admin))
433	testing.SetOriginSend(nil)
434	mustAbort(t, cur, "confirm sweep", func() {
435		Sweep(cross(cur), "please")
436	})
437
438	testing.IssueCoins(realmAddr, ugnots(77))
439	beforeT := bal(treasury)
440	surplus := bal(realmAddr) - TotalReserve()
441	testing.SetRealm(testing.NewUserRealm(admin))
442	testing.SetOriginSend(nil)
443	Sweep(cross(cur), "sweep")
444	urequire.Equal(t, TotalReserve(), bal(realmAddr))
445	urequire.Equal(t, beforeT+surplus, bal(treasury))
446	urequire.Equal(t, int64(10_000), TotalReserve())
447	supply, reserve, _ := SupplyOf("alice")
448	urequire.Equal(t, 1, supply)
449	urequire.Equal(t, int64(10_000), reserve)
450}
451
452func TestCreatorFeeSchedule(cur realm, t *testing.T) {
453	resetArena()
454	realmAddr := cur.Address()
455	alice := testutils.TestAddress("alice")
456	bob := testutils.TestAddress("bob")
457	carol := testutils.TestAddress("carol")
458	dave := testutils.TestAddress("dave")
459	eve := testutils.TestAddress("eve")
460	treasury := testutils.TestAddress("treasury")
461
462	testing.SetRealm(testing.NewUserRealm(alice))
463	testing.SetOriginSend(nil)
464	Register(cross(cur), "alice", "", "", "")
465	aliceP, _ := ProfileByHandle("alice")
466	urequire.Equal(t, CreatorFeeDefaultBps, aliceP.CreatorFee)
467
468	testing.SetRealm(testing.NewUserRealm(bob))
469	testing.SetOriginSend(nil)
470	Register(cross(cur), "bob", "", "", alice.String())
471	testing.SetRealm(testing.NewUserRealm(carol))
472	testing.SetOriginSend(nil)
473	Register(cross(cur), "carol", "", "", "")
474	testing.SetRealm(testing.NewUserRealm(dave))
475	testing.SetOriginSend(nil)
476	Register(cross(cur), "dave", "", "", alice.String())
477
478	testing.SetRealm(testing.NewUserRealm(alice))
479	testing.SetOriginSend(nil)
480	SetCreatorFee(cross(cur), 100)
481	dueAlice, _, cf, pf, rf := QuoteBuy("alice", 1)
482	urequire.Equal(t, int64(11_000), dueAlice)
483	urequire.Equal(t, int64(100), cf)
484	urequire.Equal(t, int64(900), pf)
485	urequire.Equal(t, int64(0), rf)
486
487	testing.SetRealm(testing.NewUserRealm(alice))
488	testing.SetOriginSend(nil)
489	SetCreatorFee(cross(cur), 700)
490	_, _, cf, pf, rf = QuoteBuy("alice", 1)
491	urequire.Equal(t, int64(700), cf)
492	urequire.Equal(t, int64(300), pf)
493	urequire.Equal(t, int64(0), rf)
494
495	testing.SetRealm(testing.NewUserRealm(alice))
496	testing.SetOriginSend(nil)
497	mustAbort(t, cur, "fee", func() {
498		SetCreatorFee(cross(cur), 99)
499	})
500	testing.SetRealm(testing.NewUserRealm(alice))
501	testing.SetOriginSend(nil)
502	mustAbort(t, cur, "fee", func() {
503		SetCreatorFee(cross(cur), 701)
504	})
505	testing.SetRealm(testing.NewUserRealm(alice))
506	testing.SetOriginSend(ugnots(1))
507	mustAbort(t, cur, "this call takes no payment", func() {
508		SetCreatorFee(cross(cur), 500)
509	})
510	testing.SetRealm(testing.NewUserRealm(eve))
511	testing.SetOriginSend(nil)
512	mustAbort(t, cur, "register first", func() {
513		SetCreatorFee(cross(cur), 500)
514	})
515
516	testing.SetRealm(testing.NewUserRealm(carol))
517	testing.SetOriginSend(nil)
518	SetCreatorFee(cross(cur), 100)
519	bobP, _ := ProfileByHandle("bob")
520	urequire.Equal(t, int64(500), bobP.CreatorFee)
521	carolP, _ := ProfileByHandle("carol")
522	urequire.Equal(t, int64(100), carolP.CreatorFee)
523
524	testing.SetRealm(testing.NewUserRealm(bob))
525	testing.SetOriginSend(nil)
526	SetCreatorFee(cross(cur), 700)
527	due, curve, cf, pf, rf := QuoteBuyFor("bob", dave.String(), 1)
528	urequire.Equal(t, int64(10_000), curve)
529	urequire.Equal(t, int64(11_000), due)
530	urequire.Equal(t, int64(700), cf)
531	urequire.Equal(t, int64(200), pf)
532	urequire.Equal(t, int64(100), rf)
533	same, _, _, _, _ := QuoteBuy("bob", 1)
534	urequire.Equal(t, due, same)
535	_, _, _, pf, rf = QuoteBuyFor("bob", eve.String(), 1)
536	urequire.Equal(t, int64(250), pf)
537	urequire.Equal(t, int64(50), rf)
538	if !uassert.PanicsWithMessage(t, cur, "bad address", func() {
539		QuoteBuyFor("bob", "not-an-address", 1)
540	}) {
541		t.FailNow()
542	}
543
544	testing.SetRealm(testing.NewUserRealm(bob))
545	testing.SetOriginSend(nil)
546	SetCreatorFee(cross(cur), 500)
547	due, _, cf, pf, rf = QuoteBuyFor("bob", dave.String(), 1)
548	urequire.Equal(t, int64(500), cf)
549	urequire.Equal(t, int64(400), pf)
550	urequire.Equal(t, int64(100), rf)
551
552	startRealm := bal(realmAddr)
553	startAlice := bal(alice)
554	startBob := bal(bob)
555	startTreasury := bal(treasury)
556	testing.IssueCoins(realmAddr, ugnots(due))
557	testing.SetRealm(testing.NewUserRealm(dave))
558	testing.SetOriginSend(ugnots(due))
559	Buy(cross(cur), "bob", 1)
560	urequire.Equal(t, startAlice+100, bal(alice))
561	urequire.Equal(t, startBob+500, bal(bob))
562	urequire.Equal(t, startTreasury+400, bal(treasury))
563	urequire.Equal(t, startRealm+10_000, bal(realmAddr))
564
565	proceeds, _, _, _, _ := QuoteSellFor("bob", dave.String(), 1)
566	urequire.Equal(t, int64(9_000), proceeds)
567	testing.SetRealm(testing.NewUserRealm(dave))
568	testing.SetOriginSend(nil)
569	Sell(cross(cur), "bob", 1)
570	urequire.Equal(t, startAlice+200, bal(alice))
571	urequire.Equal(t, startBob+1_000, bal(bob))
572	urequire.Equal(t, startTreasury+800, bal(treasury))
573	urequire.Equal(t, startRealm, bal(realmAddr))
574	urequire.Equal(t, int64(0), TotalReserve())
575}