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}