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