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