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