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 {
967 Env env{*this, features};
968 env.fund(XRP(1000), gw, alice, bob);
969 env.close();
970
971 // alice creates her checks ahead of time.
972 uint256 const chkId1{getCheckIndex(alice, env.seq(alice))};
973 env(check::create(alice, bob, USD(1)));
974 env.close();
975
976 uint256 const chkId2{getCheckIndex(alice, env.seq(alice))};
977 env(check::create(alice, bob, USD(2)));
978 env.close();
979
980 env(trust(alice, USD(20)));
981 env(trust(bob, USD(20)));
982 env.close();
983 env(pay(gw, alice, USD(8)));
984 env.close();
985
986 // Give bob a regular key and signers
987 Account const bobby{"bobby", KeyType::secp256k1};
988 env(regkey(bob, bobby));
989 env.close();
990
991 Account const bogie{"bogie", KeyType::secp256k1};
992 Account const demon{"demon", KeyType::ed25519};
993 env(signers(bob, 2, {{bogie, 1}, {demon, 1}}), sig(bobby));
994 env.close();
995
996 BEAST_EXPECT(ownerCount(env, bob) == 2);
997
998 // bob uses his regular key to cash a check.
999 env(check::cash(bob, chkId1, (USD(1))), sig(bobby));
1000 env.close();
1001 env.require(balance(alice, USD(7)));
1002 env.require(balance(bob, USD(1)));
1003 BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
1004 BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
1005 BEAST_EXPECT(ownerCount(env, alice) == 2);
1006 BEAST_EXPECT(ownerCount(env, bob) == 2);
1007
1008 // bob uses multisigning to cash a check.
1009 XRPAmount const baseFeeDrops{env.current()->fees().base};
1010 env(check::cash(bob, chkId2, (USD(2))),
1011 msig(bogie, demon),
1012 fee(3 * baseFeeDrops));
1013 env.close();
1014 env.require(balance(alice, USD(5)));
1015 env.require(balance(bob, USD(3)));
1016 BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
1017 BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
1018 BEAST_EXPECT(ownerCount(env, alice) == 1);
1019 BEAST_EXPECT(ownerCount(env, bob) == 2);
1020 }
1021 }
1022
1023 void
1025 {
1026 // Look at behavior when the issuer charges a transfer fee.
1027 testcase("Cash with transfer fee");
1028
1029 using namespace test::jtx;
1030
1031 Account const gw{"gateway"};
1032 Account const alice{"alice"};
1033 Account const bob{"bob"};
1034 IOU const USD{gw["USD"]};
1035
1036 Env env{*this, features};
1037
1038 env.fund(XRP(1000), gw, alice, bob);
1039 env.close();
1040
1041 env(trust(alice, USD(1000)));
1042 env(trust(bob, USD(1000)));
1043 env.close();
1044 env(pay(gw, alice, USD(1000)));
1045 env.close();
1046
1047 // Set gw's transfer rate and see the consequences when cashing a check.
1048 env(rate(gw, 1.25));
1049 env.close();
1050
1051 // alice writes a check with a SendMax of USD(125). The most bob
1052 // can get is USD(100) because of the transfer rate.
1053 uint256 const chkId125{getCheckIndex(alice, env.seq(alice))};
1054 env(check::create(alice, bob, USD(125)));
1055 env.close();
1056
1057 // alice writes another check that won't get cashed until the transfer
1058 // rate changes so we can see the rate applies when the check is
1059 // cashed, not when it is created.
1060 uint256 const chkId120{getCheckIndex(alice, env.seq(alice))};
1061 env(check::create(alice, bob, USD(120)));
1062 env.close();
1063
1064 // bob attempts to cash the check for face value. Should fail.
1065 env(check::cash(bob, chkId125, USD(125)), ter(tecPATH_PARTIAL));
1066 env.close();
1067 env(check::cash(bob, chkId125, check::DeliverMin(USD(101))),
1068 ter(tecPATH_PARTIAL));
1069 env.close();
1070
1071 // bob decides that he'll accept anything USD(75) or up.
1072 // He gets USD(100).
1073 env(check::cash(bob, chkId125, check::DeliverMin(USD(75))));
1074 verifyDeliveredAmount(env, USD(100));
1075 env.require(balance(alice, USD(1000 - 125)));
1076 env.require(balance(bob, USD(0 + 100)));
1077 BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
1078 BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
1079
1080 // Adjust gw's rate...
1081 env(rate(gw, 1.2));
1082 env.close();
1083
1084 // bob cashes the second check for less than the face value. The new
1085 // rate applies to the actual value transferred.
1086 env(check::cash(bob, chkId120, USD(50)));
1087 env.close();
1088 env.require(balance(alice, USD(1000 - 125 - 60)));
1089 env.require(balance(bob, USD(0 + 100 + 50)));
1090 BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
1091 BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
1092 }
1093
1094 void
1096 {
1097 // Look at the eight possible cases for Quality In/Out.
1098 testcase("Cash quality");
1099
1100 using namespace test::jtx;
1101
1102 Account const gw{"gateway"};
1103 Account const alice{"alice"};
1104 Account const bob{"bob"};
1105 IOU const USD{gw["USD"]};
1106
1107 Env env{*this, features};
1108
1109 env.fund(XRP(1000), gw, alice, bob);
1110 env.close();
1111
1112 env(trust(alice, USD(1000)));
1113 env(trust(bob, USD(1000)));
1114 env.close();
1115 env(pay(gw, alice, USD(1000)));
1116 env.close();
1117
1118 //
1119 // Quality effects on transfers between two non-issuers.
1120 //
1121
1122 // Provide lambdas that return a qualityInPercent and qualityOutPercent.
1123 auto qIn = [](double percent) { return qualityInPercent(percent); };
1124 auto qOut = [](double percent) { return qualityOutPercent(percent); };
1125
1126 // There are two test lambdas: one for a Payment and one for a Check.
1127 // This shows whether a Payment and a Check behave the same.
1128 auto testNonIssuerQPay = [&env, &alice, &bob, &USD](
1129 Account const& truster,
1130 IOU const& iou,
1131 auto const& inOrOut,
1132 double pct,
1133 double amount) {
1134 // Capture bob's and alice's balances so we can test at the end.
1135 STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1136 STAmount const bobStart{env.balance(bob, USD.issue()).value()};
1137
1138 // Set the modified quality.
1139 env(trust(truster, iou(1000)), inOrOut(pct));
1140 env.close();
1141
1142 env(pay(alice, bob, USD(amount)), sendmax(USD(10)));
1143 env.close();
1144 env.require(balance(alice, aliceStart - USD(10)));
1145 env.require(balance(bob, bobStart + USD(10)));
1146
1147 // Return the quality to the unmodified state so it doesn't
1148 // interfere with upcoming tests.
1149 env(trust(truster, iou(1000)), inOrOut(0));
1150 env.close();
1151 };
1152
1153 auto testNonIssuerQCheck = [&env, &alice, &bob, &USD](
1154 Account const& truster,
1155 IOU const& iou,
1156 auto const& inOrOut,
1157 double pct,
1158 double amount) {
1159 // Capture bob's and alice's balances so we can test at the end.
1160 STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1161 STAmount const bobStart{env.balance(bob, USD.issue()).value()};
1162
1163 // Set the modified quality.
1164 env(trust(truster, iou(1000)), inOrOut(pct));
1165 env.close();
1166
1167 uint256 const chkId = getCheckIndex(alice, env.seq(alice));
1168 env(check::create(alice, bob, USD(10)));
1169 env.close();
1170
1171 env(check::cash(bob, chkId, USD(amount)));
1172 env.close();
1173 env.require(balance(alice, aliceStart - USD(10)));
1174 env.require(balance(bob, bobStart + USD(10)));
1175
1176 // Return the quality to the unmodified state so it doesn't
1177 // interfere with upcoming tests.
1178 env(trust(truster, iou(1000)), inOrOut(0));
1179 env.close();
1180 };
1181
1182 // pct amount
1183 testNonIssuerQPay(alice, gw["USD"], qIn, 50, 10);
1184 testNonIssuerQCheck(alice, gw["USD"], qIn, 50, 10);
1185
1186 // This is the only case where the Quality affects the outcome.
1187 testNonIssuerQPay(bob, gw["USD"], qIn, 50, 5);
1188 testNonIssuerQCheck(bob, gw["USD"], qIn, 50, 5);
1189
1190 testNonIssuerQPay(gw, alice["USD"], qIn, 50, 10);
1191 testNonIssuerQCheck(gw, alice["USD"], qIn, 50, 10);
1192
1193 testNonIssuerQPay(gw, bob["USD"], qIn, 50, 10);
1194 testNonIssuerQCheck(gw, bob["USD"], qIn, 50, 10);
1195
1196 testNonIssuerQPay(alice, gw["USD"], qOut, 200, 10);
1197 testNonIssuerQCheck(alice, gw["USD"], qOut, 200, 10);
1198
1199 testNonIssuerQPay(bob, gw["USD"], qOut, 200, 10);
1200 testNonIssuerQCheck(bob, gw["USD"], qOut, 200, 10);
1201
1202 testNonIssuerQPay(gw, alice["USD"], qOut, 200, 10);
1203 testNonIssuerQCheck(gw, alice["USD"], qOut, 200, 10);
1204
1205 testNonIssuerQPay(gw, bob["USD"], qOut, 200, 10);
1206 testNonIssuerQCheck(gw, bob["USD"], qOut, 200, 10);
1207
1208 //
1209 // Quality effects on transfers between an issuer and a non-issuer.
1210 //
1211
1212 // There are two test lambdas for the same reason as before.
1213 auto testIssuerQPay = [&env, &gw, &alice, &USD](
1214 Account const& truster,
1215 IOU const& iou,
1216 auto const& inOrOut,
1217 double pct,
1218 double amt1,
1219 double max1,
1220 double amt2,
1221 double max2) {
1222 // Capture alice's balance so we can test at the end. It doesn't
1223 // make any sense to look at the balance of a gateway.
1224 STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1225
1226 // Set the modified quality.
1227 env(trust(truster, iou(1000)), inOrOut(pct));
1228 env.close();
1229
1230 // alice pays gw.
1231 env(pay(alice, gw, USD(amt1)), sendmax(USD(max1)));
1232 env.close();
1233 env.require(balance(alice, aliceStart - USD(10)));
1234
1235 // gw pays alice.
1236 env(pay(gw, alice, USD(amt2)), sendmax(USD(max2)));
1237 env.close();
1238 env.require(balance(alice, aliceStart));
1239
1240 // Return the quality to the unmodified state so it doesn't
1241 // interfere with upcoming tests.
1242 env(trust(truster, iou(1000)), inOrOut(0));
1243 env.close();
1244 };
1245
1246 auto testIssuerQCheck = [&env, &gw, &alice, &USD](
1247 Account const& truster,
1248 IOU const& iou,
1249 auto const& inOrOut,
1250 double pct,
1251 double amt1,
1252 double max1,
1253 double amt2,
1254 double max2) {
1255 // Capture alice's balance so we can test at the end. It doesn't
1256 // make any sense to look at the balance of the issuer.
1257 STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1258
1259 // Set the modified quality.
1260 env(trust(truster, iou(1000)), inOrOut(pct));
1261 env.close();
1262
1263 // alice writes check to gw. gw cashes.
1264 uint256 const chkAliceId{getCheckIndex(alice, env.seq(alice))};
1265 env(check::create(alice, gw, USD(max1)));
1266 env.close();
1267
1268 env(check::cash(gw, chkAliceId, USD(amt1)));
1269 env.close();
1270 env.require(balance(alice, aliceStart - USD(10)));
1271
1272 // gw writes check to alice. alice cashes.
1273 uint256 const chkGwId{getCheckIndex(gw, env.seq(gw))};
1274 env(check::create(gw, alice, USD(max2)));
1275 env.close();
1276
1277 env(check::cash(alice, chkGwId, USD(amt2)));
1278 env.close();
1279 env.require(balance(alice, aliceStart));
1280
1281 // Return the quality to the unmodified state so it doesn't
1282 // interfere with upcoming tests.
1283 env(trust(truster, iou(1000)), inOrOut(0));
1284 env.close();
1285 };
1286
1287 // The first case is the only one where the quality affects the outcome.
1288 // pct amt1 max1 amt2 max2
1289 testIssuerQPay(alice, gw["USD"], qIn, 50, 10, 10, 5, 10);
1290 testIssuerQCheck(alice, gw["USD"], qIn, 50, 10, 10, 5, 10);
1291
1292 testIssuerQPay(gw, alice["USD"], qIn, 50, 10, 10, 10, 10);
1293 testIssuerQCheck(gw, alice["USD"], qIn, 50, 10, 10, 10, 10);
1294
1295 testIssuerQPay(alice, gw["USD"], qOut, 200, 10, 10, 10, 10);
1296 testIssuerQCheck(alice, gw["USD"], qOut, 200, 10, 10, 10, 10);
1297
1298 testIssuerQPay(gw, alice["USD"], qOut, 200, 10, 10, 10, 10);
1299 testIssuerQCheck(gw, alice["USD"], qOut, 200, 10, 10, 10, 10);
1300 }
1301
1302 void
1304 {
1305 // Explore many of the ways to fail at cashing a check.
1306 testcase("Cash invalid");
1307
1308 using namespace test::jtx;
1309
1310 Account const gw{"gateway"};
1311 Account const alice{"alice"};
1312 Account const bob{"bob"};
1313 Account const zoe{"zoe"};
1314 IOU const USD{gw["USD"]};
1315
1316 Env env(*this, features);
1317
1318 env.fund(XRP(1000), gw, alice, bob, zoe);
1319 env.close();
1320
1321 // Now set up alice's trustline.
1322 env(trust(alice, USD(20)));
1323 env.close();
1324 env(pay(gw, alice, USD(20)));
1325 env.close();
1326
1327 // Now set up bob's trustline.
1328 env(trust(bob, USD(20)));
1329 env.close();
1330
1331 // bob tries to cash a non-existent check from alice.
1332 {
1333 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
1334 env(check::cash(bob, chkId, USD(20)), ter(tecNO_ENTRY));
1335 env.close();
1336 }
1337
1338 // alice creates her checks ahead of time.
1339 uint256 const chkIdU{getCheckIndex(alice, env.seq(alice))};
1340 env(check::create(alice, bob, USD(20)));
1341 env.close();
1342
1343 uint256 const chkIdX{getCheckIndex(alice, env.seq(alice))};
1344 env(check::create(alice, bob, XRP(10)));
1345 env.close();
1346
1347 using namespace std::chrono_literals;
1348 uint256 const chkIdExp{getCheckIndex(alice, env.seq(alice))};
1349 env(check::create(alice, bob, XRP(10)), expiration(env.now() + 1s));
1350 env.close();
1351
1352 uint256 const chkIdFroz1{getCheckIndex(alice, env.seq(alice))};
1353 env(check::create(alice, bob, USD(1)));
1354 env.close();
1355
1356 uint256 const chkIdFroz2{getCheckIndex(alice, env.seq(alice))};
1357 env(check::create(alice, bob, USD(2)));
1358 env.close();
1359
1360 uint256 const chkIdFroz3{getCheckIndex(alice, env.seq(alice))};
1361 env(check::create(alice, bob, USD(3)));
1362 env.close();
1363
1364 uint256 const chkIdFroz4{getCheckIndex(alice, env.seq(alice))};
1365 env(check::create(alice, bob, USD(4)));
1366 env.close();
1367
1368 uint256 const chkIdNoDest1{getCheckIndex(alice, env.seq(alice))};
1369 env(check::create(alice, bob, USD(1)));
1370 env.close();
1371
1372 uint256 const chkIdHasDest2{getCheckIndex(alice, env.seq(alice))};
1373 env(check::create(alice, bob, USD(2)), dest_tag(7));
1374 env.close();
1375
1376 // Same set of failing cases for both IOU and XRP check cashing.
1377 auto failingCases = [&env, &gw, &alice, &bob](
1378 uint256 const& chkId, STAmount const& amount) {
1379 // Bad fee.
1380 env(check::cash(bob, chkId, amount),
1381 fee(drops(-10)),
1382 ter(temBAD_FEE));
1383 env.close();
1384
1385 // Bad flags.
1386 env(check::cash(bob, chkId, amount),
1387 txflags(tfImmediateOrCancel),
1388 ter(temINVALID_FLAG));
1389 env.close();
1390
1391 // Missing both Amount and DeliverMin.
1392 {
1393 Json::Value tx{check::cash(bob, chkId, amount)};
1394 tx.removeMember(sfAmount.jsonName);
1395 env(tx, ter(temMALFORMED));
1396 env.close();
1397 }
1398 // Both Amount and DeliverMin present.
1399 {
1400 Json::Value tx{check::cash(bob, chkId, amount)};
1401 tx[sfDeliverMin.jsonName] = amount.getJson(JsonOptions::none);
1402 env(tx, ter(temMALFORMED));
1403 env.close();
1404 }
1405
1406 // Negative or zero amount.
1407 {
1408 STAmount neg{amount};
1409 neg.negate();
1410 env(check::cash(bob, chkId, neg), ter(temBAD_AMOUNT));
1411 env.close();
1412 env(check::cash(bob, chkId, amount.zeroed()),
1413 ter(temBAD_AMOUNT));
1414 env.close();
1415 }
1416
1417 // Bad currency.
1418 if (!amount.native())
1419 {
1420 Issue const badIssue{badCurrency(), amount.getIssuer()};
1421 STAmount badAmount{amount};
1422 badAmount.setIssue(Issue{badCurrency(), amount.getIssuer()});
1423 env(check::cash(bob, chkId, badAmount), ter(temBAD_CURRENCY));
1424 env.close();
1425 }
1426
1427 // Not destination cashing check.
1428 env(check::cash(alice, chkId, amount), ter(tecNO_PERMISSION));
1429 env.close();
1430 env(check::cash(gw, chkId, amount), ter(tecNO_PERMISSION));
1431 env.close();
1432
1433 // Currency mismatch.
1434 {
1435 IOU const wrongCurrency{gw["EUR"]};
1436 STAmount badAmount{amount};
1437 badAmount.setIssue(wrongCurrency.issue());
1438 env(check::cash(bob, chkId, badAmount), ter(temMALFORMED));
1439 env.close();
1440 }
1441
1442 // Issuer mismatch.
1443 {
1444 IOU const wrongIssuer{alice["USD"]};
1445 STAmount badAmount{amount};
1446 badAmount.setIssue(wrongIssuer.issue());
1447 env(check::cash(bob, chkId, badAmount), ter(temMALFORMED));
1448 env.close();
1449 }
1450
1451 // Amount bigger than SendMax.
1452 env(check::cash(bob, chkId, amount + amount), ter(tecPATH_PARTIAL));
1453 env.close();
1454
1455 // DeliverMin bigger than SendMax.
1456 env(check::cash(bob, chkId, check::DeliverMin(amount + amount)),
1457 ter(tecPATH_PARTIAL));
1458 env.close();
1459 };
1460
1461 failingCases(chkIdX, XRP(10));
1462 failingCases(chkIdU, USD(20));
1463
1464 // Verify that those two checks really were cashable.
1465 env(check::cash(bob, chkIdU, USD(20)));
1466 env.close();
1467 env(check::cash(bob, chkIdX, check::DeliverMin(XRP(10))));
1468 verifyDeliveredAmount(env, XRP(10));
1469
1470 // Try to cash an expired check.
1471 env(check::cash(bob, chkIdExp, XRP(10)), ter(tecEXPIRED));
1472 env.close();
1473
1474 // Cancel the expired check. Anyone can cancel an expired check.
1475 env(check::cancel(zoe, chkIdExp));
1476 env.close();
1477
1478 // Can we cash a check with frozen currency?
1479 {
1480 env(pay(bob, alice, USD(20)));
1481 env.close();
1482 env.require(balance(alice, USD(20)));
1483 env.require(balance(bob, USD(0)));
1484
1485 // Global freeze
1486 env(fset(gw, asfGlobalFreeze));
1487 env.close();
1488
1489 env(check::cash(bob, chkIdFroz1, USD(1)), ter(tecPATH_PARTIAL));
1490 env.close();
1491 env(check::cash(bob, chkIdFroz1, check::DeliverMin(USD(0.5))),
1492 ter(tecPATH_PARTIAL));
1493 env.close();
1494
1495 env(fclear(gw, asfGlobalFreeze));
1496 env.close();
1497
1498 // No longer frozen. Success.
1499 env(check::cash(bob, chkIdFroz1, USD(1)));
1500 env.close();
1501 env.require(balance(alice, USD(19)));
1502 env.require(balance(bob, USD(1)));
1503
1504 // Freeze individual trustlines.
1505 env(trust(gw, alice["USD"](0), tfSetFreeze));
1506 env.close();
1507 env(check::cash(bob, chkIdFroz2, USD(2)), ter(tecPATH_PARTIAL));
1508 env.close();
1509 env(check::cash(bob, chkIdFroz2, check::DeliverMin(USD(1))),
1510 ter(tecPATH_PARTIAL));
1511 env.close();
1512
1513 // Clear that freeze. Now check cashing works.
1514 env(trust(gw, alice["USD"](0), tfClearFreeze));
1515 env.close();
1516 env(check::cash(bob, chkIdFroz2, USD(2)));
1517 env.close();
1518 env.require(balance(alice, USD(17)));
1519 env.require(balance(bob, USD(3)));
1520
1521 // Freeze bob's trustline. bob can't cash the check.
1522 env(trust(gw, bob["USD"](0), tfSetFreeze));
1523 env.close();
1524 env(check::cash(bob, chkIdFroz3, USD(3)), ter(tecFROZEN));
1525 env.close();
1526 env(check::cash(bob, chkIdFroz3, check::DeliverMin(USD(1))),
1527 ter(tecFROZEN));
1528 env.close();
1529
1530 // Clear that freeze. Now check cashing works again.
1531 env(trust(gw, bob["USD"](0), tfClearFreeze));
1532 env.close();
1533 env(check::cash(bob, chkIdFroz3, check::DeliverMin(USD(1))));
1534 verifyDeliveredAmount(env, USD(3));
1535 env.require(balance(alice, USD(14)));
1536 env.require(balance(bob, USD(6)));
1537
1538 // Set bob's freeze bit in the other direction. Check
1539 // cashing fails.
1540 env(trust(bob, USD(20), tfSetFreeze));
1541 env.close();
1542 env(check::cash(bob, chkIdFroz4, USD(4)), ter(terNO_LINE));
1543 env.close();
1544 env(check::cash(bob, chkIdFroz4, check::DeliverMin(USD(1))),
1545 ter(terNO_LINE));
1546 env.close();
1547
1548 // Clear bob's freeze bit and the check should be cashable.
1549 env(trust(bob, USD(20), tfClearFreeze));
1550 env.close();
1551 env(check::cash(bob, chkIdFroz4, USD(4)));
1552 env.close();
1553 env.require(balance(alice, USD(10)));
1554 env.require(balance(bob, USD(10)));
1555 }
1556 {
1557 // Set the RequireDest flag on bob's account (after the check
1558 // was created) then cash a check without a destination tag.
1559 env(fset(bob, asfRequireDest));
1560 env.close();
1561 env(check::cash(bob, chkIdNoDest1, USD(1)), ter(tecDST_TAG_NEEDED));
1562 env.close();
1563 env(check::cash(bob, chkIdNoDest1, check::DeliverMin(USD(0.5))),
1564 ter(tecDST_TAG_NEEDED));
1565 env.close();
1566
1567 // bob can cash a check with a destination tag.
1568 env(check::cash(bob, chkIdHasDest2, USD(2)));
1569 env.close();
1570 env.require(balance(alice, USD(8)));
1571 env.require(balance(bob, USD(12)));
1572
1573 // Clear the RequireDest flag on bob's account so he can
1574 // cash the check with no DestinationTag.
1575 env(fclear(bob, asfRequireDest));
1576 env.close();
1577 env(check::cash(bob, chkIdNoDest1, USD(1)));
1578 env.close();
1579 env.require(balance(alice, USD(7)));
1580 env.require(balance(bob, USD(13)));
1581 }
1582 }
1583
1584 void
1586 {
1587 // Explore many of the ways to cancel a check.
1588 testcase("Cancel valid");
1589
1590 using namespace test::jtx;
1591
1592 Account const gw{"gateway"};
1593 Account const alice{"alice"};
1594 Account const bob{"bob"};
1595 Account const zoe{"zoe"};
1596 IOU const USD{gw["USD"]};
1597
1598 {
1599 Env env{*this, features};
1600
1601 env.fund(XRP(1000), gw, alice, bob, zoe);
1602 env.close();
1603
1604 // alice creates her checks ahead of time.
1605 // Three ordinary checks with no expiration.
1606 uint256 const chkId1{getCheckIndex(alice, env.seq(alice))};
1607 env(check::create(alice, bob, USD(10)));
1608 env.close();
1609
1610 uint256 const chkId2{getCheckIndex(alice, env.seq(alice))};
1611 env(check::create(alice, bob, XRP(10)));
1612 env.close();
1613
1614 uint256 const chkId3{getCheckIndex(alice, env.seq(alice))};
1615 env(check::create(alice, bob, USD(10)));
1616 env.close();
1617
1618 // Three checks that expire in 10 minutes.
1619 using namespace std::chrono_literals;
1620 uint256 const chkIdNotExp1{getCheckIndex(alice, env.seq(alice))};
1621 env(check::create(alice, bob, XRP(10)),
1622 expiration(env.now() + 600s));
1623 env.close();
1624
1625 uint256 const chkIdNotExp2{getCheckIndex(alice, env.seq(alice))};
1626 env(check::create(alice, bob, USD(10)),
1627 expiration(env.now() + 600s));
1628 env.close();
1629
1630 uint256 const chkIdNotExp3{getCheckIndex(alice, env.seq(alice))};
1631 env(check::create(alice, bob, XRP(10)),
1632 expiration(env.now() + 600s));
1633 env.close();
1634
1635 // Three checks that expire in one second.
1636 uint256 const chkIdExp1{getCheckIndex(alice, env.seq(alice))};
1637 env(check::create(alice, bob, USD(10)), expiration(env.now() + 1s));
1638 env.close();
1639
1640 uint256 const chkIdExp2{getCheckIndex(alice, env.seq(alice))};
1641 env(check::create(alice, bob, XRP(10)), expiration(env.now() + 1s));
1642 env.close();
1643
1644 uint256 const chkIdExp3{getCheckIndex(alice, env.seq(alice))};
1645 env(check::create(alice, bob, USD(10)), expiration(env.now() + 1s));
1646 env.close();
1647
1648 // Two checks to cancel using a regular key and using multisigning.
1649 uint256 const chkIdReg{getCheckIndex(alice, env.seq(alice))};
1650 env(check::create(alice, bob, USD(10)));
1651 env.close();
1652
1653 uint256 const chkIdMSig{getCheckIndex(alice, env.seq(alice))};
1654 env(check::create(alice, bob, XRP(10)));
1655 env.close();
1656 BEAST_EXPECT(checksOnAccount(env, alice).size() == 11);
1657 BEAST_EXPECT(ownerCount(env, alice) == 11);
1658
1659 // Creator, destination, and an outsider cancel the checks.
1660 env(check::cancel(alice, chkId1));
1661 env.close();
1662 BEAST_EXPECT(checksOnAccount(env, alice).size() == 10);
1663 BEAST_EXPECT(ownerCount(env, alice) == 10);
1664
1665 env(check::cancel(bob, chkId2));
1666 env.close();
1667 BEAST_EXPECT(checksOnAccount(env, alice).size() == 9);
1668 BEAST_EXPECT(ownerCount(env, alice) == 9);
1669
1670 env(check::cancel(zoe, chkId3), ter(tecNO_PERMISSION));
1671 env.close();
1672 BEAST_EXPECT(checksOnAccount(env, alice).size() == 9);
1673 BEAST_EXPECT(ownerCount(env, alice) == 9);
1674
1675 // Creator, destination, and an outsider cancel unexpired checks.
1676 env(check::cancel(alice, chkIdNotExp1));
1677 env.close();
1678 BEAST_EXPECT(checksOnAccount(env, alice).size() == 8);
1679 BEAST_EXPECT(ownerCount(env, alice) == 8);
1680
1681 env(check::cancel(bob, chkIdNotExp2));
1682 env.close();
1683 BEAST_EXPECT(checksOnAccount(env, alice).size() == 7);
1684 BEAST_EXPECT(ownerCount(env, alice) == 7);
1685
1686 env(check::cancel(zoe, chkIdNotExp3), ter(tecNO_PERMISSION));
1687 env.close();
1688 BEAST_EXPECT(checksOnAccount(env, alice).size() == 7);
1689 BEAST_EXPECT(ownerCount(env, alice) == 7);
1690
1691 // Creator, destination, and an outsider cancel expired checks.
1692 env(check::cancel(alice, chkIdExp1));
1693 env.close();
1694 BEAST_EXPECT(checksOnAccount(env, alice).size() == 6);
1695 BEAST_EXPECT(ownerCount(env, alice) == 6);
1696
1697 env(check::cancel(bob, chkIdExp2));
1698 env.close();
1699 BEAST_EXPECT(checksOnAccount(env, alice).size() == 5);
1700 BEAST_EXPECT(ownerCount(env, alice) == 5);
1701
1702 env(check::cancel(zoe, chkIdExp3));
1703 env.close();
1704 BEAST_EXPECT(checksOnAccount(env, alice).size() == 4);
1705 BEAST_EXPECT(ownerCount(env, alice) == 4);
1706
1707 // Use a regular key and also multisign to cancel checks.
1708 Account const alie{"alie", KeyType::ed25519};
1709 env(regkey(alice, alie));
1710 env.close();
1711
1712 Account const bogie{"bogie", KeyType::secp256k1};
1713 Account const demon{"demon", KeyType::ed25519};
1714 env(signers(alice, 2, {{bogie, 1}, {demon, 1}}), sig(alie));
1715 env.close();
1716
1717 // alice uses her regular key to cancel a check.
1718 env(check::cancel(alice, chkIdReg), sig(alie));
1719 env.close();
1720 BEAST_EXPECT(checksOnAccount(env, alice).size() == 3);
1721 BEAST_EXPECT(ownerCount(env, alice) == 4);
1722
1723 // alice uses multisigning to cancel a check.
1724 XRPAmount const baseFeeDrops{env.current()->fees().base};
1725 env(check::cancel(alice, chkIdMSig),
1726 msig(bogie, demon),
1727 fee(3 * baseFeeDrops));
1728 env.close();
1729 BEAST_EXPECT(checksOnAccount(env, alice).size() == 2);
1730 BEAST_EXPECT(ownerCount(env, alice) == 3);
1731
1732 // Creator and destination cancel the remaining unexpired checks.
1733 env(check::cancel(alice, chkId3), sig(alice));
1734 env.close();
1735 BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
1736 BEAST_EXPECT(ownerCount(env, alice) == 2);
1737
1738 env(check::cancel(bob, chkIdNotExp3));
1739 env.close();
1740 BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
1741 BEAST_EXPECT(ownerCount(env, alice) == 1);
1742 }
1743 }
1744
1745 void
1747 {
1748 // Explore many of the ways to fail at canceling a check.
1749 testcase("Cancel invalid");
1750
1751 using namespace test::jtx;
1752
1753 Account const alice{"alice"};
1754 Account const bob{"bob"};
1755
1756 Env env{*this, features};
1757
1758 env.fund(XRP(1000), alice, bob);
1759 env.close();
1760
1761 // Bad fee.
1762 env(check::cancel(bob, getCheckIndex(alice, env.seq(alice))),
1763 fee(drops(-10)),
1764 ter(temBAD_FEE));
1765 env.close();
1766
1767 // Bad flags.
1768 env(check::cancel(bob, getCheckIndex(alice, env.seq(alice))),
1769 txflags(tfImmediateOrCancel),
1770 ter(temINVALID_FLAG));
1771 env.close();
1772
1773 // Non-existent check.
1774 env(check::cancel(bob, getCheckIndex(alice, env.seq(alice))),
1775 ter(tecNO_ENTRY));
1776 env.close();
1777 }
1778
1779 void
1781 {
1782 testcase("DeliveredAmount For CheckCash Txn");
1783
1784 using namespace test::jtx;
1785 Account const alice{"alice"};
1786 Account const bob{"bob"};
1787
1788 Env env{*this, features};
1789
1790 env.fund(XRP(1000), alice, bob);
1791 env.close();
1792
1793 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
1794 env(check::create(alice, bob, XRP(200)));
1795 env.close();
1796
1797 env(check::cash(bob, chkId, check::DeliverMin(XRP(100))));
1798
1799 // Get the hash for the most recent transaction.
1800 std::string const txHash{
1801 env.tx()->getJson(JsonOptions::none)[jss::hash].asString()};
1802
1803 env.close();
1804 Json::Value const meta = env.rpc("tx", txHash)[jss::result][jss::meta];
1805
1806 // DeliveredAmount and delivered_amount are present.
1807 BEAST_EXPECT(meta.isMember(sfDeliveredAmount.jsonName));
1808 BEAST_EXPECT(meta.isMember(jss::delivered_amount));
1809 }
1810
1811 void
1813 {
1814 testcase("With Tickets");
1815
1816 using namespace test::jtx;
1817
1818 Account const gw{"gw"};
1819 Account const alice{"alice"};
1820 Account const bob{"bob"};
1821 IOU const USD{gw["USD"]};
1822
1823 Env env{*this, features};
1824 env.fund(XRP(1000), gw, alice, bob);
1825 env.close();
1826
1827 // alice and bob grab enough tickets for all of the following
1828 // transactions. Note that once the tickets are acquired alice's
1829 // and bob's account sequence numbers should not advance.
1830 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
1831 env(ticket::create(alice, 10));
1832 std::uint32_t const aliceSeq{env.seq(alice)};
1833
1834 std::uint32_t bobTicketSeq{env.seq(bob) + 1};
1835 env(ticket::create(bob, 10));
1836 std::uint32_t const bobSeq{env.seq(bob)};
1837
1838 env.close();
1839 env.require(owners(alice, 10));
1840 env.require(owners(bob, 10));
1841
1842 // alice gets enough USD to write a few checks.
1843 env(trust(alice, USD(1000)), ticket::use(aliceTicketSeq++));
1844 env(trust(bob, USD(1000)), ticket::use(bobTicketSeq++));
1845 env.close();
1846 env.require(owners(alice, 10));
1847 env.require(owners(bob, 10));
1848
1849 env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1850 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1851
1852 env.require(tickets(bob, env.seq(bob) - bobTicketSeq));
1853 BEAST_EXPECT(env.seq(bob) == bobSeq);
1854
1855 env(pay(gw, alice, USD(900)));
1856 env.close();
1857
1858 // alice creates four checks; two XRP, two IOU. Bob will cash
1859 // one of each and cancel one of each.
1860 uint256 const chkIdXrp1{getCheckIndex(alice, aliceTicketSeq)};
1861 env(check::create(alice, bob, XRP(200)), ticket::use(aliceTicketSeq++));
1862
1863 uint256 const chkIdXrp2{getCheckIndex(alice, aliceTicketSeq)};
1864 env(check::create(alice, bob, XRP(300)), ticket::use(aliceTicketSeq++));
1865
1866 uint256 const chkIdUsd1{getCheckIndex(alice, aliceTicketSeq)};
1867 env(check::create(alice, bob, USD(200)), ticket::use(aliceTicketSeq++));
1868
1869 uint256 const chkIdUsd2{getCheckIndex(alice, aliceTicketSeq)};
1870 env(check::create(alice, bob, USD(300)), ticket::use(aliceTicketSeq++));
1871
1872 env.close();
1873 // Alice used four tickets but created four checks.
1874 env.require(owners(alice, 10));
1875 env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1876 BEAST_EXPECT(checksOnAccount(env, alice).size() == 4);
1877 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1878
1879 env.require(owners(bob, 10));
1880 BEAST_EXPECT(env.seq(bob) == bobSeq);
1881
1882 // Bob cancels two of alice's checks.
1883 env(check::cancel(bob, chkIdXrp1), ticket::use(bobTicketSeq++));
1884 env(check::cancel(bob, chkIdUsd2), ticket::use(bobTicketSeq++));
1885 env.close();
1886
1887 env.require(owners(alice, 8));
1888 env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1889 BEAST_EXPECT(checksOnAccount(env, alice).size() == 2);
1890 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1891
1892 env.require(owners(bob, 8));
1893 BEAST_EXPECT(env.seq(bob) == bobSeq);
1894
1895 // Bob cashes alice's two remaining checks.
1896 env(check::cash(bob, chkIdXrp2, XRP(300)), ticket::use(bobTicketSeq++));
1897 env(check::cash(bob, chkIdUsd1, USD(200)), ticket::use(bobTicketSeq++));
1898 env.close();
1899
1900 env.require(owners(alice, 6));
1901 env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1902 BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
1903 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1904 env.require(balance(alice, USD(700)));
1905
1906 env.require(owners(bob, 6));
1907 BEAST_EXPECT(env.seq(bob) == bobSeq);
1908 env.require(balance(bob, USD(200)));
1909 }
1910
1911 void
1913 {
1914 // Explore automatic trust line creation when a check is cashed.
1915 //
1916
1917 testcase("Trust Line Creation");
1918
1919 using namespace test::jtx;
1920
1921 Env env{*this, features};
1922
1923 // An account that independently tracks its owner count.
1924 struct AccountOwns
1925 {
1927 Env const& env;
1928 Account const acct;
1929 std::size_t owners;
1930
1931 void
1932 verifyOwners(std::uint32_t line) const
1933 {
1934 suite.expect(
1935 ownerCount(env, acct) == owners,
1936 "Owner count mismatch",
1937 __FILE__,
1938 line);
1939 }
1940
1941 // Operators to make using the class more convenient.
1942 operator Account const() const
1943 {
1944 return acct;
1945 }
1946
1947 operator ripple::AccountID() const
1948 {
1949 return acct.id();
1950 }
1951
1952 IOU
1953 operator[](std::string const& s) const
1954 {
1955 return acct[s];
1956 }
1957 };
1958
1959 AccountOwns alice{*this, env, "alice", 0};
1960 AccountOwns bob{*this, env, "bob", 0};
1961
1962 // Fund with noripple so the accounts do not have any flags set.
1963 env.fund(XRP(5000), noripple(alice, bob));
1964 env.close();
1965
1966 // Automatic trust line creation should fail if the check destination
1967 // can't afford the reserve for the trust line.
1968 {
1969 AccountOwns gw1{*this, env, "gw1", 0};
1970
1971 // Fund gw1 with noripple (even though that's atypical for a
1972 // gateway) so it does not have any flags set. We'll set flags
1973 // on gw1 later.
1974 env.fund(XRP(5000), noripple(gw1));
1975 env.close();
1976
1977 IOU const CK8 = gw1["CK8"];
1978 gw1.verifyOwners(__LINE__);
1979
1980 Account const yui{"yui"};
1981
1982 // Note the reserve in unit tests is 200 XRP, not 20. So here
1983 // we're just barely giving yui enough XRP to meet the
1984 // account reserve.
1985 env.fund(XRP(200), yui);
1986 env.close();
1987
1988 uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))};
1989 env(check::create(gw1, yui, CK8(99)));
1990 env.close();
1991
1992 env(check::cash(yui, chkId, CK8(99)),
1994 env.close();
1995 alice.verifyOwners(__LINE__);
1996
1997 // Give yui enough XRP to meet the trust line's reserve. Cashing
1998 // the check succeeds and creates the trust line.
1999 env(pay(env.master, yui, XRP(51)));
2000 env.close();
2001 env(check::cash(yui, chkId, CK8(99)));
2002 verifyDeliveredAmount(env, CK8(99));
2003 env.close();
2004 BEAST_EXPECT(ownerCount(env, yui) == 1);
2005
2006 // The automatic trust line does not take a reserve from gw1.
2007 // Since gw1's check was consumed it has no owners.
2008 gw1.verifyOwners(__LINE__);
2009 }
2010
2011 // We'll be looking at the effects of various account root flags.
2012
2013 // Automatically create trust lines using
2014 // o Offers and
2015 // o Check cashing
2016 // Compare the resulting trust lines and expect them to be very similar.
2017
2018 // Lambda that compares two trust lines created by
2019 // o Offer crossing and
2020 // o Check cashing
2021 // between the same two accounts but with two different currencies.
2022 // The lambda expects the two trust lines to be largely similar.
2023 auto cmpTrustLines = [this, &env](
2024 Account const& acct1,
2025 Account const& acct2,
2026 IOU const& offerIou,
2027 IOU const& checkIou) {
2028 auto const offerLine =
2029 env.le(keylet::line(acct1, acct2, offerIou.currency));
2030 auto const checkLine =
2031 env.le(keylet::line(acct1, acct2, checkIou.currency));
2032 if (offerLine == nullptr || checkLine == nullptr)
2033 {
2034 BEAST_EXPECT(offerLine == nullptr && checkLine == nullptr);
2035 return;
2036 }
2037
2038 {
2039 // Compare the contents of required fields.
2040 BEAST_EXPECT(offerLine->at(sfFlags) == checkLine->at(sfFlags));
2041
2042 // Lambda that compares the contents of required STAmounts
2043 // without comparing the currency.
2044 auto cmpReqAmount =
2045 [this, offerLine, checkLine](SF_AMOUNT const& sfield) {
2046 STAmount const offerAmount = offerLine->at(sfield);
2047 STAmount const checkAmount = checkLine->at(sfield);
2048
2049 // Neither STAmount should be native.
2050 if (!BEAST_EXPECT(
2051 !offerAmount.native() && !checkAmount.native()))
2052 return;
2053
2054 BEAST_EXPECT(
2055 offerAmount.issue().account ==
2056 checkAmount.issue().account);
2057 BEAST_EXPECT(
2058 offerAmount.negative() == checkAmount.negative());
2059 BEAST_EXPECT(
2060 offerAmount.mantissa() == checkAmount.mantissa());
2061 BEAST_EXPECT(
2062 offerAmount.exponent() == checkAmount.exponent());
2063 };
2064 cmpReqAmount(sfBalance);
2065 cmpReqAmount(sfLowLimit);
2066 cmpReqAmount(sfHighLimit);
2067 }
2068 {
2069 // Lambda that compares the contents of optional fields.
2070 auto cmpOptField =
2071 [this, offerLine, checkLine](auto const& sfield) {
2072 // Expect both fields to either be present or absent.
2073 if (!BEAST_EXPECT(
2074 offerLine->isFieldPresent(sfield) ==
2075 checkLine->isFieldPresent(sfield)))
2076 return;
2077
2078 // If both fields are absent then there's nothing
2079 // further to check.
2080 if (!offerLine->isFieldPresent(sfield))
2081 return;
2082
2083 // Both optional fields are present so we can compare
2084 // them.
2085 BEAST_EXPECT(
2086 offerLine->at(sfield) == checkLine->at(sfield));
2087 };
2088 cmpOptField(sfLowNode);
2089 cmpOptField(sfLowQualityIn);
2090 cmpOptField(sfLowQualityOut);
2091
2092 cmpOptField(sfHighNode);
2093 cmpOptField(sfHighQualityIn);
2094 cmpOptField(sfHighQualityOut);
2095 }
2096 };
2097
2098 //----------- No account root flags, check written by issuer -----------
2099 {
2100 // No account root flags on any participant.
2101 // Automatic trust line from issuer to destination.
2102 AccountOwns gw1{*this, env, "gw1", 0};
2103
2104 BEAST_EXPECT((*env.le(gw1))[sfFlags] == 0);
2105 BEAST_EXPECT((*env.le(alice))[sfFlags] == 0);
2106 BEAST_EXPECT((*env.le(bob))[sfFlags] == 0);
2107
2108 // Use offers to automatically create the trust line.
2109 IOU const OF1 = gw1["OF1"];
2110 env(offer(gw1, XRP(98), OF1(98)));
2111 env.close();
2112 BEAST_EXPECT(
2113 env.le(keylet::line(gw1, alice, OF1.currency)) == nullptr);
2114 env(offer(alice, OF1(98), XRP(98)));
2115 ++alice.owners;
2116 env.close();
2117
2118 // Both offers should be consumed.
2119 // Since gw1's offer was consumed and the trust line was not
2120 // created by gw1, gw1's owner count should be 0.
2121 gw1.verifyOwners(__LINE__);
2122
2123 // alice's automatically created trust line bumps her owner count.
2124 alice.verifyOwners(__LINE__);
2125
2126 // Use check cashing to automatically create the trust line.
2127 IOU const CK1 = gw1["CK1"];
2128 uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))};
2129 env(check::create(gw1, alice, CK1(98)));
2130 env.close();
2131 BEAST_EXPECT(
2132 env.le(keylet::line(gw1, alice, CK1.currency)) == nullptr);
2133 env(check::cash(alice, chkId, CK1(98)));
2134 ++alice.owners;
2135 verifyDeliveredAmount(env, CK1(98));
2136 env.close();
2137
2138 // gw1's check should be consumed.
2139 // Since gw1's check 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 cmpTrustLines(gw1, alice, OF1, CK1);
2147 }
2148 //--------- No account root flags, check written by non-issuer ---------
2149 {
2150 // No account root flags on any participant.
2151 // Automatic trust line from non-issuer to non-issuer.
2152
2153 // Use offers to automatically create the trust line.
2154 // Transfer of assets using offers does not require rippling.
2155 // So bob's offer is successfully crossed which creates the
2156 // trust line.
2157 AccountOwns gw1{*this, env, "gw1", 0};
2158 IOU const OF1 = gw1["OF1"];
2159 env(offer(alice, XRP(97), OF1(97)));
2160 env.close();
2161 BEAST_EXPECT(
2162 env.le(keylet::line(alice, bob, OF1.currency)) == nullptr);
2163 env(offer(bob, OF1(97), XRP(97)));
2164 ++bob.owners;
2165 env.close();
2166
2167 // Both offers should be consumed.
2168 env.require(balance(alice, OF1(1)));
2169 env.require(balance(bob, OF1(97)));
2170
2171 // bob now has an owner count of 1 due to the new trust line.
2172 gw1.verifyOwners(__LINE__);
2173 alice.verifyOwners(__LINE__);
2174 bob.verifyOwners(__LINE__);
2175
2176 // Use check cashing to automatically create the trust line.
2177 //
2178 // However cashing a check (unlike crossing offers) requires
2179 // rippling through the currency's issuer. Since gw1 does not
2180 // have rippling enabled the check cash fails and bob does not
2181 // have a trust line created.
2182 IOU const CK1 = gw1["CK1"];
2183 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
2184 env(check::create(alice, bob, CK1(97)));
2185 env.close();
2186 BEAST_EXPECT(
2187 env.le(keylet::line(alice, bob, CK1.currency)) == nullptr);
2188 env(check::cash(bob, chkId, CK1(97)), ter(terNO_RIPPLE));
2189 env.close();
2190
2191 BEAST_EXPECT(
2192 env.le(keylet::line(gw1, bob, OF1.currency)) != nullptr);
2193 BEAST_EXPECT(
2194 env.le(keylet::line(gw1, bob, CK1.currency)) == nullptr);
2195
2196 // Delete alice's check since it is no longer needed.
2197 env(check::cancel(alice, chkId));
2198 env.close();
2199
2200 // No one's owner count should have changed.
2201 gw1.verifyOwners(__LINE__);
2202 alice.verifyOwners(__LINE__);
2203 bob.verifyOwners(__LINE__);
2204 }
2205
2206 //------------- lsfDefaultRipple, check written by issuer --------------
2207 {
2208 // gw1 enables rippling.
2209 // Automatic trust line from issuer to non-issuer should still work.
2210 AccountOwns gw1{*this, env, "gw1", 0};
2211 env(fset(gw1, asfDefaultRipple));
2212 env.close();
2213
2214 // Use offers to automatically create the trust line.
2215 IOU const OF2 = gw1["OF2"];
2216 env(offer(gw1, XRP(96), OF2(96)));
2217 env.close();
2218 BEAST_EXPECT(
2219 env.le(keylet::line(gw1, alice, OF2.currency)) == nullptr);
2220 env(offer(alice, OF2(96), XRP(96)));
2221 ++alice.owners;
2222 env.close();
2223
2224 // Both offers should be consumed.
2225 // Since gw1's offer was consumed and the trust line was not
2226 // created by gw1, gw1's owner count should still be 0.
2227 gw1.verifyOwners(__LINE__);
2228
2229 // alice's automatically created trust line bumps her owner count.
2230 alice.verifyOwners(__LINE__);
2231
2232 // Use check cashing to automatically create the trust line.
2233 IOU const CK2 = gw1["CK2"];
2234 uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))};
2235 env(check::create(gw1, alice, CK2(96)));
2236 env.close();
2237 BEAST_EXPECT(
2238 env.le(keylet::line(gw1, alice, CK2.currency)) == nullptr);
2239 env(check::cash(alice, chkId, CK2(96)));
2240 ++alice.owners;
2241 verifyDeliveredAmount(env, CK2(96));
2242 env.close();
2243
2244 // gw1's check should be consumed.
2245 // Since gw1's check 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 cmpTrustLines(gw1, alice, OF2, CK2);
2253 }
2254 //----------- lsfDefaultRipple, check written by non-issuer ------------
2255 {
2256 // gw1 enabled rippling, so automatic trust line from non-issuer
2257 // to non-issuer should work.
2258
2259 // Use offers to automatically create the trust line.
2260 AccountOwns gw1{*this, env, "gw1", 0};
2261 IOU const OF2 = gw1["OF2"];
2262 env(offer(alice, XRP(95), OF2(95)));
2263 env.close();
2264 BEAST_EXPECT(
2265 env.le(keylet::line(alice, bob, OF2.currency)) == nullptr);
2266 env(offer(bob, OF2(95), XRP(95)));
2267 ++bob.owners;
2268 env.close();
2269
2270 // bob's owner count should increase due to the new trust line.
2271 gw1.verifyOwners(__LINE__);
2272 alice.verifyOwners(__LINE__);
2273 bob.verifyOwners(__LINE__);
2274
2275 // Use check cashing to automatically create the trust line.
2276 IOU const CK2 = gw1["CK2"];
2277 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
2278 env(check::create(alice, bob, CK2(95)));
2279 env.close();
2280 BEAST_EXPECT(
2281 env.le(keylet::line(alice, bob, CK2.currency)) == nullptr);
2282 env(check::cash(bob, chkId, CK2(95)));
2283 ++bob.owners;
2284 verifyDeliveredAmount(env, CK2(95));
2285 env.close();
2286
2287 // bob's owner count should increase due to the new trust line.
2288 gw1.verifyOwners(__LINE__);
2289 alice.verifyOwners(__LINE__);
2290 bob.verifyOwners(__LINE__);
2291
2292 cmpTrustLines(alice, bob, OF2, CK2);
2293 }
2294
2295 //-------------- lsfDepositAuth, check written by issuer ---------------
2296 {
2297 // Both offers and checks ignore the lsfDepositAuth flag, since
2298 // the destination signs the transaction that delivers their funds.
2299 // So setting lsfDepositAuth on all the participants should not
2300 // change any outcomes.
2301 //
2302 // Automatic trust line from issuer to non-issuer should still work.
2303 AccountOwns gw1{*this, env, "gw1", 0};
2304 env(fset(gw1, asfDepositAuth));
2305 env(fset(alice, asfDepositAuth));
2306 env(fset(bob, asfDepositAuth));
2307 env.close();
2308
2309 // Use offers to automatically create the trust line.
2310 IOU const OF3 = gw1["OF3"];
2311 env(offer(gw1, XRP(94), OF3(94)));
2312 env.close();
2313 BEAST_EXPECT(
2314 env.le(keylet::line(gw1, alice, OF3.currency)) == nullptr);
2315 env(offer(alice, OF3(94), XRP(94)));
2316 ++alice.owners;
2317 env.close();
2318
2319 // Both offers should be consumed.
2320 // Since gw1's offer was consumed and the trust line was not
2321 // created by gw1, gw1's owner count should still be 0.
2322 gw1.verifyOwners(__LINE__);
2323
2324 // alice's automatically created trust line bumps her owner count.
2325 alice.verifyOwners(__LINE__);
2326
2327 // Use check cashing to automatically create the trust line.
2328 IOU const CK3 = gw1["CK3"];
2329 uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))};
2330 env(check::create(gw1, alice, CK3(94)));
2331 env.close();
2332 BEAST_EXPECT(
2333 env.le(keylet::line(gw1, alice, CK3.currency)) == nullptr);
2334 env(check::cash(alice, chkId, CK3(94)));
2335 ++alice.owners;
2336 verifyDeliveredAmount(env, CK3(94));
2337 env.close();
2338
2339 // gw1's check should be consumed.
2340 // Since gw1's check 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 cmpTrustLines(gw1, alice, OF3, CK3);
2348 }
2349 //------------ lsfDepositAuth, check written by non-issuer -------------
2350 {
2351 // The presence of the lsfDepositAuth flag should not affect
2352 // automatic trust line creation.
2353
2354 // Use offers to automatically create the trust line.
2355 AccountOwns gw1{*this, env, "gw1", 0};
2356 IOU const OF3 = gw1["OF3"];
2357 env(offer(alice, XRP(93), OF3(93)));
2358 env.close();
2359 BEAST_EXPECT(
2360 env.le(keylet::line(alice, bob, OF3.currency)) == nullptr);
2361 env(offer(bob, OF3(93), XRP(93)));
2362 ++bob.owners;
2363 env.close();
2364
2365 // bob's owner count should increase due to the new trust line.
2366 gw1.verifyOwners(__LINE__);
2367 alice.verifyOwners(__LINE__);
2368 bob.verifyOwners(__LINE__);
2369
2370 // Use check cashing to automatically create the trust line.
2371 IOU const CK3 = gw1["CK3"];
2372 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
2373 env(check::create(alice, bob, CK3(93)));
2374 env.close();
2375 BEAST_EXPECT(
2376 env.le(keylet::line(alice, bob, CK3.currency)) == nullptr);
2377 env(check::cash(bob, chkId, CK3(93)));
2378 ++bob.owners;
2379 verifyDeliveredAmount(env, CK3(93));
2380 env.close();
2381
2382 // bob's owner count should increase due to the new trust line.
2383 gw1.verifyOwners(__LINE__);
2384 alice.verifyOwners(__LINE__);
2385 bob.verifyOwners(__LINE__);
2386
2387 cmpTrustLines(alice, bob, OF3, CK3);
2388 }
2389
2390 //-------------- lsfGlobalFreeze, check written by issuer --------------
2391 {
2392 // Set lsfGlobalFreeze on gw1. That should stop any automatic
2393 // trust lines from being created.
2394 AccountOwns gw1{*this, env, "gw1", 0};
2395 env(fset(gw1, asfGlobalFreeze));
2396 env.close();
2397
2398 // Use offers to automatically create the trust line.
2399 IOU const OF4 = gw1["OF4"];
2400 env(offer(gw1, XRP(92), OF4(92)), ter(tecFROZEN));
2401 env.close();
2402 BEAST_EXPECT(
2403 env.le(keylet::line(gw1, alice, OF4.currency)) == nullptr);
2404 env(offer(alice, OF4(92), XRP(92)), ter(tecFROZEN));
2405 env.close();
2406
2407 // No one's owner count should have changed.
2408 gw1.verifyOwners(__LINE__);
2409 alice.verifyOwners(__LINE__);
2410 bob.verifyOwners(__LINE__);
2411
2412 // Use check cashing to automatically create the trust line.
2413 IOU const CK4 = gw1["CK4"];
2414 uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))};
2415 env(check::create(gw1, alice, CK4(92)), ter(tecFROZEN));
2416 env.close();
2417 BEAST_EXPECT(
2418 env.le(keylet::line(gw1, alice, CK4.currency)) == nullptr);
2419 env(check::cash(alice, chkId, CK4(92)), ter(tecNO_ENTRY));
2420 env.close();
2421
2422 // No one's owner count should have changed.
2423 gw1.verifyOwners(__LINE__);
2424 alice.verifyOwners(__LINE__);
2425 bob.verifyOwners(__LINE__);
2426
2427 // Because gw1 has set lsfGlobalFreeze, neither trust line
2428 // is created.
2429 BEAST_EXPECT(
2430 env.le(keylet::line(gw1, alice, OF4.currency)) == nullptr);
2431 BEAST_EXPECT(
2432 env.le(keylet::line(gw1, alice, CK4.currency)) == nullptr);
2433 }
2434 //------------ lsfGlobalFreeze, check written by non-issuer ------------
2435 {
2436 // Since gw1 has the lsfGlobalFreeze flag set, there should be
2437 // no automatic trust line creation between non-issuers.
2438
2439 // Use offers to automatically create the trust line.
2440 AccountOwns gw1{*this, env, "gw1", 0};
2441 IOU const OF4 = gw1["OF4"];
2442 env(offer(alice, XRP(91), OF4(91)), ter(tecFROZEN));
2443 env.close();
2444 BEAST_EXPECT(
2445 env.le(keylet::line(alice, bob, OF4.currency)) == nullptr);
2446 env(offer(bob, OF4(91), XRP(91)), ter(tecFROZEN));
2447 env.close();
2448
2449 // No one's owner count should have changed.
2450 gw1.verifyOwners(__LINE__);
2451 alice.verifyOwners(__LINE__);
2452 bob.verifyOwners(__LINE__);
2453
2454 // Use check cashing to automatically create the trust line.
2455 IOU const CK4 = gw1["CK4"];
2456 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
2457 env(check::create(alice, bob, CK4(91)), ter(tecFROZEN));
2458 env.close();
2459 BEAST_EXPECT(
2460 env.le(keylet::line(alice, bob, CK4.currency)) == nullptr);
2461 env(check::cash(bob, chkId, CK4(91)), ter(tecNO_ENTRY));
2462 env.close();
2463
2464 // No one's owner count should have changed.
2465 gw1.verifyOwners(__LINE__);
2466 alice.verifyOwners(__LINE__);
2467 bob.verifyOwners(__LINE__);
2468
2469 // Because gw1 has set lsfGlobalFreeze, neither trust line
2470 // is created.
2471 BEAST_EXPECT(
2472 env.le(keylet::line(gw1, bob, OF4.currency)) == nullptr);
2473 BEAST_EXPECT(
2474 env.le(keylet::line(gw1, bob, CK4.currency)) == nullptr);
2475 }
2476
2477 //-------------- lsfRequireAuth, check written by issuer ---------------
2478
2479 // We want to test the lsfRequireAuth flag, but we can't set that
2480 // flag on an account that already has trust lines. So we'll fund
2481 // a new gateway and use that.
2482 {
2483 AccountOwns gw2{*this, env, "gw2", 0};
2484 env.fund(XRP(5000), gw2);
2485 env.close();
2486
2487 // Set lsfRequireAuth on gw2. That should stop any automatic
2488 // trust lines from being created.
2489 env(fset(gw2, asfRequireAuth));
2490 env.close();
2491
2492 // Use offers to automatically create the trust line.
2493 IOU const OF5 = gw2["OF5"];
2494 std::uint32_t gw2OfferSeq = {env.seq(gw2)};
2495 env(offer(gw2, XRP(92), OF5(92)));
2496 ++gw2.owners;
2497 env.close();
2498 BEAST_EXPECT(
2499 env.le(keylet::line(gw2, alice, OF5.currency)) == nullptr);
2500 env(offer(alice, OF5(92), XRP(92)), ter(tecNO_LINE));
2501 env.close();
2502
2503 // gw2 should still own the offer, but no one else's owner
2504 // count should have changed.
2505 gw2.verifyOwners(__LINE__);
2506 alice.verifyOwners(__LINE__);
2507 bob.verifyOwners(__LINE__);
2508
2509 // Since we don't need it any more, remove gw2's offer.
2510 env(offer_cancel(gw2, gw2OfferSeq));
2511 --gw2.owners;
2512 env.close();
2513 gw2.verifyOwners(__LINE__);
2514
2515 // Use check cashing to automatically create the trust line.
2516 IOU const CK5 = gw2["CK5"];
2517 uint256 const chkId{getCheckIndex(gw2, env.seq(gw2))};
2518 env(check::create(gw2, alice, CK5(92)));
2519 ++gw2.owners;
2520 env.close();
2521 BEAST_EXPECT(
2522 env.le(keylet::line(gw2, alice, CK5.currency)) == nullptr);
2523 env(check::cash(alice, chkId, CK5(92)), ter(tecNO_AUTH));
2524 env.close();
2525
2526 // gw2 should still own the check, but no one else's owner
2527 // count should have changed.
2528 gw2.verifyOwners(__LINE__);
2529 alice.verifyOwners(__LINE__);
2530 bob.verifyOwners(__LINE__);
2531
2532 // Because gw2 has set lsfRequireAuth, neither trust line
2533 // is created.
2534 BEAST_EXPECT(
2535 env.le(keylet::line(gw2, alice, OF5.currency)) == nullptr);
2536 BEAST_EXPECT(
2537 env.le(keylet::line(gw2, alice, CK5.currency)) == nullptr);
2538
2539 // Since we don't need it any more, remove gw2's check.
2540 env(check::cancel(gw2, chkId));
2541 --gw2.owners;
2542 env.close();
2543 gw2.verifyOwners(__LINE__);
2544 }
2545 //------------ lsfRequireAuth, check written by non-issuer -------------
2546 {
2547 // Since gw2 has the lsfRequireAuth flag set, there should be
2548 // no automatic trust line creation between non-issuers.
2549
2550 // Use offers to automatically create the trust line.
2551 AccountOwns gw2{*this, env, "gw2", 0};
2552 IOU const OF5 = gw2["OF5"];
2553 env(offer(alice, XRP(91), OF5(91)), ter(tecUNFUNDED_OFFER));
2554 env.close();
2555 env(offer(bob, OF5(91), XRP(91)), ter(tecNO_LINE));
2556 BEAST_EXPECT(
2557 env.le(keylet::line(gw2, bob, OF5.currency)) == nullptr);
2558 env.close();
2559
2560 gw2.verifyOwners(__LINE__);
2561 alice.verifyOwners(__LINE__);
2562 bob.verifyOwners(__LINE__);
2563
2564 // Use check cashing to automatically create the trust line.
2565 IOU const CK5 = gw2["CK5"];
2566 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
2567 env(check::create(alice, bob, CK5(91)));
2568 env.close();
2569 BEAST_EXPECT(
2570 env.le(keylet::line(alice, bob, CK5.currency)) == nullptr);
2571 env(check::cash(bob, chkId, CK5(91)), ter(tecPATH_PARTIAL));
2572 env.close();
2573
2574 // Delete alice's check since it is no longer needed.
2575 env(check::cancel(alice, chkId));
2576 env.close();
2577
2578 // No one's owner count should have changed.
2579 gw2.verifyOwners(__LINE__);
2580 alice.verifyOwners(__LINE__);
2581 bob.verifyOwners(__LINE__);
2582
2583 // Because gw2 has set lsfRequireAuth, neither trust line
2584 // is created.
2585 BEAST_EXPECT(
2586 env.le(keylet::line(gw2, bob, OF5.currency)) == nullptr);
2587 BEAST_EXPECT(
2588 env.le(keylet::line(gw2, bob, CK5.currency)) == nullptr);
2589 }
2590 }
2591
2592 void
2594 {
2595 testEnabled(features);
2596 testCreateValid(features);
2598 testCreateInvalid(features);
2599 testCashXRP(features);
2600 testCashIOU(features);
2601 testCashXferFee(features);
2602 testCashQuality(features);
2603 testCashInvalid(features);
2604 testCancelValid(features);
2605 testCancelInvalid(features);
2607 testWithTickets(features);
2608 }
2609
2610public:
2611 void
2612 run() override
2613 {
2614 using namespace test::jtx;
2615 auto const sa = testable_amendments();
2617 testWithFeats(sa);
2619 }
2620};
2621
2622BEAST_DEFINE_TESTSUITE(Check, app, ripple);
2623
2624} // 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