rippled
Loading...
Searching...
No Matches
Check_test.cpp
1#include <test/jtx.h>
2
3#include <xrpl/protocol/Feature.h>
4#include <xrpl/protocol/jss.h>
5
6namespace ripple {
7namespace test {
8namespace jtx {
9
12{
13private:
15
16public:
17 explicit expiration(NetClock::time_point const& expiry)
18 : expry_{expiry.time_since_epoch().count()}
19 {
20 }
21
22 void
23 operator()(Env&, JTx& jt) const
24 {
25 jt[sfExpiration.jsonName] = expry_;
26 }
27};
28
31{
32private:
34
35public:
36 explicit source_tag(std::uint32_t tag) : tag_{tag}
37 {
38 }
39
40 void
41 operator()(Env&, JTx& jt) const
42 {
43 jt[sfSourceTag.jsonName] = tag_;
44 }
45};
46
49{
50private:
52
53public:
54 explicit dest_tag(std::uint32_t tag) : tag_{tag}
55 {
56 }
57
58 void
59 operator()(Env&, JTx& jt) const
60 {
61 jt[sfDestinationTag.jsonName] = tag_;
62 }
63};
64
65} // namespace jtx
66} // namespace test
67
69{
70 FeatureBitset const disallowIncoming{featureDisallowIncoming};
71
72 static uint256
73 getCheckIndex(AccountID const& account, std::uint32_t uSequence)
74 {
75 return keylet::check(account, uSequence).key;
76 }
77
78 // Helper function that returns the Checks on an account.
81 {
84 *env.current(),
85 account,
86 [&result](std::shared_ptr<SLE const> const& sle) {
87 if (sle && sle->getType() == ltCHECK)
88 result.push_back(sle);
89 });
90 return result;
91 }
92
93 // Helper function that verifies the expected DeliveredAmount is present.
94 //
95 // NOTE: the function _infers_ the transaction to operate on by calling
96 // env.tx(), which returns the result from the most recent transaction.
97 void
99 {
100 // Get the hash for the most recent transaction.
101 std::string const txHash{
102 env.tx()->getJson(JsonOptions::none)[jss::hash].asString()};
103
104 // Verify DeliveredAmount and delivered_amount metadata are correct.
105 env.close();
106 Json::Value const meta = env.rpc("tx", txHash)[jss::result][jss::meta];
107
108 // Expect there to be a DeliveredAmount field.
109 if (!BEAST_EXPECT(meta.isMember(sfDeliveredAmount.jsonName)))
110 return;
111
112 // DeliveredAmount and delivered_amount should both be present and
113 // equal amount.
114 BEAST_EXPECT(
115 meta[sfDeliveredAmount.jsonName] ==
116 amount.getJson(JsonOptions::none));
117 BEAST_EXPECT(
118 meta[jss::delivered_amount] == amount.getJson(JsonOptions::none));
119 }
120
121 void
123 {
124 testcase("Enabled");
125
126 using namespace test::jtx;
127 Account const alice{"alice"};
128 {
129 // If the Checks amendment is not enabled, you should not be able
130 // to create, cash, or cancel checks.
131 Env env{*this, features - featureChecks};
132
133 env.fund(XRP(1000), alice);
134 env.close();
135
136 uint256 const checkId{
137 getCheckIndex(env.master, env.seq(env.master))};
138 env(check::create(env.master, alice, XRP(100)), ter(temDISABLED));
139 env.close();
140
141 env(check::cash(alice, checkId, XRP(100)), ter(temDISABLED));
142 env.close();
143
144 env(check::cancel(alice, checkId), ter(temDISABLED));
145 env.close();
146 }
147 {
148 // If the Checks amendment is enabled all check-related
149 // facilities should be available.
150 Env env{*this, features};
151
152 env.fund(XRP(1000), alice);
153 env.close();
154
155 uint256 const checkId1{
156 getCheckIndex(env.master, env.seq(env.master))};
157 env(check::create(env.master, alice, XRP(100)));
158 env.close();
159
160 env(check::cash(alice, checkId1, XRP(100)));
161 env.close();
162
163 uint256 const checkId2{
164 getCheckIndex(env.master, env.seq(env.master))};
165 env(check::create(env.master, alice, XRP(100)));
166 env.close();
167
168 env(check::cancel(alice, checkId2));
169 env.close();
170 }
171 }
172
173 void
175 {
176 // Explore many of the valid ways to create a check.
177 testcase("Create valid");
178
179 using namespace test::jtx;
180
181 Account const gw{"gateway"};
182 Account const alice{"alice"};
183 Account const bob{"bob"};
184 IOU const USD{gw["USD"]};
185
186 Env env{*this, features};
187
188 STAmount const startBalance{XRP(1000).value()};
189 env.fund(startBalance, gw, alice, bob);
190 env.close();
191
192 // Note that no trust line has been set up for alice, but alice can
193 // still write a check for USD. You don't have to have the funds
194 // necessary to cover a check in order to write a check.
195 auto writeTwoChecks = [&env, &USD, this](
196 Account const& from, Account const& to) {
197 std::uint32_t const fromOwnerCount{ownerCount(env, from)};
198 std::uint32_t const toOwnerCount{ownerCount(env, to)};
199
200 std::size_t const fromCkCount{checksOnAccount(env, from).size()};
201 std::size_t const toCkCount{checksOnAccount(env, to).size()};
202
203 env(check::create(from, to, XRP(2000)));
204 env.close();
205
206 env(check::create(from, to, USD(50)));
207 env.close();
208
209 BEAST_EXPECT(checksOnAccount(env, from).size() == fromCkCount + 2);
210 BEAST_EXPECT(checksOnAccount(env, to).size() == toCkCount + 2);
211
212 env.require(owners(from, fromOwnerCount + 2));
213 env.require(
214 owners(to, to == from ? fromOwnerCount + 2 : toOwnerCount));
215 };
216 // from to
217 writeTwoChecks(alice, bob);
218 writeTwoChecks(gw, alice);
219 writeTwoChecks(alice, gw);
220
221 // Now try adding the various optional fields. There's no
222 // expected interaction between these optional fields; other than
223 // the expiration, they are just plopped into the ledger. So I'm
224 // not looking at interactions.
225 using namespace std::chrono_literals;
226 std::size_t const aliceCount{checksOnAccount(env, alice).size()};
227 std::size_t const bobCount{checksOnAccount(env, bob).size()};
228 env(check::create(alice, bob, USD(50)), expiration(env.now() + 1s));
229 env.close();
230
231 env(check::create(alice, bob, USD(50)), source_tag(2));
232 env.close();
233 env(check::create(alice, bob, USD(50)), dest_tag(3));
234 env.close();
235 env(check::create(alice, bob, USD(50)), invoice_id(uint256{4}));
236 env.close();
237 env(check::create(alice, bob, USD(50)),
238 expiration(env.now() + 1s),
239 source_tag(12),
240 dest_tag(13),
241 invoice_id(uint256{4}));
242 env.close();
243
244 BEAST_EXPECT(checksOnAccount(env, alice).size() == aliceCount + 5);
245 BEAST_EXPECT(checksOnAccount(env, bob).size() == bobCount + 5);
246
247 // Use a regular key and also multisign to create a check.
248 Account const alie{"alie", KeyType::ed25519};
249 env(regkey(alice, alie));
250 env.close();
251
252 Account const bogie{"bogie", KeyType::secp256k1};
253 Account const demon{"demon", KeyType::ed25519};
254 env(signers(alice, 2, {{bogie, 1}, {demon, 1}}), sig(alie));
255 env.close();
256
257 // alice uses her regular key to create a check.
258 env(check::create(alice, bob, USD(50)), sig(alie));
259 env.close();
260 BEAST_EXPECT(checksOnAccount(env, alice).size() == aliceCount + 6);
261 BEAST_EXPECT(checksOnAccount(env, bob).size() == bobCount + 6);
262
263 // alice uses multisigning to create a check.
264 XRPAmount const baseFeeDrops{env.current()->fees().base};
265 env(check::create(alice, bob, USD(50)),
266 msig(bogie, demon),
267 fee(3 * baseFeeDrops));
268 env.close();
269 BEAST_EXPECT(checksOnAccount(env, alice).size() == aliceCount + 7);
270 BEAST_EXPECT(checksOnAccount(env, bob).size() == bobCount + 7);
271 }
272
273 void
275 {
276 testcase("Create valid with disallow incoming");
277
278 using namespace test::jtx;
279
280 // test flag doesn't set unless amendment enabled
281 {
282 Env env{*this, features - disallowIncoming};
283 Account const alice{"alice"};
284 env.fund(XRP(10000), alice);
285 env(fset(alice, asfDisallowIncomingCheck));
286 env.close();
287 auto const sle = env.le(alice);
288 uint32_t flags = sle->getFlags();
289 BEAST_EXPECT(!(flags & lsfDisallowIncomingCheck));
290 }
291
292 Account const gw{"gateway"};
293 Account const alice{"alice"};
294 Account const bob{"bob"};
295 IOU const USD{gw["USD"]};
296
297 Env env{*this, features | disallowIncoming};
298
299 STAmount const startBalance{XRP(1000).value()};
300 env.fund(startBalance, gw, alice, bob);
301 env.close();
302
303 /*
304 * Attempt to create two checks from `from` to `to` and
305 * require they both result in error/success code `expected`
306 */
307 auto writeTwoChecksDI = [&env, &USD, this](
308 Account const& from,
309 Account const& to,
310 TER expected) {
311 std::uint32_t const fromOwnerCount{ownerCount(env, from)};
312 std::uint32_t const toOwnerCount{ownerCount(env, to)};
313
314 std::size_t const fromCkCount{checksOnAccount(env, from).size()};
315 std::size_t const toCkCount{checksOnAccount(env, to).size()};
316
317 env(check::create(from, to, XRP(2000)), ter(expected));
318 env.close();
319
320 env(check::create(from, to, USD(50)), ter(expected));
321 env.close();
322
323 if (expected == tesSUCCESS)
324 {
325 BEAST_EXPECT(
326 checksOnAccount(env, from).size() == fromCkCount + 2);
327 BEAST_EXPECT(checksOnAccount(env, to).size() == toCkCount + 2);
328
329 env.require(owners(from, fromOwnerCount + 2));
330 env.require(
331 owners(to, to == from ? fromOwnerCount + 2 : toOwnerCount));
332 return;
333 }
334
335 BEAST_EXPECT(checksOnAccount(env, from).size() == fromCkCount);
336 BEAST_EXPECT(checksOnAccount(env, to).size() == toCkCount);
337
338 env.require(owners(from, fromOwnerCount));
339 env.require(owners(to, to == from ? fromOwnerCount : toOwnerCount));
340 };
341
342 // enable the DisallowIncoming flag on both bob and alice
343 env(fset(bob, asfDisallowIncomingCheck));
344 env(fset(alice, asfDisallowIncomingCheck));
345 env.close();
346
347 // both alice and bob can't receive checks
348 writeTwoChecksDI(alice, bob, tecNO_PERMISSION);
349 writeTwoChecksDI(gw, alice, tecNO_PERMISSION);
350
351 // remove the flag from alice but not from bob
352 env(fclear(alice, asfDisallowIncomingCheck));
353 env.close();
354
355 // now bob can send alice a cheque but not visa-versa
356 writeTwoChecksDI(bob, alice, tesSUCCESS);
357 writeTwoChecksDI(alice, bob, tecNO_PERMISSION);
358
359 // remove bob's flag too
360 env(fclear(bob, asfDisallowIncomingCheck));
361 env.close();
362
363 // now they can send checks freely
364 writeTwoChecksDI(bob, alice, tesSUCCESS);
365 writeTwoChecksDI(alice, bob, tesSUCCESS);
366 }
367
368 void
370 {
371 // Explore many of the invalid ways to create a check.
372 testcase("Create invalid");
373
374 using namespace test::jtx;
375
376 Account const gw1{"gateway1"};
377 Account const gwF{"gatewayFrozen"};
378 Account const alice{"alice"};
379 Account const bob{"bob"};
380 IOU const USD{gw1["USD"]};
381
382 Env env{*this, features};
383
384 STAmount const startBalance{XRP(1000).value()};
385 env.fund(startBalance, gw1, gwF, alice, bob);
386 env.close();
387
388 // Bad fee.
389 env(check::create(alice, bob, USD(50)),
390 fee(drops(-10)),
391 ter(temBAD_FEE));
392 env.close();
393
394 // Bad flags.
395 env(check::create(alice, bob, USD(50)),
396 txflags(tfImmediateOrCancel),
397 ter(temINVALID_FLAG));
398 env.close();
399
400 // Check to self.
401 env(check::create(alice, alice, XRP(10)), ter(temREDUNDANT));
402 env.close();
403
404 // Bad amount.
405 env(check::create(alice, bob, drops(-1)), ter(temBAD_AMOUNT));
406 env.close();
407
408 env(check::create(alice, bob, drops(0)), ter(temBAD_AMOUNT));
409 env.close();
410
411 env(check::create(alice, bob, drops(1)));
412 env.close();
413
414 env(check::create(alice, bob, USD(-1)), ter(temBAD_AMOUNT));
415 env.close();
416
417 env(check::create(alice, bob, USD(0)), ter(temBAD_AMOUNT));
418 env.close();
419
420 env(check::create(alice, bob, USD(1)));
421 env.close();
422 {
423 IOU const BAD{gw1, badCurrency()};
424 env(check::create(alice, bob, BAD(2)), ter(temBAD_CURRENCY));
425 env.close();
426 }
427
428 // Bad expiration.
429 env(check::create(alice, bob, USD(50)),
430 expiration(NetClock::time_point{}),
431 ter(temBAD_EXPIRATION));
432 env.close();
433
434 // Destination does not exist.
435 Account const bogie{"bogie"};
436 env(check::create(alice, bogie, USD(50)), ter(tecNO_DST));
437 env.close();
438
439 // Require destination tag.
440 env(fset(bob, asfRequireDest));
441 env.close();
442
443 env(check::create(alice, bob, USD(50)), ter(tecDST_TAG_NEEDED));
444 env.close();
445
446 env(check::create(alice, bob, USD(50)), dest_tag(11));
447 env.close();
448
449 env(fclear(bob, asfRequireDest));
450 env.close();
451 {
452 // Globally frozen asset.
453 IOU const USF{gwF["USF"]};
454 env(fset(gwF, asfGlobalFreeze));
455 env.close();
456
457 env(check::create(alice, bob, USF(50)), ter(tecFROZEN));
458 env.close();
459
460 env(fclear(gwF, asfGlobalFreeze));
461 env.close();
462
463 env(check::create(alice, bob, USF(50)));
464 env.close();
465 }
466 {
467 // Frozen trust line. Check creation should be similar to payment
468 // behavior in the face of frozen trust lines.
469 env.trust(USD(1000), alice);
470 env.trust(USD(1000), bob);
471 env.close();
472 env(pay(gw1, alice, USD(25)));
473 env(pay(gw1, bob, USD(25)));
474 env.close();
475
476 // Setting trustline freeze in one direction prevents alice from
477 // creating a check for USD. But bob and gw1 should still be able
478 // to create a check for USD to alice.
479 env(trust(gw1, alice["USD"](0), tfSetFreeze));
480 env.close();
481 env(check::create(alice, bob, USD(50)), ter(tecFROZEN));
482 env.close();
483 env(pay(alice, bob, USD(1)), ter(tecPATH_DRY));
484 env.close();
485 env(check::create(bob, alice, USD(50)));
486 env.close();
487 env(pay(bob, alice, USD(1)));
488 env.close();
489 env(check::create(gw1, alice, USD(50)));
490 env.close();
491 env(pay(gw1, alice, USD(1)));
492 env.close();
493
494 // Clear that freeze. Now check creation works.
495 env(trust(gw1, alice["USD"](0), tfClearFreeze));
496 env.close();
497 env(check::create(alice, bob, USD(50)));
498 env.close();
499 env(check::create(bob, alice, USD(50)));
500 env.close();
501 env(check::create(gw1, alice, USD(50)));
502 env.close();
503
504 // Freezing in the other direction does not effect alice's USD
505 // check creation, but prevents bob and gw1 from writing a check
506 // for USD to alice.
507 env(trust(alice, USD(0), tfSetFreeze));
508 env.close();
509 env(check::create(alice, bob, USD(50)));
510 env.close();
511 env(pay(alice, bob, USD(1)));
512 env.close();
513 env(check::create(bob, alice, USD(50)), ter(tecFROZEN));
514 env.close();
515 env(pay(bob, alice, USD(1)), ter(tecPATH_DRY));
516 env.close();
517 env(check::create(gw1, alice, USD(50)), ter(tecFROZEN));
518 env.close();
519 env(pay(gw1, alice, USD(1)), ter(tecPATH_DRY));
520 env.close();
521
522 // Clear that freeze.
523 env(trust(alice, USD(0), tfClearFreeze));
524 env.close();
525 }
526
527 // Expired expiration.
528 env(check::create(alice, bob, USD(50)),
529 expiration(env.now()),
530 ter(tecEXPIRED));
531 env.close();
532
533 using namespace std::chrono_literals;
534 env(check::create(alice, bob, USD(50)), expiration(env.now() + 1s));
535 env.close();
536
537 // Insufficient reserve.
538 Account const cheri{"cheri"};
539 env.fund(env.current()->fees().accountReserve(1) - drops(1), cheri);
540 env.close();
541
542 env(check::create(cheri, bob, USD(50)),
543 fee(drops(env.current()->fees().base)),
545 env.close();
546
547 env(pay(bob, cheri, drops(env.current()->fees().base + 1)));
548 env.close();
549
550 env(check::create(cheri, bob, USD(50)));
551 env.close();
552 }
553
554 void
556 {
557 // Explore many of the valid ways to cash a check for XRP.
558 testcase("Cash XRP");
559
560 using namespace test::jtx;
561
562 Account const alice{"alice"};
563 Account const bob{"bob"};
564
565 Env env{*this, features};
566
567 XRPAmount const baseFeeDrops{env.current()->fees().base};
568 STAmount const startBalance{XRP(300).value()};
569 env.fund(startBalance, alice, bob);
570 env.close();
571 {
572 // Basic XRP check.
573 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
574 env(check::create(alice, bob, XRP(10)));
575 env.close();
576 env.require(balance(alice, startBalance - drops(baseFeeDrops)));
577 env.require(balance(bob, startBalance));
578 BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
579 BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
580 BEAST_EXPECT(ownerCount(env, alice) == 1);
581 BEAST_EXPECT(ownerCount(env, bob) == 0);
582
583 env(check::cash(bob, chkId, XRP(10)));
584 env.close();
585 env.require(
586 balance(alice, startBalance - XRP(10) - drops(baseFeeDrops)));
587 env.require(
588 balance(bob, startBalance + XRP(10) - drops(baseFeeDrops)));
589 BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
590 BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
591 BEAST_EXPECT(ownerCount(env, alice) == 0);
592 BEAST_EXPECT(ownerCount(env, bob) == 0);
593
594 // Make alice's and bob's balances easy to think about.
595 env(pay(env.master, alice, XRP(10) + drops(baseFeeDrops)));
596 env(pay(bob, env.master, XRP(10) - drops(baseFeeDrops * 2)));
597 env.close();
598 env.require(balance(alice, startBalance));
599 env.require(balance(bob, startBalance));
600 }
601 {
602 // Write a check that chews into alice's reserve.
603 STAmount const reserve{env.current()->fees().reserve};
604 STAmount const checkAmount{
605 startBalance - reserve - drops(baseFeeDrops)};
606 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
607 env(check::create(alice, bob, checkAmount));
608 env.close();
609
610 // bob tries to cash for more than the check amount.
611 env(check::cash(bob, chkId, checkAmount + drops(1)),
612 ter(tecPATH_PARTIAL));
613 env.close();
614 env(check::cash(
615 bob, chkId, check::DeliverMin(checkAmount + drops(1))),
616 ter(tecPATH_PARTIAL));
617 env.close();
618
619 // bob cashes exactly the check amount. This is successful
620 // because one unit of alice's reserve is released when the
621 // check is consumed.
622 env(check::cash(bob, chkId, check::DeliverMin(checkAmount)));
623 verifyDeliveredAmount(env, drops(checkAmount.mantissa()));
624 env.require(balance(alice, reserve));
625 env.require(balance(
626 bob, startBalance + checkAmount - drops(baseFeeDrops * 3)));
627 BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
628 BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
629 BEAST_EXPECT(ownerCount(env, alice) == 0);
630 BEAST_EXPECT(ownerCount(env, bob) == 0);
631
632 // Make alice's and bob's balances easy to think about.
633 env(pay(env.master, alice, checkAmount + drops(baseFeeDrops)));
634 env(pay(bob, env.master, checkAmount - drops(baseFeeDrops * 4)));
635 env.close();
636 env.require(balance(alice, startBalance));
637 env.require(balance(bob, startBalance));
638 }
639 {
640 // Write a check that goes one drop past what alice can pay.
641 STAmount const reserve{env.current()->fees().reserve};
642 STAmount const checkAmount{
643 startBalance - reserve - drops(baseFeeDrops - 1)};
644 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
645 env(check::create(alice, bob, checkAmount));
646 env.close();
647
648 // bob tries to cash for exactly the check amount. Fails because
649 // alice is one drop shy of funding the check.
650 env(check::cash(bob, chkId, checkAmount), ter(tecPATH_PARTIAL));
651 env.close();
652
653 // bob decides to get what he can from the bounced check.
654 env(check::cash(bob, chkId, check::DeliverMin(drops(1))));
655 verifyDeliveredAmount(env, drops(checkAmount.mantissa() - 1));
656 env.require(balance(alice, reserve));
657 env.require(balance(
658 bob, startBalance + checkAmount - drops(baseFeeDrops * 2 + 1)));
659 BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
660 BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
661 BEAST_EXPECT(ownerCount(env, alice) == 0);
662 BEAST_EXPECT(ownerCount(env, bob) == 0);
663
664 // Make alice's and bob's balances easy to think about.
665 env(pay(env.master, alice, checkAmount + drops(baseFeeDrops - 1)));
666 env(pay(
667 bob, env.master, checkAmount - drops(baseFeeDrops * 3 + 1)));
668 env.close();
669 env.require(balance(alice, startBalance));
670 env.require(balance(bob, startBalance));
671 }
672 }
673
674 void
676 {
677 // Explore many of the valid ways to cash a check for an IOU.
678 testcase("Cash IOU");
679
680 using namespace test::jtx;
681
682 Account const gw{"gateway"};
683 Account const alice{"alice"};
684 Account const bob{"bob"};
685 IOU const USD{gw["USD"]};
686 {
687 // Simple IOU check cashed with Amount (with failures).
688 Env env{*this, features};
689
690 env.fund(XRP(1000), gw, alice, bob);
691 env.close();
692
693 // alice writes the check before she gets the funds.
694 uint256 const chkId1{getCheckIndex(alice, env.seq(alice))};
695 env(check::create(alice, bob, USD(10)));
696 env.close();
697
698 // bob attempts to cash the check. Should fail.
699 env(check::cash(bob, chkId1, USD(10)), ter(tecPATH_PARTIAL));
700 env.close();
701
702 // alice gets almost enough funds. bob tries and fails again.
703 env(trust(alice, USD(20)));
704 env.close();
705 env(pay(gw, alice, USD(9.5)));
706 env.close();
707 env(check::cash(bob, chkId1, USD(10)), ter(tecPATH_PARTIAL));
708 env.close();
709
710 // alice gets the last of the necessary funds. bob tries again
711 // and fails because he hasn't got a trust line for USD.
712 env(pay(gw, alice, USD(0.5)));
713 env.close();
714
715 // bob sets up the trust line, but not at a high enough limit.
716 env(trust(bob, USD(9.5)));
717 env.close();
718
719 // bob sets the trust line limit high enough but asks for more
720 // than the check's SendMax.
721 env(trust(bob, USD(10.5)));
722 env.close();
723 env(check::cash(bob, chkId1, USD(10.5)), ter(tecPATH_PARTIAL));
724 env.close();
725
726 // bob asks for exactly the check amount and the check clears.
727 env(check::cash(bob, chkId1, USD(10)));
728 env.close();
729 env.require(balance(alice, USD(0)));
730 env.require(balance(bob, USD(10)));
731 BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
732 BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
733 BEAST_EXPECT(ownerCount(env, alice) == 1);
734 BEAST_EXPECT(ownerCount(env, bob) == 1);
735
736 // bob tries to cash the same check again, which fails.
737 env(check::cash(bob, chkId1, USD(10)), ter(tecNO_ENTRY));
738 env.close();
739
740 // bob pays alice USD(7) so he can try another case.
741 env(pay(bob, alice, USD(7)));
742 env.close();
743
744 uint256 const chkId2{getCheckIndex(alice, env.seq(alice))};
745 env(check::create(alice, bob, USD(7)));
746 env.close();
747 BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
748 BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
749
750 // bob cashes the check for less than the face amount. That works,
751 // consumes the check, and bob receives as much as he asked for.
752 env(check::cash(bob, chkId2, USD(5)));
753 env.close();
754 env.require(balance(alice, USD(2)));
755 env.require(balance(bob, USD(8)));
756 BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
757 BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
758 BEAST_EXPECT(ownerCount(env, alice) == 1);
759 BEAST_EXPECT(ownerCount(env, bob) == 1);
760
761 // alice writes two checks for USD(2), although she only has USD(2).
762 uint256 const chkId3{getCheckIndex(alice, env.seq(alice))};
763 env(check::create(alice, bob, USD(2)));
764 env.close();
765 uint256 const chkId4{getCheckIndex(alice, env.seq(alice))};
766 env(check::create(alice, bob, USD(2)));
767 env.close();
768 BEAST_EXPECT(checksOnAccount(env, alice).size() == 2);
769 BEAST_EXPECT(checksOnAccount(env, bob).size() == 2);
770
771 // bob cashes the second check for the face amount.
772 env(check::cash(bob, chkId4, USD(2)));
773 env.close();
774 env.require(balance(alice, USD(0)));
775 env.require(balance(bob, USD(10)));
776 BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
777 BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
778 BEAST_EXPECT(ownerCount(env, alice) == 2);
779 BEAST_EXPECT(ownerCount(env, bob) == 1);
780
781 // bob is not allowed to cash the last check for USD(0), he must
782 // use check::cancel instead.
783 env(check::cash(bob, chkId3, USD(0)), ter(temBAD_AMOUNT));
784 env.close();
785 env.require(balance(alice, USD(0)));
786 env.require(balance(bob, USD(10)));
787 BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
788 BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
789 BEAST_EXPECT(ownerCount(env, alice) == 2);
790 BEAST_EXPECT(ownerCount(env, bob) == 1);
791
792 // Automatic trust lines are enabled. But one aspect of
793 // automatic trust lines is that they allow the account
794 // cashing a check to exceed their trust line limit. Show
795 // that at work.
796 //
797 // bob's trust line limit is currently USD(10.5). Show that
798 // a payment to bob cannot exceed that trust line, but cashing
799 // a check can.
800
801 // Payment of 20 USD fails.
802 env(pay(gw, bob, USD(20)), ter(tecPATH_PARTIAL));
803 env.close();
804
805 uint256 const chkId20{getCheckIndex(gw, env.seq(gw))};
806 env(check::create(gw, bob, USD(20)));
807 env.close();
808
809 // However cashing a check for 20 USD succeeds.
810 env(check::cash(bob, chkId20, USD(20)));
811 env.close();
812 env.require(balance(bob, USD(30)));
813
814 // Clean up this most recent experiment so the rest of the
815 // tests work.
816 env(pay(bob, gw, USD(20)));
817
818 // ... so bob cancels alice's remaining check.
819 env(check::cancel(bob, chkId3));
820 env.close();
821 env.require(balance(alice, USD(0)));
822 env.require(balance(bob, USD(10)));
823 BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
824 BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
825 BEAST_EXPECT(ownerCount(env, alice) == 1);
826 BEAST_EXPECT(ownerCount(env, bob) == 1);
827 }
828 {
829 // Simple IOU check cashed with DeliverMin (with failures).
830 Env env{*this, features};
831
832 env.fund(XRP(1000), gw, alice, bob);
833 env.close();
834
835 env(trust(alice, USD(20)));
836 env(trust(bob, USD(20)));
837 env.close();
838 env(pay(gw, alice, USD(8)));
839 env.close();
840
841 // alice creates several checks ahead of time.
842 uint256 const chkId9{getCheckIndex(alice, env.seq(alice))};
843 env(check::create(alice, bob, USD(9)));
844 env.close();
845 uint256 const chkId8{getCheckIndex(alice, env.seq(alice))};
846 env(check::create(alice, bob, USD(8)));
847 env.close();
848 uint256 const chkId7{getCheckIndex(alice, env.seq(alice))};
849 env(check::create(alice, bob, USD(7)));
850 env.close();
851 uint256 const chkId6{getCheckIndex(alice, env.seq(alice))};
852 env(check::create(alice, bob, USD(6)));
853 env.close();
854
855 // bob attempts to cash a check for the amount on the check.
856 // Should fail, since alice doesn't have the funds.
857 env(check::cash(bob, chkId9, check::DeliverMin(USD(9))),
858 ter(tecPATH_PARTIAL));
859 env.close();
860
861 // bob sets a DeliverMin of 7 and gets all that alice has.
862 env(check::cash(bob, chkId9, check::DeliverMin(USD(7))));
863 verifyDeliveredAmount(env, USD(8));
864 env.require(balance(alice, USD(0)));
865 env.require(balance(bob, USD(8)));
866 BEAST_EXPECT(checksOnAccount(env, alice).size() == 3);
867 BEAST_EXPECT(checksOnAccount(env, bob).size() == 3);
868 BEAST_EXPECT(ownerCount(env, alice) == 4);
869 BEAST_EXPECT(ownerCount(env, bob) == 1);
870
871 // bob pays alice USD(7) so he can use another check.
872 env(pay(bob, alice, USD(7)));
873 env.close();
874
875 // Using DeliverMin for the SendMax value of the check (and no
876 // transfer fees) should work just like setting Amount.
877 env(check::cash(bob, chkId7, check::DeliverMin(USD(7))));
878 verifyDeliveredAmount(env, USD(7));
879 env.require(balance(alice, USD(0)));
880 env.require(balance(bob, USD(8)));
881 BEAST_EXPECT(checksOnAccount(env, alice).size() == 2);
882 BEAST_EXPECT(checksOnAccount(env, bob).size() == 2);
883 BEAST_EXPECT(ownerCount(env, alice) == 3);
884 BEAST_EXPECT(ownerCount(env, bob) == 1);
885
886 // bob pays alice USD(8) so he can use the last two checks.
887 env(pay(bob, alice, USD(8)));
888 env.close();
889
890 // alice has USD(8). If bob uses the check for USD(6) and uses a
891 // DeliverMin of 4, he should get the SendMax value of the check.
892 env(check::cash(bob, chkId6, check::DeliverMin(USD(4))));
893 verifyDeliveredAmount(env, USD(6));
894 env.require(balance(alice, USD(2)));
895 env.require(balance(bob, USD(6)));
896 BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
897 BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
898 BEAST_EXPECT(ownerCount(env, alice) == 2);
899 BEAST_EXPECT(ownerCount(env, bob) == 1);
900
901 // bob cashes the last remaining check setting a DeliverMin.
902 // of exactly alice's remaining USD.
903 env(check::cash(bob, chkId8, check::DeliverMin(USD(2))));
904 verifyDeliveredAmount(env, USD(2));
905 env.require(balance(alice, USD(0)));
906 env.require(balance(bob, USD(8)));
907 BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
908 BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
909 BEAST_EXPECT(ownerCount(env, alice) == 1);
910 BEAST_EXPECT(ownerCount(env, bob) == 1);
911 }
912 {
913 // Examine the effects of the asfRequireAuth flag.
914 Env env(*this, features);
915
916 env.fund(XRP(1000), gw, alice, bob);
917 env(fset(gw, asfRequireAuth));
918 env.close();
919 env(trust(gw, alice["USD"](100)), txflags(tfSetfAuth));
920 env(trust(alice, USD(20)));
921 env.close();
922 env(pay(gw, alice, USD(8)));
923 env.close();
924
925 // alice writes a check to bob for USD. bob can't cash it
926 // because he is not authorized to hold gw["USD"].
927 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
928 env(check::create(alice, bob, USD(7)));
929 env.close();
930
931 env(check::cash(bob, chkId, USD(7)), ter(tecNO_AUTH));
932 env.close();
933
934 // Now give bob a trustline for USD. bob still can't cash the
935 // check because he is not authorized.
936 env(trust(bob, USD(5)));
937 env.close();
938
939 env(check::cash(bob, chkId, USD(7)), ter(tecNO_AUTH));
940 env.close();
941
942 // bob gets authorization to hold gw["USD"].
943 env(trust(gw, bob["USD"](1)), txflags(tfSetfAuth));
944 env.close();
945
946 // Two possible outcomes here depending on whether cashing a
947 // check can build a trust line:
948 // o If it can't build a trust line, then since bob set his
949 // limit low, he cashes the check with a DeliverMin and hits
950 // his trust limit.
951 // o If it can build a trust line, then the check is allowed to
952 // exceed the trust limit and bob gets the full transfer.
953 env(check::cash(bob, chkId, check::DeliverMin(USD(4))));
954 STAmount const bobGot = USD(7);
955 verifyDeliveredAmount(env, bobGot);
956 env.require(balance(alice, USD(8) - bobGot));
957 env.require(balance(bob, bobGot));
958
959 BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
960 BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
961 BEAST_EXPECT(ownerCount(env, alice) == 1);
962 BEAST_EXPECT(ownerCount(env, bob) == 1);
963 }
964
965 // Use a regular key and also multisign to cash a check.
966 // featureMultiSignReserve changes the reserve on a SignerList, so
967 // check both before and after.
968 for (auto const& testFeatures :
969 {features - featureMultiSignReserve,
970 features | featureMultiSignReserve})
971 {
972 Env env{*this, testFeatures};
973
974 env.fund(XRP(1000), gw, alice, bob);
975 env.close();
976
977 // alice creates her checks ahead of time.
978 uint256 const chkId1{getCheckIndex(alice, env.seq(alice))};
979 env(check::create(alice, bob, USD(1)));
980 env.close();
981
982 uint256 const chkId2{getCheckIndex(alice, env.seq(alice))};
983 env(check::create(alice, bob, USD(2)));
984 env.close();
985
986 env(trust(alice, USD(20)));
987 env(trust(bob, USD(20)));
988 env.close();
989 env(pay(gw, alice, USD(8)));
990 env.close();
991
992 // Give bob a regular key and signers
993 Account const bobby{"bobby", KeyType::secp256k1};
994 env(regkey(bob, bobby));
995 env.close();
996
997 Account const bogie{"bogie", KeyType::secp256k1};
998 Account const demon{"demon", KeyType::ed25519};
999 env(signers(bob, 2, {{bogie, 1}, {demon, 1}}), sig(bobby));
1000 env.close();
1001
1002 // If featureMultiSignReserve is enabled then bob's signer list
1003 // has an owner count of 1, otherwise it's 4.
1004 int const signersCount = {
1005 testFeatures[featureMultiSignReserve] ? 1 : 4};
1006 BEAST_EXPECT(ownerCount(env, bob) == signersCount + 1);
1007
1008 // bob uses his regular key to cash a check.
1009 env(check::cash(bob, chkId1, (USD(1))), sig(bobby));
1010 env.close();
1011 env.require(balance(alice, USD(7)));
1012 env.require(balance(bob, USD(1)));
1013 BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
1014 BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
1015 BEAST_EXPECT(ownerCount(env, alice) == 2);
1016 BEAST_EXPECT(ownerCount(env, bob) == signersCount + 1);
1017
1018 // bob uses multisigning to cash a check.
1019 XRPAmount const baseFeeDrops{env.current()->fees().base};
1020 env(check::cash(bob, chkId2, (USD(2))),
1021 msig(bogie, demon),
1022 fee(3 * baseFeeDrops));
1023 env.close();
1024 env.require(balance(alice, USD(5)));
1025 env.require(balance(bob, USD(3)));
1026 BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
1027 BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
1028 BEAST_EXPECT(ownerCount(env, alice) == 1);
1029 BEAST_EXPECT(ownerCount(env, bob) == signersCount + 1);
1030 }
1031 }
1032
1033 void
1035 {
1036 // Look at behavior when the issuer charges a transfer fee.
1037 testcase("Cash with transfer fee");
1038
1039 using namespace test::jtx;
1040
1041 Account const gw{"gateway"};
1042 Account const alice{"alice"};
1043 Account const bob{"bob"};
1044 IOU const USD{gw["USD"]};
1045
1046 Env env{*this, features};
1047
1048 env.fund(XRP(1000), gw, alice, bob);
1049 env.close();
1050
1051 env(trust(alice, USD(1000)));
1052 env(trust(bob, USD(1000)));
1053 env.close();
1054 env(pay(gw, alice, USD(1000)));
1055 env.close();
1056
1057 // Set gw's transfer rate and see the consequences when cashing a check.
1058 env(rate(gw, 1.25));
1059 env.close();
1060
1061 // alice writes a check with a SendMax of USD(125). The most bob
1062 // can get is USD(100) because of the transfer rate.
1063 uint256 const chkId125{getCheckIndex(alice, env.seq(alice))};
1064 env(check::create(alice, bob, USD(125)));
1065 env.close();
1066
1067 // alice writes another check that won't get cashed until the transfer
1068 // rate changes so we can see the rate applies when the check is
1069 // cashed, not when it is created.
1070 uint256 const chkId120{getCheckIndex(alice, env.seq(alice))};
1071 env(check::create(alice, bob, USD(120)));
1072 env.close();
1073
1074 // bob attempts to cash the check for face value. Should fail.
1075 env(check::cash(bob, chkId125, USD(125)), ter(tecPATH_PARTIAL));
1076 env.close();
1077 env(check::cash(bob, chkId125, check::DeliverMin(USD(101))),
1078 ter(tecPATH_PARTIAL));
1079 env.close();
1080
1081 // bob decides that he'll accept anything USD(75) or up.
1082 // He gets USD(100).
1083 env(check::cash(bob, chkId125, check::DeliverMin(USD(75))));
1084 verifyDeliveredAmount(env, USD(100));
1085 env.require(balance(alice, USD(1000 - 125)));
1086 env.require(balance(bob, USD(0 + 100)));
1087 BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
1088 BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
1089
1090 // Adjust gw's rate...
1091 env(rate(gw, 1.2));
1092 env.close();
1093
1094 // bob cashes the second check for less than the face value. The new
1095 // rate applies to the actual value transferred.
1096 env(check::cash(bob, chkId120, USD(50)));
1097 env.close();
1098 env.require(balance(alice, USD(1000 - 125 - 60)));
1099 env.require(balance(bob, USD(0 + 100 + 50)));
1100 BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
1101 BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
1102 }
1103
1104 void
1106 {
1107 // Look at the eight possible cases for Quality In/Out.
1108 testcase("Cash quality");
1109
1110 using namespace test::jtx;
1111
1112 Account const gw{"gateway"};
1113 Account const alice{"alice"};
1114 Account const bob{"bob"};
1115 IOU const USD{gw["USD"]};
1116
1117 Env env{*this, features};
1118
1119 env.fund(XRP(1000), gw, alice, bob);
1120 env.close();
1121
1122 env(trust(alice, USD(1000)));
1123 env(trust(bob, USD(1000)));
1124 env.close();
1125 env(pay(gw, alice, USD(1000)));
1126 env.close();
1127
1128 //
1129 // Quality effects on transfers between two non-issuers.
1130 //
1131
1132 // Provide lambdas that return a qualityInPercent and qualityOutPercent.
1133 auto qIn = [](double percent) { return qualityInPercent(percent); };
1134 auto qOut = [](double percent) { return qualityOutPercent(percent); };
1135
1136 // There are two test lambdas: one for a Payment and one for a Check.
1137 // This shows whether a Payment and a Check behave the same.
1138 auto testNonIssuerQPay = [&env, &alice, &bob, &USD](
1139 Account const& truster,
1140 IOU const& iou,
1141 auto const& inOrOut,
1142 double pct,
1143 double amount) {
1144 // Capture bob's and alice's balances so we can test at the end.
1145 STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1146 STAmount const bobStart{env.balance(bob, USD.issue()).value()};
1147
1148 // Set the modified quality.
1149 env(trust(truster, iou(1000)), inOrOut(pct));
1150 env.close();
1151
1152 env(pay(alice, bob, USD(amount)), sendmax(USD(10)));
1153 env.close();
1154 env.require(balance(alice, aliceStart - USD(10)));
1155 env.require(balance(bob, bobStart + USD(10)));
1156
1157 // Return the quality to the unmodified state so it doesn't
1158 // interfere with upcoming tests.
1159 env(trust(truster, iou(1000)), inOrOut(0));
1160 env.close();
1161 };
1162
1163 auto testNonIssuerQCheck = [&env, &alice, &bob, &USD](
1164 Account const& truster,
1165 IOU const& iou,
1166 auto const& inOrOut,
1167 double pct,
1168 double amount) {
1169 // Capture bob's and alice's balances so we can test at the end.
1170 STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1171 STAmount const bobStart{env.balance(bob, USD.issue()).value()};
1172
1173 // Set the modified quality.
1174 env(trust(truster, iou(1000)), inOrOut(pct));
1175 env.close();
1176
1177 uint256 const chkId = getCheckIndex(alice, env.seq(alice));
1178 env(check::create(alice, bob, USD(10)));
1179 env.close();
1180
1181 env(check::cash(bob, chkId, USD(amount)));
1182 env.close();
1183 env.require(balance(alice, aliceStart - USD(10)));
1184 env.require(balance(bob, bobStart + USD(10)));
1185
1186 // Return the quality to the unmodified state so it doesn't
1187 // interfere with upcoming tests.
1188 env(trust(truster, iou(1000)), inOrOut(0));
1189 env.close();
1190 };
1191
1192 // pct amount
1193 testNonIssuerQPay(alice, gw["USD"], qIn, 50, 10);
1194 testNonIssuerQCheck(alice, gw["USD"], qIn, 50, 10);
1195
1196 // This is the only case where the Quality affects the outcome.
1197 testNonIssuerQPay(bob, gw["USD"], qIn, 50, 5);
1198 testNonIssuerQCheck(bob, gw["USD"], qIn, 50, 5);
1199
1200 testNonIssuerQPay(gw, alice["USD"], qIn, 50, 10);
1201 testNonIssuerQCheck(gw, alice["USD"], qIn, 50, 10);
1202
1203 testNonIssuerQPay(gw, bob["USD"], qIn, 50, 10);
1204 testNonIssuerQCheck(gw, bob["USD"], qIn, 50, 10);
1205
1206 testNonIssuerQPay(alice, gw["USD"], qOut, 200, 10);
1207 testNonIssuerQCheck(alice, gw["USD"], qOut, 200, 10);
1208
1209 testNonIssuerQPay(bob, gw["USD"], qOut, 200, 10);
1210 testNonIssuerQCheck(bob, gw["USD"], qOut, 200, 10);
1211
1212 testNonIssuerQPay(gw, alice["USD"], qOut, 200, 10);
1213 testNonIssuerQCheck(gw, alice["USD"], qOut, 200, 10);
1214
1215 testNonIssuerQPay(gw, bob["USD"], qOut, 200, 10);
1216 testNonIssuerQCheck(gw, bob["USD"], qOut, 200, 10);
1217
1218 //
1219 // Quality effects on transfers between an issuer and a non-issuer.
1220 //
1221
1222 // There are two test lambdas for the same reason as before.
1223 auto testIssuerQPay = [&env, &gw, &alice, &USD](
1224 Account const& truster,
1225 IOU const& iou,
1226 auto const& inOrOut,
1227 double pct,
1228 double amt1,
1229 double max1,
1230 double amt2,
1231 double max2) {
1232 // Capture alice's balance so we can test at the end. It doesn't
1233 // make any sense to look at the balance of a gateway.
1234 STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1235
1236 // Set the modified quality.
1237 env(trust(truster, iou(1000)), inOrOut(pct));
1238 env.close();
1239
1240 // alice pays gw.
1241 env(pay(alice, gw, USD(amt1)), sendmax(USD(max1)));
1242 env.close();
1243 env.require(balance(alice, aliceStart - USD(10)));
1244
1245 // gw pays alice.
1246 env(pay(gw, alice, USD(amt2)), sendmax(USD(max2)));
1247 env.close();
1248 env.require(balance(alice, aliceStart));
1249
1250 // Return the quality to the unmodified state so it doesn't
1251 // interfere with upcoming tests.
1252 env(trust(truster, iou(1000)), inOrOut(0));
1253 env.close();
1254 };
1255
1256 auto testIssuerQCheck = [&env, &gw, &alice, &USD](
1257 Account const& truster,
1258 IOU const& iou,
1259 auto const& inOrOut,
1260 double pct,
1261 double amt1,
1262 double max1,
1263 double amt2,
1264 double max2) {
1265 // Capture alice's balance so we can test at the end. It doesn't
1266 // make any sense to look at the balance of the issuer.
1267 STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1268
1269 // Set the modified quality.
1270 env(trust(truster, iou(1000)), inOrOut(pct));
1271 env.close();
1272
1273 // alice writes check to gw. gw cashes.
1274 uint256 const chkAliceId{getCheckIndex(alice, env.seq(alice))};
1275 env(check::create(alice, gw, USD(max1)));
1276 env.close();
1277
1278 env(check::cash(gw, chkAliceId, USD(amt1)));
1279 env.close();
1280 env.require(balance(alice, aliceStart - USD(10)));
1281
1282 // gw writes check to alice. alice cashes.
1283 uint256 const chkGwId{getCheckIndex(gw, env.seq(gw))};
1284 env(check::create(gw, alice, USD(max2)));
1285 env.close();
1286
1287 env(check::cash(alice, chkGwId, USD(amt2)));
1288 env.close();
1289 env.require(balance(alice, aliceStart));
1290
1291 // Return the quality to the unmodified state so it doesn't
1292 // interfere with upcoming tests.
1293 env(trust(truster, iou(1000)), inOrOut(0));
1294 env.close();
1295 };
1296
1297 // The first case is the only one where the quality affects the outcome.
1298 // pct amt1 max1 amt2 max2
1299 testIssuerQPay(alice, gw["USD"], qIn, 50, 10, 10, 5, 10);
1300 testIssuerQCheck(alice, gw["USD"], qIn, 50, 10, 10, 5, 10);
1301
1302 testIssuerQPay(gw, alice["USD"], qIn, 50, 10, 10, 10, 10);
1303 testIssuerQCheck(gw, alice["USD"], qIn, 50, 10, 10, 10, 10);
1304
1305 testIssuerQPay(alice, gw["USD"], qOut, 200, 10, 10, 10, 10);
1306 testIssuerQCheck(alice, gw["USD"], qOut, 200, 10, 10, 10, 10);
1307
1308 testIssuerQPay(gw, alice["USD"], qOut, 200, 10, 10, 10, 10);
1309 testIssuerQCheck(gw, alice["USD"], qOut, 200, 10, 10, 10, 10);
1310 }
1311
1312 void
1314 {
1315 // Explore many of the ways to fail at cashing a check.
1316 testcase("Cash invalid");
1317
1318 using namespace test::jtx;
1319
1320 Account const gw{"gateway"};
1321 Account const alice{"alice"};
1322 Account const bob{"bob"};
1323 Account const zoe{"zoe"};
1324 IOU const USD{gw["USD"]};
1325
1326 Env env(*this, features);
1327
1328 env.fund(XRP(1000), gw, alice, bob, zoe);
1329 env.close();
1330
1331 // Now set up alice's trustline.
1332 env(trust(alice, USD(20)));
1333 env.close();
1334 env(pay(gw, alice, USD(20)));
1335 env.close();
1336
1337 // Now set up bob's trustline.
1338 env(trust(bob, USD(20)));
1339 env.close();
1340
1341 // bob tries to cash a non-existent check from alice.
1342 {
1343 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
1344 env(check::cash(bob, chkId, USD(20)), ter(tecNO_ENTRY));
1345 env.close();
1346 }
1347
1348 // alice creates her checks ahead of time.
1349 uint256 const chkIdU{getCheckIndex(alice, env.seq(alice))};
1350 env(check::create(alice, bob, USD(20)));
1351 env.close();
1352
1353 uint256 const chkIdX{getCheckIndex(alice, env.seq(alice))};
1354 env(check::create(alice, bob, XRP(10)));
1355 env.close();
1356
1357 using namespace std::chrono_literals;
1358 uint256 const chkIdExp{getCheckIndex(alice, env.seq(alice))};
1359 env(check::create(alice, bob, XRP(10)), expiration(env.now() + 1s));
1360 env.close();
1361
1362 uint256 const chkIdFroz1{getCheckIndex(alice, env.seq(alice))};
1363 env(check::create(alice, bob, USD(1)));
1364 env.close();
1365
1366 uint256 const chkIdFroz2{getCheckIndex(alice, env.seq(alice))};
1367 env(check::create(alice, bob, USD(2)));
1368 env.close();
1369
1370 uint256 const chkIdFroz3{getCheckIndex(alice, env.seq(alice))};
1371 env(check::create(alice, bob, USD(3)));
1372 env.close();
1373
1374 uint256 const chkIdFroz4{getCheckIndex(alice, env.seq(alice))};
1375 env(check::create(alice, bob, USD(4)));
1376 env.close();
1377
1378 uint256 const chkIdNoDest1{getCheckIndex(alice, env.seq(alice))};
1379 env(check::create(alice, bob, USD(1)));
1380 env.close();
1381
1382 uint256 const chkIdHasDest2{getCheckIndex(alice, env.seq(alice))};
1383 env(check::create(alice, bob, USD(2)), dest_tag(7));
1384 env.close();
1385
1386 // Same set of failing cases for both IOU and XRP check cashing.
1387 auto failingCases = [&env, &gw, &alice, &bob](
1388 uint256 const& chkId, STAmount const& amount) {
1389 // Bad fee.
1390 env(check::cash(bob, chkId, amount),
1391 fee(drops(-10)),
1392 ter(temBAD_FEE));
1393 env.close();
1394
1395 // Bad flags.
1396 env(check::cash(bob, chkId, amount),
1397 txflags(tfImmediateOrCancel),
1398 ter(temINVALID_FLAG));
1399 env.close();
1400
1401 // Missing both Amount and DeliverMin.
1402 {
1403 Json::Value tx{check::cash(bob, chkId, amount)};
1404 tx.removeMember(sfAmount.jsonName);
1405 env(tx, ter(temMALFORMED));
1406 env.close();
1407 }
1408 // Both Amount and DeliverMin present.
1409 {
1410 Json::Value tx{check::cash(bob, chkId, amount)};
1411 tx[sfDeliverMin.jsonName] = amount.getJson(JsonOptions::none);
1412 env(tx, ter(temMALFORMED));
1413 env.close();
1414 }
1415
1416 // Negative or zero amount.
1417 {
1418 STAmount neg{amount};
1419 neg.negate();
1420 env(check::cash(bob, chkId, neg), ter(temBAD_AMOUNT));
1421 env.close();
1422 env(check::cash(bob, chkId, amount.zeroed()),
1423 ter(temBAD_AMOUNT));
1424 env.close();
1425 }
1426
1427 // Bad currency.
1428 if (!amount.native())
1429 {
1430 Issue const badIssue{badCurrency(), amount.getIssuer()};
1431 STAmount badAmount{amount};
1432 badAmount.setIssue(Issue{badCurrency(), amount.getIssuer()});
1433 env(check::cash(bob, chkId, badAmount), ter(temBAD_CURRENCY));
1434 env.close();
1435 }
1436
1437 // Not destination cashing check.
1438 env(check::cash(alice, chkId, amount), ter(tecNO_PERMISSION));
1439 env.close();
1440 env(check::cash(gw, chkId, amount), ter(tecNO_PERMISSION));
1441 env.close();
1442
1443 // Currency mismatch.
1444 {
1445 IOU const wrongCurrency{gw["EUR"]};
1446 STAmount badAmount{amount};
1447 badAmount.setIssue(wrongCurrency.issue());
1448 env(check::cash(bob, chkId, badAmount), ter(temMALFORMED));
1449 env.close();
1450 }
1451
1452 // Issuer mismatch.
1453 {
1454 IOU const wrongIssuer{alice["USD"]};
1455 STAmount badAmount{amount};
1456 badAmount.setIssue(wrongIssuer.issue());
1457 env(check::cash(bob, chkId, badAmount), ter(temMALFORMED));
1458 env.close();
1459 }
1460
1461 // Amount bigger than SendMax.
1462 env(check::cash(bob, chkId, amount + amount), ter(tecPATH_PARTIAL));
1463 env.close();
1464
1465 // DeliverMin bigger than SendMax.
1466 env(check::cash(bob, chkId, check::DeliverMin(amount + amount)),
1467 ter(tecPATH_PARTIAL));
1468 env.close();
1469 };
1470
1471 failingCases(chkIdX, XRP(10));
1472 failingCases(chkIdU, USD(20));
1473
1474 // Verify that those two checks really were cashable.
1475 env(check::cash(bob, chkIdU, USD(20)));
1476 env.close();
1477 env(check::cash(bob, chkIdX, check::DeliverMin(XRP(10))));
1478 verifyDeliveredAmount(env, XRP(10));
1479
1480 // Try to cash an expired check.
1481 env(check::cash(bob, chkIdExp, XRP(10)), ter(tecEXPIRED));
1482 env.close();
1483
1484 // Cancel the expired check. Anyone can cancel an expired check.
1485 env(check::cancel(zoe, chkIdExp));
1486 env.close();
1487
1488 // Can we cash a check with frozen currency?
1489 {
1490 env(pay(bob, alice, USD(20)));
1491 env.close();
1492 env.require(balance(alice, USD(20)));
1493 env.require(balance(bob, USD(0)));
1494
1495 // Global freeze
1496 env(fset(gw, asfGlobalFreeze));
1497 env.close();
1498
1499 env(check::cash(bob, chkIdFroz1, USD(1)), ter(tecPATH_PARTIAL));
1500 env.close();
1501 env(check::cash(bob, chkIdFroz1, check::DeliverMin(USD(0.5))),
1502 ter(tecPATH_PARTIAL));
1503 env.close();
1504
1505 env(fclear(gw, asfGlobalFreeze));
1506 env.close();
1507
1508 // No longer frozen. Success.
1509 env(check::cash(bob, chkIdFroz1, USD(1)));
1510 env.close();
1511 env.require(balance(alice, USD(19)));
1512 env.require(balance(bob, USD(1)));
1513
1514 // Freeze individual trustlines.
1515 env(trust(gw, alice["USD"](0), tfSetFreeze));
1516 env.close();
1517 env(check::cash(bob, chkIdFroz2, USD(2)), ter(tecPATH_PARTIAL));
1518 env.close();
1519 env(check::cash(bob, chkIdFroz2, check::DeliverMin(USD(1))),
1520 ter(tecPATH_PARTIAL));
1521 env.close();
1522
1523 // Clear that freeze. Now check cashing works.
1524 env(trust(gw, alice["USD"](0), tfClearFreeze));
1525 env.close();
1526 env(check::cash(bob, chkIdFroz2, USD(2)));
1527 env.close();
1528 env.require(balance(alice, USD(17)));
1529 env.require(balance(bob, USD(3)));
1530
1531 // Freeze bob's trustline. bob can't cash the check.
1532 env(trust(gw, bob["USD"](0), tfSetFreeze));
1533 env.close();
1534 env(check::cash(bob, chkIdFroz3, USD(3)), ter(tecFROZEN));
1535 env.close();
1536 env(check::cash(bob, chkIdFroz3, check::DeliverMin(USD(1))),
1537 ter(tecFROZEN));
1538 env.close();
1539
1540 // Clear that freeze. Now check cashing works again.
1541 env(trust(gw, bob["USD"](0), tfClearFreeze));
1542 env.close();
1543 env(check::cash(bob, chkIdFroz3, check::DeliverMin(USD(1))));
1544 verifyDeliveredAmount(env, USD(3));
1545 env.require(balance(alice, USD(14)));
1546 env.require(balance(bob, USD(6)));
1547
1548 // Set bob's freeze bit in the other direction. Check
1549 // cashing fails.
1550 env(trust(bob, USD(20), tfSetFreeze));
1551 env.close();
1552 env(check::cash(bob, chkIdFroz4, USD(4)), ter(terNO_LINE));
1553 env.close();
1554 env(check::cash(bob, chkIdFroz4, check::DeliverMin(USD(1))),
1555 ter(terNO_LINE));
1556 env.close();
1557
1558 // Clear bob's freeze bit and the check should be cashable.
1559 env(trust(bob, USD(20), tfClearFreeze));
1560 env.close();
1561 env(check::cash(bob, chkIdFroz4, USD(4)));
1562 env.close();
1563 env.require(balance(alice, USD(10)));
1564 env.require(balance(bob, USD(10)));
1565 }
1566 {
1567 // Set the RequireDest flag on bob's account (after the check
1568 // was created) then cash a check without a destination tag.
1569 env(fset(bob, asfRequireDest));
1570 env.close();
1571 env(check::cash(bob, chkIdNoDest1, USD(1)), ter(tecDST_TAG_NEEDED));
1572 env.close();
1573 env(check::cash(bob, chkIdNoDest1, check::DeliverMin(USD(0.5))),
1574 ter(tecDST_TAG_NEEDED));
1575 env.close();
1576
1577 // bob can cash a check with a destination tag.
1578 env(check::cash(bob, chkIdHasDest2, USD(2)));
1579 env.close();
1580 env.require(balance(alice, USD(8)));
1581 env.require(balance(bob, USD(12)));
1582
1583 // Clear the RequireDest flag on bob's account so he can
1584 // cash the check with no DestinationTag.
1585 env(fclear(bob, asfRequireDest));
1586 env.close();
1587 env(check::cash(bob, chkIdNoDest1, USD(1)));
1588 env.close();
1589 env.require(balance(alice, USD(7)));
1590 env.require(balance(bob, USD(13)));
1591 }
1592 }
1593
1594 void
1596 {
1597 // Explore many of the ways to cancel a check.
1598 testcase("Cancel valid");
1599
1600 using namespace test::jtx;
1601
1602 Account const gw{"gateway"};
1603 Account const alice{"alice"};
1604 Account const bob{"bob"};
1605 Account const zoe{"zoe"};
1606 IOU const USD{gw["USD"]};
1607
1608 // featureMultiSignReserve changes the reserve on a SignerList, so
1609 // check both before and after.
1610 for (auto const& testFeatures :
1611 {features - featureMultiSignReserve,
1612 features | featureMultiSignReserve})
1613 {
1614 Env env{*this, testFeatures};
1615
1616 env.fund(XRP(1000), gw, alice, bob, zoe);
1617 env.close();
1618
1619 // alice creates her checks ahead of time.
1620 // Three ordinary checks with no expiration.
1621 uint256 const chkId1{getCheckIndex(alice, env.seq(alice))};
1622 env(check::create(alice, bob, USD(10)));
1623 env.close();
1624
1625 uint256 const chkId2{getCheckIndex(alice, env.seq(alice))};
1626 env(check::create(alice, bob, XRP(10)));
1627 env.close();
1628
1629 uint256 const chkId3{getCheckIndex(alice, env.seq(alice))};
1630 env(check::create(alice, bob, USD(10)));
1631 env.close();
1632
1633 // Three checks that expire in 10 minutes.
1634 using namespace std::chrono_literals;
1635 uint256 const chkIdNotExp1{getCheckIndex(alice, env.seq(alice))};
1636 env(check::create(alice, bob, XRP(10)),
1637 expiration(env.now() + 600s));
1638 env.close();
1639
1640 uint256 const chkIdNotExp2{getCheckIndex(alice, env.seq(alice))};
1641 env(check::create(alice, bob, USD(10)),
1642 expiration(env.now() + 600s));
1643 env.close();
1644
1645 uint256 const chkIdNotExp3{getCheckIndex(alice, env.seq(alice))};
1646 env(check::create(alice, bob, XRP(10)),
1647 expiration(env.now() + 600s));
1648 env.close();
1649
1650 // Three checks that expire in one second.
1651 uint256 const chkIdExp1{getCheckIndex(alice, env.seq(alice))};
1652 env(check::create(alice, bob, USD(10)), expiration(env.now() + 1s));
1653 env.close();
1654
1655 uint256 const chkIdExp2{getCheckIndex(alice, env.seq(alice))};
1656 env(check::create(alice, bob, XRP(10)), expiration(env.now() + 1s));
1657 env.close();
1658
1659 uint256 const chkIdExp3{getCheckIndex(alice, env.seq(alice))};
1660 env(check::create(alice, bob, USD(10)), expiration(env.now() + 1s));
1661 env.close();
1662
1663 // Two checks to cancel using a regular key and using multisigning.
1664 uint256 const chkIdReg{getCheckIndex(alice, env.seq(alice))};
1665 env(check::create(alice, bob, USD(10)));
1666 env.close();
1667
1668 uint256 const chkIdMSig{getCheckIndex(alice, env.seq(alice))};
1669 env(check::create(alice, bob, XRP(10)));
1670 env.close();
1671 BEAST_EXPECT(checksOnAccount(env, alice).size() == 11);
1672 BEAST_EXPECT(ownerCount(env, alice) == 11);
1673
1674 // Creator, destination, and an outsider cancel the checks.
1675 env(check::cancel(alice, chkId1));
1676 env.close();
1677 BEAST_EXPECT(checksOnAccount(env, alice).size() == 10);
1678 BEAST_EXPECT(ownerCount(env, alice) == 10);
1679
1680 env(check::cancel(bob, chkId2));
1681 env.close();
1682 BEAST_EXPECT(checksOnAccount(env, alice).size() == 9);
1683 BEAST_EXPECT(ownerCount(env, alice) == 9);
1684
1685 env(check::cancel(zoe, chkId3), ter(tecNO_PERMISSION));
1686 env.close();
1687 BEAST_EXPECT(checksOnAccount(env, alice).size() == 9);
1688 BEAST_EXPECT(ownerCount(env, alice) == 9);
1689
1690 // Creator, destination, and an outsider cancel unexpired checks.
1691 env(check::cancel(alice, chkIdNotExp1));
1692 env.close();
1693 BEAST_EXPECT(checksOnAccount(env, alice).size() == 8);
1694 BEAST_EXPECT(ownerCount(env, alice) == 8);
1695
1696 env(check::cancel(bob, chkIdNotExp2));
1697 env.close();
1698 BEAST_EXPECT(checksOnAccount(env, alice).size() == 7);
1699 BEAST_EXPECT(ownerCount(env, alice) == 7);
1700
1701 env(check::cancel(zoe, chkIdNotExp3), ter(tecNO_PERMISSION));
1702 env.close();
1703 BEAST_EXPECT(checksOnAccount(env, alice).size() == 7);
1704 BEAST_EXPECT(ownerCount(env, alice) == 7);
1705
1706 // Creator, destination, and an outsider cancel expired checks.
1707 env(check::cancel(alice, chkIdExp1));
1708 env.close();
1709 BEAST_EXPECT(checksOnAccount(env, alice).size() == 6);
1710 BEAST_EXPECT(ownerCount(env, alice) == 6);
1711
1712 env(check::cancel(bob, chkIdExp2));
1713 env.close();
1714 BEAST_EXPECT(checksOnAccount(env, alice).size() == 5);
1715 BEAST_EXPECT(ownerCount(env, alice) == 5);
1716
1717 env(check::cancel(zoe, chkIdExp3));
1718 env.close();
1719 BEAST_EXPECT(checksOnAccount(env, alice).size() == 4);
1720 BEAST_EXPECT(ownerCount(env, alice) == 4);
1721
1722 // Use a regular key and also multisign to cancel checks.
1723 Account const alie{"alie", KeyType::ed25519};
1724 env(regkey(alice, alie));
1725 env.close();
1726
1727 Account const bogie{"bogie", KeyType::secp256k1};
1728 Account const demon{"demon", KeyType::ed25519};
1729 env(signers(alice, 2, {{bogie, 1}, {demon, 1}}), sig(alie));
1730 env.close();
1731
1732 // If featureMultiSignReserve is enabled then alices's signer list
1733 // has an owner count of 1, otherwise it's 4.
1734 int const signersCount{
1735 testFeatures[featureMultiSignReserve] ? 1 : 4};
1736
1737 // alice uses her regular key to cancel a check.
1738 env(check::cancel(alice, chkIdReg), sig(alie));
1739 env.close();
1740 BEAST_EXPECT(checksOnAccount(env, alice).size() == 3);
1741 BEAST_EXPECT(ownerCount(env, alice) == signersCount + 3);
1742
1743 // alice uses multisigning to cancel a check.
1744 XRPAmount const baseFeeDrops{env.current()->fees().base};
1745 env(check::cancel(alice, chkIdMSig),
1746 msig(bogie, demon),
1747 fee(3 * baseFeeDrops));
1748 env.close();
1749 BEAST_EXPECT(checksOnAccount(env, alice).size() == 2);
1750 BEAST_EXPECT(ownerCount(env, alice) == signersCount + 2);
1751
1752 // Creator and destination cancel the remaining unexpired checks.
1753 env(check::cancel(alice, chkId3), sig(alice));
1754 env.close();
1755 BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
1756 BEAST_EXPECT(ownerCount(env, alice) == signersCount + 1);
1757
1758 env(check::cancel(bob, chkIdNotExp3));
1759 env.close();
1760 BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
1761 BEAST_EXPECT(ownerCount(env, alice) == signersCount + 0);
1762 }
1763 }
1764
1765 void
1767 {
1768 // Explore many of the ways to fail at canceling a check.
1769 testcase("Cancel invalid");
1770
1771 using namespace test::jtx;
1772
1773 Account const alice{"alice"};
1774 Account const bob{"bob"};
1775
1776 Env env{*this, features};
1777
1778 env.fund(XRP(1000), alice, bob);
1779 env.close();
1780
1781 // Bad fee.
1782 env(check::cancel(bob, getCheckIndex(alice, env.seq(alice))),
1783 fee(drops(-10)),
1784 ter(temBAD_FEE));
1785 env.close();
1786
1787 // Bad flags.
1788 env(check::cancel(bob, getCheckIndex(alice, env.seq(alice))),
1789 txflags(tfImmediateOrCancel),
1790 ter(temINVALID_FLAG));
1791 env.close();
1792
1793 // Non-existent check.
1794 env(check::cancel(bob, getCheckIndex(alice, env.seq(alice))),
1795 ter(tecNO_ENTRY));
1796 env.close();
1797 }
1798
1799 void
1801 {
1802 testcase("DeliveredAmount For CheckCash Txn");
1803
1804 using namespace test::jtx;
1805 Account const alice{"alice"};
1806 Account const bob{"bob"};
1807
1808 Env env{*this, features};
1809
1810 env.fund(XRP(1000), alice, bob);
1811 env.close();
1812
1813 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
1814 env(check::create(alice, bob, XRP(200)));
1815 env.close();
1816
1817 env(check::cash(bob, chkId, check::DeliverMin(XRP(100))));
1818
1819 // Get the hash for the most recent transaction.
1820 std::string const txHash{
1821 env.tx()->getJson(JsonOptions::none)[jss::hash].asString()};
1822
1823 env.close();
1824 Json::Value const meta = env.rpc("tx", txHash)[jss::result][jss::meta];
1825
1826 // DeliveredAmount and delivered_amount are present.
1827 BEAST_EXPECT(meta.isMember(sfDeliveredAmount.jsonName));
1828 BEAST_EXPECT(meta.isMember(jss::delivered_amount));
1829 }
1830
1831 void
1833 {
1834 testcase("With Tickets");
1835
1836 using namespace test::jtx;
1837
1838 Account const gw{"gw"};
1839 Account const alice{"alice"};
1840 Account const bob{"bob"};
1841 IOU const USD{gw["USD"]};
1842
1843 Env env{*this, features};
1844 env.fund(XRP(1000), gw, alice, bob);
1845 env.close();
1846
1847 // alice and bob grab enough tickets for all of the following
1848 // transactions. Note that once the tickets are acquired alice's
1849 // and bob's account sequence numbers should not advance.
1850 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
1851 env(ticket::create(alice, 10));
1852 std::uint32_t const aliceSeq{env.seq(alice)};
1853
1854 std::uint32_t bobTicketSeq{env.seq(bob) + 1};
1855 env(ticket::create(bob, 10));
1856 std::uint32_t const bobSeq{env.seq(bob)};
1857
1858 env.close();
1859 env.require(owners(alice, 10));
1860 env.require(owners(bob, 10));
1861
1862 // alice gets enough USD to write a few checks.
1863 env(trust(alice, USD(1000)), ticket::use(aliceTicketSeq++));
1864 env(trust(bob, USD(1000)), ticket::use(bobTicketSeq++));
1865 env.close();
1866 env.require(owners(alice, 10));
1867 env.require(owners(bob, 10));
1868
1869 env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1870 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1871
1872 env.require(tickets(bob, env.seq(bob) - bobTicketSeq));
1873 BEAST_EXPECT(env.seq(bob) == bobSeq);
1874
1875 env(pay(gw, alice, USD(900)));
1876 env.close();
1877
1878 // alice creates four checks; two XRP, two IOU. Bob will cash
1879 // one of each and cancel one of each.
1880 uint256 const chkIdXrp1{getCheckIndex(alice, aliceTicketSeq)};
1881 env(check::create(alice, bob, XRP(200)), ticket::use(aliceTicketSeq++));
1882
1883 uint256 const chkIdXrp2{getCheckIndex(alice, aliceTicketSeq)};
1884 env(check::create(alice, bob, XRP(300)), ticket::use(aliceTicketSeq++));
1885
1886 uint256 const chkIdUsd1{getCheckIndex(alice, aliceTicketSeq)};
1887 env(check::create(alice, bob, USD(200)), ticket::use(aliceTicketSeq++));
1888
1889 uint256 const chkIdUsd2{getCheckIndex(alice, aliceTicketSeq)};
1890 env(check::create(alice, bob, USD(300)), ticket::use(aliceTicketSeq++));
1891
1892 env.close();
1893 // Alice used four tickets but created four checks.
1894 env.require(owners(alice, 10));
1895 env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1896 BEAST_EXPECT(checksOnAccount(env, alice).size() == 4);
1897 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1898
1899 env.require(owners(bob, 10));
1900 BEAST_EXPECT(env.seq(bob) == bobSeq);
1901
1902 // Bob cancels two of alice's checks.
1903 env(check::cancel(bob, chkIdXrp1), ticket::use(bobTicketSeq++));
1904 env(check::cancel(bob, chkIdUsd2), ticket::use(bobTicketSeq++));
1905 env.close();
1906
1907 env.require(owners(alice, 8));
1908 env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1909 BEAST_EXPECT(checksOnAccount(env, alice).size() == 2);
1910 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1911
1912 env.require(owners(bob, 8));
1913 BEAST_EXPECT(env.seq(bob) == bobSeq);
1914
1915 // Bob cashes alice's two remaining checks.
1916 env(check::cash(bob, chkIdXrp2, XRP(300)), ticket::use(bobTicketSeq++));
1917 env(check::cash(bob, chkIdUsd1, USD(200)), ticket::use(bobTicketSeq++));
1918 env.close();
1919
1920 env.require(owners(alice, 6));
1921 env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1922 BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
1923 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1924 env.require(balance(alice, USD(700)));
1925
1926 env.require(owners(bob, 6));
1927 BEAST_EXPECT(env.seq(bob) == bobSeq);
1928 env.require(balance(bob, USD(200)));
1929 }
1930
1931 void
1933 {
1934 // Explore automatic trust line creation when a check is cashed.
1935 //
1936
1937 testcase("Trust Line Creation");
1938
1939 using namespace test::jtx;
1940
1941 Env env{*this, features};
1942
1943 // An account that independently tracks its owner count.
1944 struct AccountOwns
1945 {
1947 Env const& env;
1948 Account const acct;
1949 std::size_t owners;
1950
1951 void
1952 verifyOwners(std::uint32_t line) const
1953 {
1954 suite.expect(
1955 ownerCount(env, acct) == owners,
1956 "Owner count mismatch",
1957 __FILE__,
1958 line);
1959 }
1960
1961 // Operators to make using the class more convenient.
1962 operator Account const() const
1963 {
1964 return acct;
1965 }
1966
1967 operator ripple::AccountID() const
1968 {
1969 return acct.id();
1970 }
1971
1972 IOU
1973 operator[](std::string const& s) const
1974 {
1975 return acct[s];
1976 }
1977 };
1978
1979 AccountOwns alice{*this, env, "alice", 0};
1980 AccountOwns bob{*this, env, "bob", 0};
1981
1982 // Fund with noripple so the accounts do not have any flags set.
1983 env.fund(XRP(5000), noripple(alice, bob));
1984 env.close();
1985
1986 // Automatic trust line creation should fail if the check destination
1987 // can't afford the reserve for the trust line.
1988 {
1989 AccountOwns gw1{*this, env, "gw1", 0};
1990
1991 // Fund gw1 with noripple (even though that's atypical for a
1992 // gateway) so it does not have any flags set. We'll set flags
1993 // on gw1 later.
1994 env.fund(XRP(5000), noripple(gw1));
1995 env.close();
1996
1997 IOU const CK8 = gw1["CK8"];
1998 gw1.verifyOwners(__LINE__);
1999
2000 Account const yui{"yui"};
2001
2002 // Note the reserve in unit tests is 200 XRP, not 20. So here
2003 // we're just barely giving yui enough XRP to meet the
2004 // account reserve.
2005 env.fund(XRP(200), yui);
2006 env.close();
2007
2008 uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))};
2009 env(check::create(gw1, yui, CK8(99)));
2010 env.close();
2011
2012 env(check::cash(yui, chkId, CK8(99)),
2014 env.close();
2015 alice.verifyOwners(__LINE__);
2016
2017 // Give yui enough XRP to meet the trust line's reserve. Cashing
2018 // the check succeeds and creates the trust line.
2019 env(pay(env.master, yui, XRP(51)));
2020 env.close();
2021 env(check::cash(yui, chkId, CK8(99)));
2022 verifyDeliveredAmount(env, CK8(99));
2023 env.close();
2024 BEAST_EXPECT(ownerCount(env, yui) == 1);
2025
2026 // The automatic trust line does not take a reserve from gw1.
2027 // Since gw1's check was consumed it has no owners.
2028 gw1.verifyOwners(__LINE__);
2029 }
2030
2031 // We'll be looking at the effects of various account root flags.
2032
2033 // Automatically create trust lines using
2034 // o Offers and
2035 // o Check cashing
2036 // Compare the resulting trust lines and expect them to be very similar.
2037
2038 // Lambda that compares two trust lines created by
2039 // o Offer crossing and
2040 // o Check cashing
2041 // between the same two accounts but with two different currencies.
2042 // The lambda expects the two trust lines to be largely similar.
2043 auto cmpTrustLines = [this, &env](
2044 Account const& acct1,
2045 Account const& acct2,
2046 IOU const& offerIou,
2047 IOU const& checkIou) {
2048 auto const offerLine =
2049 env.le(keylet::line(acct1, acct2, offerIou.currency));
2050 auto const checkLine =
2051 env.le(keylet::line(acct1, acct2, checkIou.currency));
2052 if (offerLine == nullptr || checkLine == nullptr)
2053 {
2054 BEAST_EXPECT(offerLine == nullptr && checkLine == nullptr);
2055 return;
2056 }
2057
2058 {
2059 // Compare the contents of required fields.
2060 BEAST_EXPECT(offerLine->at(sfFlags) == checkLine->at(sfFlags));
2061
2062 // Lambda that compares the contents of required STAmounts
2063 // without comparing the currency.
2064 auto cmpReqAmount =
2065 [this, offerLine, checkLine](SF_AMOUNT const& sfield) {
2066 STAmount const offerAmount = offerLine->at(sfield);
2067 STAmount const checkAmount = checkLine->at(sfield);
2068
2069 // Neither STAmount should be native.
2070 if (!BEAST_EXPECT(
2071 !offerAmount.native() && !checkAmount.native()))
2072 return;
2073
2074 BEAST_EXPECT(
2075 offerAmount.issue().account ==
2076 checkAmount.issue().account);
2077 BEAST_EXPECT(
2078 offerAmount.negative() == checkAmount.negative());
2079 BEAST_EXPECT(
2080 offerAmount.mantissa() == checkAmount.mantissa());
2081 BEAST_EXPECT(
2082 offerAmount.exponent() == checkAmount.exponent());
2083 };
2084 cmpReqAmount(sfBalance);
2085 cmpReqAmount(sfLowLimit);
2086 cmpReqAmount(sfHighLimit);
2087 }
2088 {
2089 // Lambda that compares the contents of optional fields.
2090 auto cmpOptField =
2091 [this, offerLine, checkLine](auto const& sfield) {
2092 // Expect both fields to either be present or absent.
2093 if (!BEAST_EXPECT(
2094 offerLine->isFieldPresent(sfield) ==
2095 checkLine->isFieldPresent(sfield)))
2096 return;
2097
2098 // If both fields are absent then there's nothing
2099 // further to check.
2100 if (!offerLine->isFieldPresent(sfield))
2101 return;
2102
2103 // Both optional fields are present so we can compare
2104 // them.
2105 BEAST_EXPECT(
2106 offerLine->at(sfield) == checkLine->at(sfield));
2107 };
2108 cmpOptField(sfLowNode);
2109 cmpOptField(sfLowQualityIn);
2110 cmpOptField(sfLowQualityOut);
2111
2112 cmpOptField(sfHighNode);
2113 cmpOptField(sfHighQualityIn);
2114 cmpOptField(sfHighQualityOut);
2115 }
2116 };
2117
2118 //----------- No account root flags, check written by issuer -----------
2119 {
2120 // No account root flags on any participant.
2121 // Automatic trust line from issuer to destination.
2122 AccountOwns gw1{*this, env, "gw1", 0};
2123
2124 BEAST_EXPECT((*env.le(gw1))[sfFlags] == 0);
2125 BEAST_EXPECT((*env.le(alice))[sfFlags] == 0);
2126 BEAST_EXPECT((*env.le(bob))[sfFlags] == 0);
2127
2128 // Use offers to automatically create the trust line.
2129 IOU const OF1 = gw1["OF1"];
2130 env(offer(gw1, XRP(98), OF1(98)));
2131 env.close();
2132 BEAST_EXPECT(
2133 env.le(keylet::line(gw1, alice, OF1.currency)) == nullptr);
2134 env(offer(alice, OF1(98), XRP(98)));
2135 ++alice.owners;
2136 env.close();
2137
2138 // Both offers should be consumed.
2139 // Since gw1's offer was consumed and the trust line was not
2140 // created by gw1, gw1's owner count should be 0.
2141 gw1.verifyOwners(__LINE__);
2142
2143 // alice's automatically created trust line bumps her owner count.
2144 alice.verifyOwners(__LINE__);
2145
2146 // Use check cashing to automatically create the trust line.
2147 IOU const CK1 = gw1["CK1"];
2148 uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))};
2149 env(check::create(gw1, alice, CK1(98)));
2150 env.close();
2151 BEAST_EXPECT(
2152 env.le(keylet::line(gw1, alice, CK1.currency)) == nullptr);
2153 env(check::cash(alice, chkId, CK1(98)));
2154 ++alice.owners;
2155 verifyDeliveredAmount(env, CK1(98));
2156 env.close();
2157
2158 // gw1's check should be consumed.
2159 // Since gw1's check was consumed and the trust line was not
2160 // created by gw1, gw1's owner count should be 0.
2161 gw1.verifyOwners(__LINE__);
2162
2163 // alice's automatically created trust line bumps her owner count.
2164 alice.verifyOwners(__LINE__);
2165
2166 cmpTrustLines(gw1, alice, OF1, CK1);
2167 }
2168 //--------- No account root flags, check written by non-issuer ---------
2169 {
2170 // No account root flags on any participant.
2171 // Automatic trust line from non-issuer to non-issuer.
2172
2173 // Use offers to automatically create the trust line.
2174 // Transfer of assets using offers does not require rippling.
2175 // So bob's offer is successfully crossed which creates the
2176 // trust line.
2177 AccountOwns gw1{*this, env, "gw1", 0};
2178 IOU const OF1 = gw1["OF1"];
2179 env(offer(alice, XRP(97), OF1(97)));
2180 env.close();
2181 BEAST_EXPECT(
2182 env.le(keylet::line(alice, bob, OF1.currency)) == nullptr);
2183 env(offer(bob, OF1(97), XRP(97)));
2184 ++bob.owners;
2185 env.close();
2186
2187 // Both offers should be consumed.
2188 env.require(balance(alice, OF1(1)));
2189 env.require(balance(bob, OF1(97)));
2190
2191 // bob now has an owner count of 1 due to the new trust line.
2192 gw1.verifyOwners(__LINE__);
2193 alice.verifyOwners(__LINE__);
2194 bob.verifyOwners(__LINE__);
2195
2196 // Use check cashing to automatically create the trust line.
2197 //
2198 // However cashing a check (unlike crossing offers) requires
2199 // rippling through the currency's issuer. Since gw1 does not
2200 // have rippling enabled the check cash fails and bob does not
2201 // have a trust line created.
2202 IOU const CK1 = gw1["CK1"];
2203 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
2204 env(check::create(alice, bob, CK1(97)));
2205 env.close();
2206 BEAST_EXPECT(
2207 env.le(keylet::line(alice, bob, CK1.currency)) == nullptr);
2208 env(check::cash(bob, chkId, CK1(97)), ter(terNO_RIPPLE));
2209 env.close();
2210
2211 BEAST_EXPECT(
2212 env.le(keylet::line(gw1, bob, OF1.currency)) != nullptr);
2213 BEAST_EXPECT(
2214 env.le(keylet::line(gw1, bob, CK1.currency)) == nullptr);
2215
2216 // Delete alice's check since it is no longer needed.
2217 env(check::cancel(alice, chkId));
2218 env.close();
2219
2220 // No one's owner count should have changed.
2221 gw1.verifyOwners(__LINE__);
2222 alice.verifyOwners(__LINE__);
2223 bob.verifyOwners(__LINE__);
2224 }
2225
2226 //------------- lsfDefaultRipple, check written by issuer --------------
2227 {
2228 // gw1 enables rippling.
2229 // Automatic trust line from issuer to non-issuer should still work.
2230 AccountOwns gw1{*this, env, "gw1", 0};
2231 env(fset(gw1, asfDefaultRipple));
2232 env.close();
2233
2234 // Use offers to automatically create the trust line.
2235 IOU const OF2 = gw1["OF2"];
2236 env(offer(gw1, XRP(96), OF2(96)));
2237 env.close();
2238 BEAST_EXPECT(
2239 env.le(keylet::line(gw1, alice, OF2.currency)) == nullptr);
2240 env(offer(alice, OF2(96), XRP(96)));
2241 ++alice.owners;
2242 env.close();
2243
2244 // Both offers should be consumed.
2245 // Since gw1's offer was consumed and the trust line was not
2246 // created by gw1, gw1's owner count should still be 0.
2247 gw1.verifyOwners(__LINE__);
2248
2249 // alice's automatically created trust line bumps her owner count.
2250 alice.verifyOwners(__LINE__);
2251
2252 // Use check cashing to automatically create the trust line.
2253 IOU const CK2 = gw1["CK2"];
2254 uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))};
2255 env(check::create(gw1, alice, CK2(96)));
2256 env.close();
2257 BEAST_EXPECT(
2258 env.le(keylet::line(gw1, alice, CK2.currency)) == nullptr);
2259 env(check::cash(alice, chkId, CK2(96)));
2260 ++alice.owners;
2261 verifyDeliveredAmount(env, CK2(96));
2262 env.close();
2263
2264 // gw1's check should be consumed.
2265 // Since gw1's check was consumed and the trust line was not
2266 // created by gw1, gw1's owner count should still be 0.
2267 gw1.verifyOwners(__LINE__);
2268
2269 // alice's automatically created trust line bumps her owner count.
2270 alice.verifyOwners(__LINE__);
2271
2272 cmpTrustLines(gw1, alice, OF2, CK2);
2273 }
2274 //----------- lsfDefaultRipple, check written by non-issuer ------------
2275 {
2276 // gw1 enabled rippling, so automatic trust line from non-issuer
2277 // to non-issuer should work.
2278
2279 // Use offers to automatically create the trust line.
2280 AccountOwns gw1{*this, env, "gw1", 0};
2281 IOU const OF2 = gw1["OF2"];
2282 env(offer(alice, XRP(95), OF2(95)));
2283 env.close();
2284 BEAST_EXPECT(
2285 env.le(keylet::line(alice, bob, OF2.currency)) == nullptr);
2286 env(offer(bob, OF2(95), XRP(95)));
2287 ++bob.owners;
2288 env.close();
2289
2290 // bob's owner count should increase due to the new trust line.
2291 gw1.verifyOwners(__LINE__);
2292 alice.verifyOwners(__LINE__);
2293 bob.verifyOwners(__LINE__);
2294
2295 // Use check cashing to automatically create the trust line.
2296 IOU const CK2 = gw1["CK2"];
2297 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
2298 env(check::create(alice, bob, CK2(95)));
2299 env.close();
2300 BEAST_EXPECT(
2301 env.le(keylet::line(alice, bob, CK2.currency)) == nullptr);
2302 env(check::cash(bob, chkId, CK2(95)));
2303 ++bob.owners;
2304 verifyDeliveredAmount(env, CK2(95));
2305 env.close();
2306
2307 // bob's owner count should increase due to the new trust line.
2308 gw1.verifyOwners(__LINE__);
2309 alice.verifyOwners(__LINE__);
2310 bob.verifyOwners(__LINE__);
2311
2312 cmpTrustLines(alice, bob, OF2, CK2);
2313 }
2314
2315 //-------------- lsfDepositAuth, check written by issuer ---------------
2316 {
2317 // Both offers and checks ignore the lsfDepositAuth flag, since
2318 // the destination signs the transaction that delivers their funds.
2319 // So setting lsfDepositAuth on all the participants should not
2320 // change any outcomes.
2321 //
2322 // Automatic trust line from issuer to non-issuer should still work.
2323 AccountOwns gw1{*this, env, "gw1", 0};
2324 env(fset(gw1, asfDepositAuth));
2325 env(fset(alice, asfDepositAuth));
2326 env(fset(bob, asfDepositAuth));
2327 env.close();
2328
2329 // Use offers to automatically create the trust line.
2330 IOU const OF3 = gw1["OF3"];
2331 env(offer(gw1, XRP(94), OF3(94)));
2332 env.close();
2333 BEAST_EXPECT(
2334 env.le(keylet::line(gw1, alice, OF3.currency)) == nullptr);
2335 env(offer(alice, OF3(94), XRP(94)));
2336 ++alice.owners;
2337 env.close();
2338
2339 // Both offers should be consumed.
2340 // Since gw1's offer was consumed and the trust line was not
2341 // created by gw1, gw1's owner count should still be 0.
2342 gw1.verifyOwners(__LINE__);
2343
2344 // alice's automatically created trust line bumps her owner count.
2345 alice.verifyOwners(__LINE__);
2346
2347 // Use check cashing to automatically create the trust line.
2348 IOU const CK3 = gw1["CK3"];
2349 uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))};
2350 env(check::create(gw1, alice, CK3(94)));
2351 env.close();
2352 BEAST_EXPECT(
2353 env.le(keylet::line(gw1, alice, CK3.currency)) == nullptr);
2354 env(check::cash(alice, chkId, CK3(94)));
2355 ++alice.owners;
2356 verifyDeliveredAmount(env, CK3(94));
2357 env.close();
2358
2359 // gw1's check should be consumed.
2360 // Since gw1's check was consumed and the trust line was not
2361 // created by gw1, gw1's owner count should still be 0.
2362 gw1.verifyOwners(__LINE__);
2363
2364 // alice's automatically created trust line bumps her owner count.
2365 alice.verifyOwners(__LINE__);
2366
2367 cmpTrustLines(gw1, alice, OF3, CK3);
2368 }
2369 //------------ lsfDepositAuth, check written by non-issuer -------------
2370 {
2371 // The presence of the lsfDepositAuth flag should not affect
2372 // automatic trust line creation.
2373
2374 // Use offers to automatically create the trust line.
2375 AccountOwns gw1{*this, env, "gw1", 0};
2376 IOU const OF3 = gw1["OF3"];
2377 env(offer(alice, XRP(93), OF3(93)));
2378 env.close();
2379 BEAST_EXPECT(
2380 env.le(keylet::line(alice, bob, OF3.currency)) == nullptr);
2381 env(offer(bob, OF3(93), XRP(93)));
2382 ++bob.owners;
2383 env.close();
2384
2385 // bob's owner count should increase due to the new trust line.
2386 gw1.verifyOwners(__LINE__);
2387 alice.verifyOwners(__LINE__);
2388 bob.verifyOwners(__LINE__);
2389
2390 // Use check cashing to automatically create the trust line.
2391 IOU const CK3 = gw1["CK3"];
2392 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
2393 env(check::create(alice, bob, CK3(93)));
2394 env.close();
2395 BEAST_EXPECT(
2396 env.le(keylet::line(alice, bob, CK3.currency)) == nullptr);
2397 env(check::cash(bob, chkId, CK3(93)));
2398 ++bob.owners;
2399 verifyDeliveredAmount(env, CK3(93));
2400 env.close();
2401
2402 // bob's owner count should increase due to the new trust line.
2403 gw1.verifyOwners(__LINE__);
2404 alice.verifyOwners(__LINE__);
2405 bob.verifyOwners(__LINE__);
2406
2407 cmpTrustLines(alice, bob, OF3, CK3);
2408 }
2409
2410 //-------------- lsfGlobalFreeze, check written by issuer --------------
2411 {
2412 // Set lsfGlobalFreeze on gw1. That should stop any automatic
2413 // trust lines from being created.
2414 AccountOwns gw1{*this, env, "gw1", 0};
2415 env(fset(gw1, asfGlobalFreeze));
2416 env.close();
2417
2418 // Use offers to automatically create the trust line.
2419 IOU const OF4 = gw1["OF4"];
2420 env(offer(gw1, XRP(92), OF4(92)), ter(tecFROZEN));
2421 env.close();
2422 BEAST_EXPECT(
2423 env.le(keylet::line(gw1, alice, OF4.currency)) == nullptr);
2424 env(offer(alice, OF4(92), XRP(92)), ter(tecFROZEN));
2425 env.close();
2426
2427 // No one's owner count should have changed.
2428 gw1.verifyOwners(__LINE__);
2429 alice.verifyOwners(__LINE__);
2430 bob.verifyOwners(__LINE__);
2431
2432 // Use check cashing to automatically create the trust line.
2433 IOU const CK4 = gw1["CK4"];
2434 uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))};
2435 env(check::create(gw1, alice, CK4(92)), ter(tecFROZEN));
2436 env.close();
2437 BEAST_EXPECT(
2438 env.le(keylet::line(gw1, alice, CK4.currency)) == nullptr);
2439 env(check::cash(alice, chkId, CK4(92)), ter(tecNO_ENTRY));
2440 env.close();
2441
2442 // No one's owner count should have changed.
2443 gw1.verifyOwners(__LINE__);
2444 alice.verifyOwners(__LINE__);
2445 bob.verifyOwners(__LINE__);
2446
2447 // Because gw1 has set lsfGlobalFreeze, neither trust line
2448 // is created.
2449 BEAST_EXPECT(
2450 env.le(keylet::line(gw1, alice, OF4.currency)) == nullptr);
2451 BEAST_EXPECT(
2452 env.le(keylet::line(gw1, alice, CK4.currency)) == nullptr);
2453 }
2454 //------------ lsfGlobalFreeze, check written by non-issuer ------------
2455 {
2456 // Since gw1 has the lsfGlobalFreeze flag set, there should be
2457 // no automatic trust line creation between non-issuers.
2458
2459 // Use offers to automatically create the trust line.
2460 AccountOwns gw1{*this, env, "gw1", 0};
2461 IOU const OF4 = gw1["OF4"];
2462 env(offer(alice, XRP(91), OF4(91)), ter(tecFROZEN));
2463 env.close();
2464 BEAST_EXPECT(
2465 env.le(keylet::line(alice, bob, OF4.currency)) == nullptr);
2466 env(offer(bob, OF4(91), XRP(91)), ter(tecFROZEN));
2467 env.close();
2468
2469 // No one's owner count should have changed.
2470 gw1.verifyOwners(__LINE__);
2471 alice.verifyOwners(__LINE__);
2472 bob.verifyOwners(__LINE__);
2473
2474 // Use check cashing to automatically create the trust line.
2475 IOU const CK4 = gw1["CK4"];
2476 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
2477 env(check::create(alice, bob, CK4(91)), ter(tecFROZEN));
2478 env.close();
2479 BEAST_EXPECT(
2480 env.le(keylet::line(alice, bob, CK4.currency)) == nullptr);
2481 env(check::cash(bob, chkId, CK4(91)), ter(tecNO_ENTRY));
2482 env.close();
2483
2484 // No one's owner count should have changed.
2485 gw1.verifyOwners(__LINE__);
2486 alice.verifyOwners(__LINE__);
2487 bob.verifyOwners(__LINE__);
2488
2489 // Because gw1 has set lsfGlobalFreeze, neither trust line
2490 // is created.
2491 BEAST_EXPECT(
2492 env.le(keylet::line(gw1, bob, OF4.currency)) == nullptr);
2493 BEAST_EXPECT(
2494 env.le(keylet::line(gw1, bob, CK4.currency)) == nullptr);
2495 }
2496
2497 //-------------- lsfRequireAuth, check written by issuer ---------------
2498
2499 // We want to test the lsfRequireAuth flag, but we can't set that
2500 // flag on an account that already has trust lines. So we'll fund
2501 // a new gateway and use that.
2502 {
2503 AccountOwns gw2{*this, env, "gw2", 0};
2504 env.fund(XRP(5000), gw2);
2505 env.close();
2506
2507 // Set lsfRequireAuth on gw2. That should stop any automatic
2508 // trust lines from being created.
2509 env(fset(gw2, asfRequireAuth));
2510 env.close();
2511
2512 // Use offers to automatically create the trust line.
2513 IOU const OF5 = gw2["OF5"];
2514 std::uint32_t gw2OfferSeq = {env.seq(gw2)};
2515 env(offer(gw2, XRP(92), OF5(92)));
2516 ++gw2.owners;
2517 env.close();
2518 BEAST_EXPECT(
2519 env.le(keylet::line(gw2, alice, OF5.currency)) == nullptr);
2520 env(offer(alice, OF5(92), XRP(92)), ter(tecNO_LINE));
2521 env.close();
2522
2523 // gw2 should still own the offer, but no one else's owner
2524 // count should have changed.
2525 gw2.verifyOwners(__LINE__);
2526 alice.verifyOwners(__LINE__);
2527 bob.verifyOwners(__LINE__);
2528
2529 // Since we don't need it any more, remove gw2's offer.
2530 env(offer_cancel(gw2, gw2OfferSeq));
2531 --gw2.owners;
2532 env.close();
2533 gw2.verifyOwners(__LINE__);
2534
2535 // Use check cashing to automatically create the trust line.
2536 IOU const CK5 = gw2["CK5"];
2537 uint256 const chkId{getCheckIndex(gw2, env.seq(gw2))};
2538 env(check::create(gw2, alice, CK5(92)));
2539 ++gw2.owners;
2540 env.close();
2541 BEAST_EXPECT(
2542 env.le(keylet::line(gw2, alice, CK5.currency)) == nullptr);
2543 env(check::cash(alice, chkId, CK5(92)), ter(tecNO_AUTH));
2544 env.close();
2545
2546 // gw2 should still own the check, but no one else's owner
2547 // count should have changed.
2548 gw2.verifyOwners(__LINE__);
2549 alice.verifyOwners(__LINE__);
2550 bob.verifyOwners(__LINE__);
2551
2552 // Because gw2 has set lsfRequireAuth, neither trust line
2553 // is created.
2554 BEAST_EXPECT(
2555 env.le(keylet::line(gw2, alice, OF5.currency)) == nullptr);
2556 BEAST_EXPECT(
2557 env.le(keylet::line(gw2, alice, CK5.currency)) == nullptr);
2558
2559 // Since we don't need it any more, remove gw2's check.
2560 env(check::cancel(gw2, chkId));
2561 --gw2.owners;
2562 env.close();
2563 gw2.verifyOwners(__LINE__);
2564 }
2565 //------------ lsfRequireAuth, check written by non-issuer -------------
2566 {
2567 // Since gw2 has the lsfRequireAuth flag set, there should be
2568 // no automatic trust line creation between non-issuers.
2569
2570 // Use offers to automatically create the trust line.
2571 AccountOwns gw2{*this, env, "gw2", 0};
2572 IOU const OF5 = gw2["OF5"];
2573 env(offer(alice, XRP(91), OF5(91)), ter(tecUNFUNDED_OFFER));
2574 env.close();
2575 env(offer(bob, OF5(91), XRP(91)), ter(tecNO_LINE));
2576 BEAST_EXPECT(
2577 env.le(keylet::line(gw2, bob, OF5.currency)) == nullptr);
2578 env.close();
2579
2580 gw2.verifyOwners(__LINE__);
2581 alice.verifyOwners(__LINE__);
2582 bob.verifyOwners(__LINE__);
2583
2584 // Use check cashing to automatically create the trust line.
2585 IOU const CK5 = gw2["CK5"];
2586 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
2587 env(check::create(alice, bob, CK5(91)));
2588 env.close();
2589 BEAST_EXPECT(
2590 env.le(keylet::line(alice, bob, CK5.currency)) == nullptr);
2591 env(check::cash(bob, chkId, CK5(91)), ter(tecPATH_PARTIAL));
2592 env.close();
2593
2594 // Delete alice's check since it is no longer needed.
2595 env(check::cancel(alice, chkId));
2596 env.close();
2597
2598 // No one's owner count should have changed.
2599 gw2.verifyOwners(__LINE__);
2600 alice.verifyOwners(__LINE__);
2601 bob.verifyOwners(__LINE__);
2602
2603 // Because gw2 has set lsfRequireAuth, neither trust line
2604 // is created.
2605 BEAST_EXPECT(
2606 env.le(keylet::line(gw2, bob, OF5.currency)) == nullptr);
2607 BEAST_EXPECT(
2608 env.le(keylet::line(gw2, bob, CK5.currency)) == nullptr);
2609 }
2610 }
2611
2612 void
2614 {
2615 testEnabled(features);
2616 testCreateValid(features);
2618 testCreateInvalid(features);
2619 testCashXRP(features);
2620 testCashIOU(features);
2621 testCashXferFee(features);
2622 testCashQuality(features);
2623 testCashInvalid(features);
2624 testCancelValid(features);
2625 testCancelInvalid(features);
2627 testWithTickets(features);
2628 }
2629
2630public:
2631 void
2632 run() override
2633 {
2634 using namespace test::jtx;
2635 auto const sa = testable_amendments();
2637 testWithFeats(sa);
2639 }
2640};
2641
2642BEAST_DEFINE_TESTSUITE(Check, app, ripple);
2643
2644} // namespace ripple
Represents a JSON value.
Definition json_value.h:131
Value removeMember(char const *key)
Remove and return the named member.
bool isMember(char const *key) const
Return true if the object has a member named key.
A testsuite class.
Definition suite.h:52
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:152
bool expect(Condition const &shouldBeTrue)
Evaluate a test condition.
Definition suite.h:226
void testCancelInvalid(FeatureBitset features)
void testCashXferFee(FeatureBitset features)
void testCashIOU(FeatureBitset features)
void testWithTickets(FeatureBitset features)
void testDeliveredAmountForCheckCashTxn(FeatureBitset features)
static std::vector< std::shared_ptr< SLE const > > checksOnAccount(test::jtx::Env &env, test::jtx::Account account)
void testCashXRP(FeatureBitset features)
void verifyDeliveredAmount(test::jtx::Env &env, STAmount const &amount)
void testEnabled(FeatureBitset features)
void testCashQuality(FeatureBitset features)
static uint256 getCheckIndex(AccountID const &account, std::uint32_t uSequence)
void testTrustLineCreation(FeatureBitset features)
FeatureBitset const disallowIncoming
void testCreateDisallowIncoming(FeatureBitset features)
void testCreateInvalid(FeatureBitset features)
void testCancelValid(FeatureBitset features)
void testCreateValid(FeatureBitset features)
void run() override
Runs the suite.
void testCashInvalid(FeatureBitset features)
void testWithFeats(FeatureBitset features)
A currency issued by an account.
Definition Issue.h:14
AccountID account
Definition Issue.h:17
Json::Value getJson(JsonOptions=JsonOptions::none) const override
Definition STAmount.cpp:753
int exponent() const noexcept
Definition STAmount.h:433
void setIssue(Asset const &asset)
Set the Issue for this amount.
Definition STAmount.cpp:429
bool negative() const noexcept
Definition STAmount.h:452
Issue const & issue() const
Definition STAmount.h:477
std::uint64_t mantissa() const noexcept
Definition STAmount.h:458
bool native() const noexcept
Definition STAmount.h:439
Immutable cryptographic account descriptor.
Definition Account.h:20
A transaction testing environment.
Definition Env.h:102
std::shared_ptr< STTx const > tx() const
Return the tx data for the last JTx.
Definition Env.cpp:507
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition Env.h:312
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:103
Json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition Env.h:772
Set DestinationTag on a JTx.
std::uint32_t const tag_
dest_tag(std::uint32_t tag)
void operator()(Env &, JTx &jt) const
Set Expiration on a JTx.
void operator()(Env &, JTx &jt) const
expiration(NetClock::time_point const &expiry)
std::uint32_t const expry_
Set SourceTag on a JTx.
void operator()(Env &, JTx &jt) const
std::uint32_t const tag_
source_tag(std::uint32_t tag)
Keylet line(AccountID const &id0, AccountID const &id1, Currency const &currency) noexcept
The index of a trust line for a given currency.
Definition Indexes.cpp:225
Keylet check(AccountID const &id, std::uint32_t seq) noexcept
A Check.
Definition Indexes.cpp:317
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:29
constexpr std::uint32_t asfGlobalFreeze
Definition TxFlags.h:64
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
constexpr std::uint32_t asfDepositAuth
Definition TxFlags.h:66
constexpr std::uint32_t asfRequireDest
Definition TxFlags.h:58
@ lsfDisallowIncomingCheck
constexpr std::uint32_t tfImmediateOrCancel
Definition TxFlags.h:80
void forEachItem(ReadView const &view, Keylet const &root, std::function< void(std::shared_ptr< SLE const > const &)> const &f)
Iterate all items in the given directory.
Definition View.cpp:637
constexpr std::uint32_t tfSetfAuth
Definition TxFlags.h:96
constexpr std::uint32_t asfDefaultRipple
Definition TxFlags.h:65
constexpr std::uint32_t asfDisallowIncomingCheck
Definition TxFlags.h:72
constexpr std::uint32_t tfClearFreeze
Definition TxFlags.h:100
@ tecNO_ENTRY
Definition TER.h:288
@ tecNO_DST
Definition TER.h:272
@ tecNO_LINE_INSUF_RESERVE
Definition TER.h:274
@ tecUNFUNDED_OFFER
Definition TER.h:266
@ tecFROZEN
Definition TER.h:285
@ tecNO_PERMISSION
Definition TER.h:287
@ tecDST_TAG_NEEDED
Definition TER.h:291
@ tecPATH_PARTIAL
Definition TER.h:264
@ tecNO_LINE
Definition TER.h:283
@ tecPATH_DRY
Definition TER.h:276
@ tecINSUFFICIENT_RESERVE
Definition TER.h:289
@ tecEXPIRED
Definition TER.h:296
@ tecNO_AUTH
Definition TER.h:282
@ tesSUCCESS
Definition TER.h:226
constexpr std::uint32_t asfRequireAuth
Definition TxFlags.h:59
@ terNO_RIPPLE
Definition TER.h:205
@ terNO_LINE
Definition TER.h:200
constexpr std::uint32_t tfSetFreeze
Definition TxFlags.h:99
@ temBAD_AMOUNT
Definition TER.h:70
@ temREDUNDANT
Definition TER.h:93
@ temBAD_FEE
Definition TER.h:73
@ temBAD_CURRENCY
Definition TER.h:71
@ temMALFORMED
Definition TER.h:68
@ temBAD_EXPIRATION
Definition TER.h:72
@ temINVALID_FLAG
Definition TER.h:92
@ temDISABLED
Definition TER.h:95
uint256 key
Definition Keylet.h:21
A field with a type known at compile time.
Definition SField.h:301
Execution context for applying a JSON transaction.
Definition JTx.h:26