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
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
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)),
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)),
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().accountReserve(0)};
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)),
632 env.close();
633 env(check::cash(
634 bob, chkId, check::DeliverMin(checkAmount + drops(1))),
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().accountReserve(0)};
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))),
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))),
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),
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()),
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)),
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))),
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))),
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))),
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))),
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("Fix1623 enable");
1873
1874 using namespace test::jtx;
1875
1876 auto testEnable = [this](
1877 FeatureBitset const& features, bool hasFields) {
1878 // Unless fix1623 is enabled a "tx" RPC command should return
1879 // neither "DeliveredAmount" nor "delivered_amount" on a CheckCash
1880 // transaction.
1881 Account const alice{"alice"};
1882 Account const bob{"bob"};
1883
1884 Env env{*this, features};
1885
1886 env.fund(XRP(1000), alice, bob);
1887 env.close();
1888
1889 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
1890 env(check::create(alice, bob, XRP(200)));
1891 env.close();
1892
1893 env(check::cash(bob, chkId, check::DeliverMin(XRP(100))));
1894
1895 // Get the hash for the most recent transaction.
1896 std::string const txHash{
1897 env.tx()->getJson(JsonOptions::none)[jss::hash].asString()};
1898
1899 // DeliveredAmount and delivered_amount are either present or
1900 // not present in the metadata returned by "tx" based on fix1623.
1901 env.close();
1902 Json::Value const meta =
1903 env.rpc("tx", txHash)[jss::result][jss::meta];
1904
1905 BEAST_EXPECT(
1906 meta.isMember(sfDeliveredAmount.jsonName) == hasFields);
1907 BEAST_EXPECT(meta.isMember(jss::delivered_amount) == hasFields);
1908 };
1909
1910 // Run both the disabled and enabled cases.
1911 testEnable(features - fix1623, false);
1912 testEnable(features, true);
1913 }
1914
1915 void
1917 {
1918 testcase("With Tickets");
1919
1920 using namespace test::jtx;
1921
1922 Account const gw{"gw"};
1923 Account const alice{"alice"};
1924 Account const bob{"bob"};
1925 IOU const USD{gw["USD"]};
1926
1927 Env env{*this, features};
1928 env.fund(XRP(1000), gw, alice, bob);
1929 env.close();
1930
1931 // alice and bob grab enough tickets for all of the following
1932 // transactions. Note that once the tickets are acquired alice's
1933 // and bob's account sequence numbers should not advance.
1934 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
1935 env(ticket::create(alice, 10));
1936 std::uint32_t const aliceSeq{env.seq(alice)};
1937
1938 std::uint32_t bobTicketSeq{env.seq(bob) + 1};
1939 env(ticket::create(bob, 10));
1940 std::uint32_t const bobSeq{env.seq(bob)};
1941
1942 env.close();
1943 env.require(owners(alice, 10));
1944 env.require(owners(bob, 10));
1945
1946 // alice gets enough USD to write a few checks.
1947 env(trust(alice, USD(1000)), ticket::use(aliceTicketSeq++));
1948 env(trust(bob, USD(1000)), ticket::use(bobTicketSeq++));
1949 env.close();
1950 env.require(owners(alice, 10));
1951 env.require(owners(bob, 10));
1952
1953 env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1954 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1955
1956 env.require(tickets(bob, env.seq(bob) - bobTicketSeq));
1957 BEAST_EXPECT(env.seq(bob) == bobSeq);
1958
1959 env(pay(gw, alice, USD(900)));
1960 env.close();
1961
1962 // alice creates four checks; two XRP, two IOU. Bob will cash
1963 // one of each and cancel one of each.
1964 uint256 const chkIdXrp1{getCheckIndex(alice, aliceTicketSeq)};
1965 env(check::create(alice, bob, XRP(200)), ticket::use(aliceTicketSeq++));
1966
1967 uint256 const chkIdXrp2{getCheckIndex(alice, aliceTicketSeq)};
1968 env(check::create(alice, bob, XRP(300)), ticket::use(aliceTicketSeq++));
1969
1970 uint256 const chkIdUsd1{getCheckIndex(alice, aliceTicketSeq)};
1971 env(check::create(alice, bob, USD(200)), ticket::use(aliceTicketSeq++));
1972
1973 uint256 const chkIdUsd2{getCheckIndex(alice, aliceTicketSeq)};
1974 env(check::create(alice, bob, USD(300)), ticket::use(aliceTicketSeq++));
1975
1976 env.close();
1977 // Alice used four tickets but created four checks.
1978 env.require(owners(alice, 10));
1979 env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1980 BEAST_EXPECT(checksOnAccount(env, alice).size() == 4);
1981 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1982
1983 env.require(owners(bob, 10));
1984 BEAST_EXPECT(env.seq(bob) == bobSeq);
1985
1986 // Bob cancels two of alice's checks.
1987 env(check::cancel(bob, chkIdXrp1), ticket::use(bobTicketSeq++));
1988 env(check::cancel(bob, chkIdUsd2), ticket::use(bobTicketSeq++));
1989 env.close();
1990
1991 env.require(owners(alice, 8));
1992 env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1993 BEAST_EXPECT(checksOnAccount(env, alice).size() == 2);
1994 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1995
1996 env.require(owners(bob, 8));
1997 BEAST_EXPECT(env.seq(bob) == bobSeq);
1998
1999 // Bob cashes alice's two remaining checks.
2000 env(check::cash(bob, chkIdXrp2, XRP(300)), ticket::use(bobTicketSeq++));
2001 env(check::cash(bob, chkIdUsd1, USD(200)), ticket::use(bobTicketSeq++));
2002 env.close();
2003
2004 env.require(owners(alice, 6));
2005 env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
2006 BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
2007 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2008 env.require(balance(alice, USD(700)));
2009
2010 env.require(owners(bob, 6));
2011 BEAST_EXPECT(env.seq(bob) == bobSeq);
2012 env.require(balance(bob, USD(200)));
2013 }
2014
2015 void
2017 {
2018 // Explore automatic trust line creation when a check is cashed.
2019 //
2020 // This capability is enabled by the featureCheckCashMakesTrustLine
2021 // amendment. So this test executes only when that amendment is
2022 // active.
2023 assert(features[featureCheckCashMakesTrustLine]);
2024
2025 testcase("Trust Line Creation");
2026
2027 using namespace test::jtx;
2028
2029 Env env{*this, features};
2030
2031 // An account that independently tracks its owner count.
2032 struct AccountOwns
2033 {
2035 Env const& env;
2036 Account const acct;
2038
2039 void
2040 verifyOwners(std::uint32_t line) const
2041 {
2042 suite.expect(
2043 ownerCount(env, acct) == owners,
2044 "Owner count mismatch",
2045 __FILE__,
2046 line);
2047 }
2048
2049 // Operators to make using the class more convenient.
2050 operator Account const() const
2051 {
2052 return acct;
2053 }
2054
2055 operator ripple::AccountID() const
2056 {
2057 return acct.id();
2058 }
2059
2060 IOU
2061 operator[](std::string const& s) const
2062 {
2063 return acct[s];
2064 }
2065 };
2066
2067 AccountOwns alice{*this, env, "alice", 0};
2068 AccountOwns bob{*this, env, "bob", 0};
2069
2070 // Fund with noripple so the accounts do not have any flags set.
2071 env.fund(XRP(5000), noripple(alice, bob));
2072 env.close();
2073
2074 // Automatic trust line creation should fail if the check destination
2075 // can't afford the reserve for the trust line.
2076 {
2077 AccountOwns gw1{*this, env, "gw1", 0};
2078
2079 // Fund gw1 with noripple (even though that's atypical for a
2080 // gateway) so it does not have any flags set. We'll set flags
2081 // on gw1 later.
2082 env.fund(XRP(5000), noripple(gw1));
2083 env.close();
2084
2085 IOU const CK8 = gw1["CK8"];
2086 gw1.verifyOwners(__LINE__);
2087
2088 Account const yui{"yui"};
2089
2090 // Note the reserve in unit tests is 200 XRP, not 20. So here
2091 // we're just barely giving yui enough XRP to meet the
2092 // account reserve.
2093 env.fund(XRP(200), yui);
2094 env.close();
2095
2096 uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))};
2097 env(check::create(gw1, yui, CK8(99)));
2098 env.close();
2099
2100 env(check::cash(yui, chkId, CK8(99)),
2102 env.close();
2103 alice.verifyOwners(__LINE__);
2104
2105 // Give yui enough XRP to meet the trust line's reserve. Cashing
2106 // the check succeeds and creates the trust line.
2107 env(pay(env.master, yui, XRP(51)));
2108 env.close();
2109 env(check::cash(yui, chkId, CK8(99)));
2110 verifyDeliveredAmount(env, CK8(99));
2111 env.close();
2112 BEAST_EXPECT(ownerCount(env, yui) == 1);
2113
2114 // The automatic trust line does not take a reserve from gw1.
2115 // Since gw1's check was consumed it has no owners.
2116 gw1.verifyOwners(__LINE__);
2117 }
2118
2119 // We'll be looking at the effects of various account root flags.
2120
2121 // Automatically create trust lines using
2122 // o Offers and
2123 // o Check cashing
2124 // Compare the resulting trust lines and expect them to be very similar.
2125
2126 // Lambda that compares two trust lines created by
2127 // o Offer crossing and
2128 // o Check cashing
2129 // between the same two accounts but with two different currencies.
2130 // The lambda expects the two trust lines to be largely similar.
2131 auto cmpTrustLines = [this, &env](
2132 Account const& acct1,
2133 Account const& acct2,
2134 IOU const& offerIou,
2135 IOU const& checkIou) {
2136 auto const offerLine =
2137 env.le(keylet::line(acct1, acct2, offerIou.currency));
2138 auto const checkLine =
2139 env.le(keylet::line(acct1, acct2, checkIou.currency));
2140 if (offerLine == nullptr || checkLine == nullptr)
2141 {
2142 BEAST_EXPECT(offerLine == nullptr && checkLine == nullptr);
2143 return;
2144 }
2145
2146 {
2147 // Compare the contents of required fields.
2148 BEAST_EXPECT(offerLine->at(sfFlags) == checkLine->at(sfFlags));
2149
2150 // Lambda that compares the contents of required STAmounts
2151 // without comparing the currency.
2152 auto cmpReqAmount =
2153 [this, offerLine, checkLine](SF_AMOUNT const& sfield) {
2154 STAmount const offerAmount = offerLine->at(sfield);
2155 STAmount const checkAmount = checkLine->at(sfield);
2156
2157 // Neither STAmount should be native.
2158 if (!BEAST_EXPECT(
2159 !offerAmount.native() && !checkAmount.native()))
2160 return;
2161
2162 BEAST_EXPECT(
2163 offerAmount.issue().account ==
2164 checkAmount.issue().account);
2165 BEAST_EXPECT(
2166 offerAmount.negative() == checkAmount.negative());
2167 BEAST_EXPECT(
2168 offerAmount.mantissa() == checkAmount.mantissa());
2169 BEAST_EXPECT(
2170 offerAmount.exponent() == checkAmount.exponent());
2171 };
2172 cmpReqAmount(sfBalance);
2173 cmpReqAmount(sfLowLimit);
2174 cmpReqAmount(sfHighLimit);
2175 }
2176 {
2177 // Lambda that compares the contents of optional fields.
2178 auto cmpOptField =
2179 [this, offerLine, checkLine](auto const& sfield) {
2180 // Expect both fields to either be present or absent.
2181 if (!BEAST_EXPECT(
2182 offerLine->isFieldPresent(sfield) ==
2183 checkLine->isFieldPresent(sfield)))
2184 return;
2185
2186 // If both fields are absent then there's nothing
2187 // further to check.
2188 if (!offerLine->isFieldPresent(sfield))
2189 return;
2190
2191 // Both optional fields are present so we can compare
2192 // them.
2193 BEAST_EXPECT(
2194 offerLine->at(sfield) == checkLine->at(sfield));
2195 };
2196 cmpOptField(sfLowNode);
2197 cmpOptField(sfLowQualityIn);
2198 cmpOptField(sfLowQualityOut);
2199
2200 cmpOptField(sfHighNode);
2201 cmpOptField(sfHighQualityIn);
2202 cmpOptField(sfHighQualityOut);
2203 }
2204 };
2205
2206 //----------- No account root flags, check written by issuer -----------
2207 {
2208 // No account root flags on any participant.
2209 // Automatic trust line from issuer to destination.
2210 AccountOwns gw1{*this, env, "gw1", 0};
2211
2212 BEAST_EXPECT((*env.le(gw1))[sfFlags] == 0);
2213 BEAST_EXPECT((*env.le(alice))[sfFlags] == 0);
2214 BEAST_EXPECT((*env.le(bob))[sfFlags] == 0);
2215
2216 // Use offers to automatically create the trust line.
2217 IOU const OF1 = gw1["OF1"];
2218 env(offer(gw1, XRP(98), OF1(98)));
2219 env.close();
2220 BEAST_EXPECT(
2221 env.le(keylet::line(gw1, alice, OF1.currency)) == nullptr);
2222 env(offer(alice, OF1(98), XRP(98)));
2223 ++alice.owners;
2224 env.close();
2225
2226 // Both offers should be consumed.
2227 // Since gw1's offer was consumed and the trust line was not
2228 // created by gw1, gw1's owner count should be 0.
2229 gw1.verifyOwners(__LINE__);
2230
2231 // alice's automatically created trust line bumps her owner count.
2232 alice.verifyOwners(__LINE__);
2233
2234 // Use check cashing to automatically create the trust line.
2235 IOU const CK1 = gw1["CK1"];
2236 uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))};
2237 env(check::create(gw1, alice, CK1(98)));
2238 env.close();
2239 BEAST_EXPECT(
2240 env.le(keylet::line(gw1, alice, CK1.currency)) == nullptr);
2241 env(check::cash(alice, chkId, CK1(98)));
2242 ++alice.owners;
2243 verifyDeliveredAmount(env, CK1(98));
2244 env.close();
2245
2246 // gw1's check should be consumed.
2247 // Since gw1's check was consumed and the trust line was not
2248 // created by gw1, gw1's owner count should be 0.
2249 gw1.verifyOwners(__LINE__);
2250
2251 // alice's automatically created trust line bumps her owner count.
2252 alice.verifyOwners(__LINE__);
2253
2254 cmpTrustLines(gw1, alice, OF1, CK1);
2255 }
2256 //--------- No account root flags, check written by non-issuer ---------
2257 {
2258 // No account root flags on any participant.
2259 // Automatic trust line from non-issuer to non-issuer.
2260
2261 // Use offers to automatically create the trust line.
2262 // Transfer of assets using offers does not require rippling.
2263 // So bob's offer is successfully crossed which creates the
2264 // trust line.
2265 AccountOwns gw1{*this, env, "gw1", 0};
2266 IOU const OF1 = gw1["OF1"];
2267 env(offer(alice, XRP(97), OF1(97)));
2268 env.close();
2269 BEAST_EXPECT(
2270 env.le(keylet::line(alice, bob, OF1.currency)) == nullptr);
2271 env(offer(bob, OF1(97), XRP(97)));
2272 ++bob.owners;
2273 env.close();
2274
2275 // Both offers should be consumed.
2276 env.require(balance(alice, OF1(1)));
2277 env.require(balance(bob, OF1(97)));
2278
2279 // bob now has an owner count of 1 due to the new trust line.
2280 gw1.verifyOwners(__LINE__);
2281 alice.verifyOwners(__LINE__);
2282 bob.verifyOwners(__LINE__);
2283
2284 // Use check cashing to automatically create the trust line.
2285 //
2286 // However cashing a check (unlike crossing offers) requires
2287 // rippling through the currency's issuer. Since gw1 does not
2288 // have rippling enabled the check cash fails and bob does not
2289 // have a trust line created.
2290 IOU const CK1 = gw1["CK1"];
2291 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
2292 env(check::create(alice, bob, CK1(97)));
2293 env.close();
2294 BEAST_EXPECT(
2295 env.le(keylet::line(alice, bob, CK1.currency)) == nullptr);
2296 env(check::cash(bob, chkId, CK1(97)), ter(terNO_RIPPLE));
2297 env.close();
2298
2299 BEAST_EXPECT(
2300 env.le(keylet::line(gw1, bob, OF1.currency)) != nullptr);
2301 BEAST_EXPECT(
2302 env.le(keylet::line(gw1, bob, CK1.currency)) == nullptr);
2303
2304 // Delete alice's check since it is no longer needed.
2305 env(check::cancel(alice, chkId));
2306 env.close();
2307
2308 // No one's owner count should have changed.
2309 gw1.verifyOwners(__LINE__);
2310 alice.verifyOwners(__LINE__);
2311 bob.verifyOwners(__LINE__);
2312 }
2313
2314 //------------- lsfDefaultRipple, check written by issuer --------------
2315 {
2316 // gw1 enables rippling.
2317 // Automatic trust line from issuer to non-issuer should still work.
2318 AccountOwns gw1{*this, env, "gw1", 0};
2319 env(fset(gw1, asfDefaultRipple));
2320 env.close();
2321
2322 // Use offers to automatically create the trust line.
2323 IOU const OF2 = gw1["OF2"];
2324 env(offer(gw1, XRP(96), OF2(96)));
2325 env.close();
2326 BEAST_EXPECT(
2327 env.le(keylet::line(gw1, alice, OF2.currency)) == nullptr);
2328 env(offer(alice, OF2(96), XRP(96)));
2329 ++alice.owners;
2330 env.close();
2331
2332 // Both offers should be consumed.
2333 // Since gw1's offer was consumed and the trust line was not
2334 // created by gw1, gw1's owner count should still be 0.
2335 gw1.verifyOwners(__LINE__);
2336
2337 // alice's automatically created trust line bumps her owner count.
2338 alice.verifyOwners(__LINE__);
2339
2340 // Use check cashing to automatically create the trust line.
2341 IOU const CK2 = gw1["CK2"];
2342 uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))};
2343 env(check::create(gw1, alice, CK2(96)));
2344 env.close();
2345 BEAST_EXPECT(
2346 env.le(keylet::line(gw1, alice, CK2.currency)) == nullptr);
2347 env(check::cash(alice, chkId, CK2(96)));
2348 ++alice.owners;
2349 verifyDeliveredAmount(env, CK2(96));
2350 env.close();
2351
2352 // gw1's check should be consumed.
2353 // Since gw1's check was consumed and the trust line was not
2354 // created by gw1, gw1's owner count should still be 0.
2355 gw1.verifyOwners(__LINE__);
2356
2357 // alice's automatically created trust line bumps her owner count.
2358 alice.verifyOwners(__LINE__);
2359
2360 cmpTrustLines(gw1, alice, OF2, CK2);
2361 }
2362 //----------- lsfDefaultRipple, check written by non-issuer ------------
2363 {
2364 // gw1 enabled rippling, so automatic trust line from non-issuer
2365 // to non-issuer should work.
2366
2367 // Use offers to automatically create the trust line.
2368 AccountOwns gw1{*this, env, "gw1", 0};
2369 IOU const OF2 = gw1["OF2"];
2370 env(offer(alice, XRP(95), OF2(95)));
2371 env.close();
2372 BEAST_EXPECT(
2373 env.le(keylet::line(alice, bob, OF2.currency)) == nullptr);
2374 env(offer(bob, OF2(95), XRP(95)));
2375 ++bob.owners;
2376 env.close();
2377
2378 // bob's owner count should increase due to the new trust line.
2379 gw1.verifyOwners(__LINE__);
2380 alice.verifyOwners(__LINE__);
2381 bob.verifyOwners(__LINE__);
2382
2383 // Use check cashing to automatically create the trust line.
2384 IOU const CK2 = gw1["CK2"];
2385 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
2386 env(check::create(alice, bob, CK2(95)));
2387 env.close();
2388 BEAST_EXPECT(
2389 env.le(keylet::line(alice, bob, CK2.currency)) == nullptr);
2390 env(check::cash(bob, chkId, CK2(95)));
2391 ++bob.owners;
2392 verifyDeliveredAmount(env, CK2(95));
2393 env.close();
2394
2395 // bob's owner count should increase due to the new trust line.
2396 gw1.verifyOwners(__LINE__);
2397 alice.verifyOwners(__LINE__);
2398 bob.verifyOwners(__LINE__);
2399
2400 cmpTrustLines(alice, bob, OF2, CK2);
2401 }
2402
2403 //-------------- lsfDepositAuth, check written by issuer ---------------
2404 {
2405 // Both offers and checks ignore the lsfDepositAuth flag, since
2406 // the destination signs the transaction that delivers their funds.
2407 // So setting lsfDepositAuth on all the participants should not
2408 // change any outcomes.
2409 //
2410 // Automatic trust line from issuer to non-issuer should still work.
2411 AccountOwns gw1{*this, env, "gw1", 0};
2412 env(fset(gw1, asfDepositAuth));
2413 env(fset(alice, asfDepositAuth));
2414 env(fset(bob, asfDepositAuth));
2415 env.close();
2416
2417 // Use offers to automatically create the trust line.
2418 IOU const OF3 = gw1["OF3"];
2419 env(offer(gw1, XRP(94), OF3(94)));
2420 env.close();
2421 BEAST_EXPECT(
2422 env.le(keylet::line(gw1, alice, OF3.currency)) == nullptr);
2423 env(offer(alice, OF3(94), XRP(94)));
2424 ++alice.owners;
2425 env.close();
2426
2427 // Both offers should be consumed.
2428 // Since gw1's offer was consumed and the trust line was not
2429 // created by gw1, gw1's owner count should still be 0.
2430 gw1.verifyOwners(__LINE__);
2431
2432 // alice's automatically created trust line bumps her owner count.
2433 alice.verifyOwners(__LINE__);
2434
2435 // Use check cashing to automatically create the trust line.
2436 IOU const CK3 = gw1["CK3"];
2437 uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))};
2438 env(check::create(gw1, alice, CK3(94)));
2439 env.close();
2440 BEAST_EXPECT(
2441 env.le(keylet::line(gw1, alice, CK3.currency)) == nullptr);
2442 env(check::cash(alice, chkId, CK3(94)));
2443 ++alice.owners;
2444 verifyDeliveredAmount(env, CK3(94));
2445 env.close();
2446
2447 // gw1's check should be consumed.
2448 // Since gw1's check was consumed and the trust line was not
2449 // created by gw1, gw1's owner count should still be 0.
2450 gw1.verifyOwners(__LINE__);
2451
2452 // alice's automatically created trust line bumps her owner count.
2453 alice.verifyOwners(__LINE__);
2454
2455 cmpTrustLines(gw1, alice, OF3, CK3);
2456 }
2457 //------------ lsfDepositAuth, check written by non-issuer -------------
2458 {
2459 // The presence of the lsfDepositAuth flag should not affect
2460 // automatic trust line creation.
2461
2462 // Use offers to automatically create the trust line.
2463 AccountOwns gw1{*this, env, "gw1", 0};
2464 IOU const OF3 = gw1["OF3"];
2465 env(offer(alice, XRP(93), OF3(93)));
2466 env.close();
2467 BEAST_EXPECT(
2468 env.le(keylet::line(alice, bob, OF3.currency)) == nullptr);
2469 env(offer(bob, OF3(93), XRP(93)));
2470 ++bob.owners;
2471 env.close();
2472
2473 // bob's owner count should increase due to the new trust line.
2474 gw1.verifyOwners(__LINE__);
2475 alice.verifyOwners(__LINE__);
2476 bob.verifyOwners(__LINE__);
2477
2478 // Use check cashing to automatically create the trust line.
2479 IOU const CK3 = gw1["CK3"];
2480 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
2481 env(check::create(alice, bob, CK3(93)));
2482 env.close();
2483 BEAST_EXPECT(
2484 env.le(keylet::line(alice, bob, CK3.currency)) == nullptr);
2485 env(check::cash(bob, chkId, CK3(93)));
2486 ++bob.owners;
2487 verifyDeliveredAmount(env, CK3(93));
2488 env.close();
2489
2490 // bob's owner count should increase due to the new trust line.
2491 gw1.verifyOwners(__LINE__);
2492 alice.verifyOwners(__LINE__);
2493 bob.verifyOwners(__LINE__);
2494
2495 cmpTrustLines(alice, bob, OF3, CK3);
2496 }
2497
2498 //-------------- lsfGlobalFreeze, check written by issuer --------------
2499 {
2500 // Set lsfGlobalFreeze on gw1. That should stop any automatic
2501 // trust lines from being created.
2502 AccountOwns gw1{*this, env, "gw1", 0};
2503 env(fset(gw1, asfGlobalFreeze));
2504 env.close();
2505
2506 // Use offers to automatically create the trust line.
2507 IOU const OF4 = gw1["OF4"];
2508 env(offer(gw1, XRP(92), OF4(92)), ter(tecFROZEN));
2509 env.close();
2510 BEAST_EXPECT(
2511 env.le(keylet::line(gw1, alice, OF4.currency)) == nullptr);
2512 env(offer(alice, OF4(92), XRP(92)), ter(tecFROZEN));
2513 env.close();
2514
2515 // No one's owner count should have changed.
2516 gw1.verifyOwners(__LINE__);
2517 alice.verifyOwners(__LINE__);
2518 bob.verifyOwners(__LINE__);
2519
2520 // Use check cashing to automatically create the trust line.
2521 IOU const CK4 = gw1["CK4"];
2522 uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))};
2523 env(check::create(gw1, alice, CK4(92)), ter(tecFROZEN));
2524 env.close();
2525 BEAST_EXPECT(
2526 env.le(keylet::line(gw1, alice, CK4.currency)) == nullptr);
2527 env(check::cash(alice, chkId, CK4(92)), ter(tecNO_ENTRY));
2528 env.close();
2529
2530 // No one's owner count should have changed.
2531 gw1.verifyOwners(__LINE__);
2532 alice.verifyOwners(__LINE__);
2533 bob.verifyOwners(__LINE__);
2534
2535 // Because gw1 has set lsfGlobalFreeze, neither trust line
2536 // is created.
2537 BEAST_EXPECT(
2538 env.le(keylet::line(gw1, alice, OF4.currency)) == nullptr);
2539 BEAST_EXPECT(
2540 env.le(keylet::line(gw1, alice, CK4.currency)) == nullptr);
2541 }
2542 //------------ lsfGlobalFreeze, check written by non-issuer ------------
2543 {
2544 // Since gw1 has the lsfGlobalFreeze flag set, there should be
2545 // no automatic trust line creation between non-issuers.
2546
2547 // Use offers to automatically create the trust line.
2548 AccountOwns gw1{*this, env, "gw1", 0};
2549 IOU const OF4 = gw1["OF4"];
2550 env(offer(alice, XRP(91), OF4(91)), ter(tecFROZEN));
2551 env.close();
2552 BEAST_EXPECT(
2553 env.le(keylet::line(alice, bob, OF4.currency)) == nullptr);
2554 env(offer(bob, OF4(91), XRP(91)), ter(tecFROZEN));
2555 env.close();
2556
2557 // No one's owner count should have changed.
2558 gw1.verifyOwners(__LINE__);
2559 alice.verifyOwners(__LINE__);
2560 bob.verifyOwners(__LINE__);
2561
2562 // Use check cashing to automatically create the trust line.
2563 IOU const CK4 = gw1["CK4"];
2564 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
2565 env(check::create(alice, bob, CK4(91)), ter(tecFROZEN));
2566 env.close();
2567 BEAST_EXPECT(
2568 env.le(keylet::line(alice, bob, CK4.currency)) == nullptr);
2569 env(check::cash(bob, chkId, CK4(91)), ter(tecNO_ENTRY));
2570 env.close();
2571
2572 // No one's owner count should have changed.
2573 gw1.verifyOwners(__LINE__);
2574 alice.verifyOwners(__LINE__);
2575 bob.verifyOwners(__LINE__);
2576
2577 // Because gw1 has set lsfGlobalFreeze, neither trust line
2578 // is created.
2579 BEAST_EXPECT(
2580 env.le(keylet::line(gw1, bob, OF4.currency)) == nullptr);
2581 BEAST_EXPECT(
2582 env.le(keylet::line(gw1, bob, CK4.currency)) == nullptr);
2583 }
2584
2585 //-------------- lsfRequireAuth, check written by issuer ---------------
2586
2587 // We want to test the lsfRequireAuth flag, but we can't set that
2588 // flag on an account that already has trust lines. So we'll fund
2589 // a new gateway and use that.
2590 {
2591 AccountOwns gw2{*this, env, "gw2", 0};
2592 env.fund(XRP(5000), gw2);
2593 env.close();
2594
2595 // Set lsfRequireAuth on gw2. That should stop any automatic
2596 // trust lines from being created.
2597 env(fset(gw2, asfRequireAuth));
2598 env.close();
2599
2600 // Use offers to automatically create the trust line.
2601 IOU const OF5 = gw2["OF5"];
2602 std::uint32_t gw2OfferSeq = {env.seq(gw2)};
2603 env(offer(gw2, XRP(92), OF5(92)));
2604 ++gw2.owners;
2605 env.close();
2606 BEAST_EXPECT(
2607 env.le(keylet::line(gw2, alice, OF5.currency)) == nullptr);
2608 env(offer(alice, OF5(92), XRP(92)), ter(tecNO_LINE));
2609 env.close();
2610
2611 // gw2 should still own the offer, but no one else's owner
2612 // count should have changed.
2613 gw2.verifyOwners(__LINE__);
2614 alice.verifyOwners(__LINE__);
2615 bob.verifyOwners(__LINE__);
2616
2617 // Since we don't need it any more, remove gw2's offer.
2618 env(offer_cancel(gw2, gw2OfferSeq));
2619 --gw2.owners;
2620 env.close();
2621 gw2.verifyOwners(__LINE__);
2622
2623 // Use check cashing to automatically create the trust line.
2624 IOU const CK5 = gw2["CK5"];
2625 uint256 const chkId{getCheckIndex(gw2, env.seq(gw2))};
2626 env(check::create(gw2, alice, CK5(92)));
2627 ++gw2.owners;
2628 env.close();
2629 BEAST_EXPECT(
2630 env.le(keylet::line(gw2, alice, CK5.currency)) == nullptr);
2631 env(check::cash(alice, chkId, CK5(92)), ter(tecNO_AUTH));
2632 env.close();
2633
2634 // gw2 should still own the check, but no one else's owner
2635 // count should have changed.
2636 gw2.verifyOwners(__LINE__);
2637 alice.verifyOwners(__LINE__);
2638 bob.verifyOwners(__LINE__);
2639
2640 // Because gw2 has set lsfRequireAuth, neither trust line
2641 // is created.
2642 BEAST_EXPECT(
2643 env.le(keylet::line(gw2, alice, OF5.currency)) == nullptr);
2644 BEAST_EXPECT(
2645 env.le(keylet::line(gw2, alice, CK5.currency)) == nullptr);
2646
2647 // Since we don't need it any more, remove gw2's check.
2648 env(check::cancel(gw2, chkId));
2649 --gw2.owners;
2650 env.close();
2651 gw2.verifyOwners(__LINE__);
2652 }
2653 //------------ lsfRequireAuth, check written by non-issuer -------------
2654 {
2655 // Since gw2 has the lsfRequireAuth flag set, there should be
2656 // no automatic trust line creation between non-issuers.
2657
2658 // Use offers to automatically create the trust line.
2659 AccountOwns gw2{*this, env, "gw2", 0};
2660 IOU const OF5 = gw2["OF5"];
2661 env(offer(alice, XRP(91), OF5(91)), ter(tecUNFUNDED_OFFER));
2662 env.close();
2663 env(offer(bob, OF5(91), XRP(91)), ter(tecNO_LINE));
2664 BEAST_EXPECT(
2665 env.le(keylet::line(gw2, bob, OF5.currency)) == nullptr);
2666 env.close();
2667
2668 gw2.verifyOwners(__LINE__);
2669 alice.verifyOwners(__LINE__);
2670 bob.verifyOwners(__LINE__);
2671
2672 // Use check cashing to automatically create the trust line.
2673 IOU const CK5 = gw2["CK5"];
2674 uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
2675 env(check::create(alice, bob, CK5(91)));
2676 env.close();
2677 BEAST_EXPECT(
2678 env.le(keylet::line(alice, bob, CK5.currency)) == nullptr);
2679 env(check::cash(bob, chkId, CK5(91)), ter(tecPATH_PARTIAL));
2680 env.close();
2681
2682 // Delete alice's check since it is no longer needed.
2683 env(check::cancel(alice, chkId));
2684 env.close();
2685
2686 // No one's owner count should have changed.
2687 gw2.verifyOwners(__LINE__);
2688 alice.verifyOwners(__LINE__);
2689 bob.verifyOwners(__LINE__);
2690
2691 // Because gw2 has set lsfRequireAuth, neither trust line
2692 // is created.
2693 BEAST_EXPECT(
2694 env.le(keylet::line(gw2, bob, OF5.currency)) == nullptr);
2695 BEAST_EXPECT(
2696 env.le(keylet::line(gw2, bob, CK5.currency)) == nullptr);
2697 }
2698 }
2699
2700 void
2702 {
2703 testEnabled(features);
2704 testCreateValid(features);
2706 testCreateInvalid(features);
2707 testCashXRP(features);
2708 testCashIOU(features);
2709 testCashXferFee(features);
2710 testCashQuality(features);
2711 testCashInvalid(features);
2712 testCancelValid(features);
2713 testCancelInvalid(features);
2714 testFix1623Enable(features);
2715 testWithTickets(features);
2716 }
2717
2718public:
2719 void
2720 run() override
2721 {
2722 using namespace test::jtx;
2723 auto const sa = supported_amendments();
2724 testWithFeats(sa - featureCheckCashMakesTrustLine);
2726 testWithFeats(sa);
2727
2728 testTrustLineCreation(sa); // Test with featureCheckCashMakesTrustLine
2729 }
2730};
2731
2732BEAST_DEFINE_TESTSUITE(Check, tx, ripple);
2733
2734} // namespace ripple
Represents a JSON value.
Definition: json_value.h:150
Value removeMember(char const *key)
Remove and return the named member.
Definition: json_value.cpp:935
bool isMember(char const *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:962
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)
Definition: Check_test.cpp:694
void testFix1623Enable(FeatureBitset features)
void testWithTickets(FeatureBitset features)
static std::vector< std::shared_ptr< SLE const > > checksOnAccount(test::jtx::Env &env, test::jtx::Account account)
Definition: Check_test.cpp:99
void testCashXRP(FeatureBitset features)
Definition: Check_test.cpp:574
void verifyDeliveredAmount(test::jtx::Env &env, STAmount const &amount)
Definition: Check_test.cpp:117
void testEnabled(FeatureBitset features)
Definition: Check_test.cpp:141
void testCashQuality(FeatureBitset features)
static uint256 getCheckIndex(AccountID const &account, std::uint32_t uSequence)
Definition: Check_test.cpp:92
void testTrustLineCreation(FeatureBitset features)
FeatureBitset const disallowIncoming
Definition: Check_test.cpp:89
void testCreateDisallowIncoming(FeatureBitset features)
Definition: Check_test.cpp:293
void testCreateInvalid(FeatureBitset features)
Definition: Check_test.cpp:388
void testCancelValid(FeatureBitset features)
void testCreateValid(FeatureBitset features)
Definition: Check_test.cpp:193
void run() override
Runs the suite.
void testCashInvalid(FeatureBitset features)
void testWithFeats(FeatureBitset features)
A currency issued by an account.
Definition: Issue.h:36
AccountID account
Definition: Issue.h:39
Json::Value getJson(JsonOptions=JsonOptions::none) const override
Definition: STAmount.cpp:639
int exponent() const noexcept
Definition: STAmount.h:452
void setIssue(Asset const &asset)
Set the Issue for this amount.
Definition: STAmount.cpp:471
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
AccountID id() const
Returns the Account ID.
Definition: Account.h:107
A transaction testing environment.
Definition: Env.h:121
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
Definition: Env.cpp:212
void require(Args const &... args)
Check a set of requirements.
Definition: Env.h:535
std::shared_ptr< STTx const > tx() const
Return the tx data for the last JTx.
Definition: Env.cpp:455
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:117
NetClock::time_point now()
Returns the current network time.
Definition: Env.h:284
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:770
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:233
Converts to IOU Issue or STAmount.
A balance matches.
Definition: balance.h:39
Set DestinationTag on a JTx.
Definition: Check_test.cpp:68
std::uint32_t const tag_
Definition: Check_test.cpp:70
dest_tag(std::uint32_t tag)
Definition: Check_test.cpp:73
void operator()(Env &, JTx &jt) const
Definition: Check_test.cpp:78
Set Expiration on a JTx.
Definition: Check_test.cpp:31
void operator()(Env &, JTx &jt) const
Definition: Check_test.cpp:42
expiration(NetClock::time_point const &expiry)
Definition: Check_test.cpp:36
std::uint32_t const expry_
Definition: Check_test.cpp:33
Set the fee on a JTx.
Definition: fee.h:37
Match set account flags.
Definition: flags.h:125
Set a multisignature on a JTx.
Definition: multisign.h:67
Match the number of items in the account's owner directory.
Definition: owners.h:73
Sets the QualityIn on a trust JTx.
Definition: quality.h:46
Sets the QualityOut on a trust JTx as a percentage.
Definition: quality.h:74
Sets the SendMax on a JTx.
Definition: sendmax.h:33
Set the regular signature on a JTx.
Definition: sig.h:35
Set SourceTag on a JTx.
Definition: Check_test.cpp:50
void operator()(Env &, JTx &jt) const
Definition: Check_test.cpp:60
std::uint32_t const tag_
Definition: Check_test.cpp:52
source_tag(std::uint32_t tag)
Definition: Check_test.cpp:55
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition: ter.h:35
Set a ticket sequence on a JTx.
Definition: ticket.h:48
Set the flags on a JTx.
Definition: txflags.h:31
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:237
Keylet check(AccountID const &id, std::uint32_t seq) noexcept
A Check.
Definition: Indexes.cpp:329
Json::Value create(A const &account, A const &dest, STAmount const &sendMax)
Create a check.
Definition: TestHelpers.h:450
Json::Value cancel(jtx::Account const &dest, uint256 const &checkId)
Cancel a check.
Definition: check.cpp:60
Json::Value cash(jtx::Account const &dest, uint256 const &checkId, STAmount const &amount)
Cash a check requiring that a specific amount be delivered.
Definition: check.cpp:33
Json::Value create(Account const &account, std::uint32_t count)
Create one of more tickets.
Definition: ticket.cpp:31
std::uint32_t ownerCount(Env const &env, Account const &account)
Definition: TestHelpers.cpp:54
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Definition: flags.h:41
Json::Value regkey(Account const &account, disabled_t)
Disable the regular key.
Definition: regkey.cpp:29
Json::Value signers(Account const &account, std::uint32_t quorum, std::vector< signer > const &v)
Definition: multisign.cpp:34
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Definition: trust.cpp:32
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Definition: flags.cpp:29
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Definition: pay.cpp:30
Json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
Definition: rate.cpp:32
std::array< Account, 1+sizeof...(Args)> noripple(Account const &account, Args const &... args)
Designate accounts as no-ripple in Env::fund.
Definition: Env.h:68
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
Definition: offer.cpp:29
owner_count< ltTICKET > tickets
Match the number of tickets on the account.
Definition: ticket.h:64
XRP_t const XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:105
FeatureBitset supported_amendments()
Definition: Env.h:74
Json::Value offer_cancel(Account const &account, std::uint32_t offerSeq)
Cancel an offer.
Definition: offer.cpp:46
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition: AccountID.h:49
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...
Definition: UintTypes.cpp:133
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:98
constexpr std::uint32_t tfSetfAuth
Definition: TxFlags.h:114
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:118
@ tecNO_ENTRY
Definition: TER.h:306
@ tecNO_DST
Definition: TER.h:290
@ tecNO_LINE_INSUF_RESERVE
Definition: TER.h:292
@ tecUNFUNDED_OFFER
Definition: TER.h:284
@ tecFROZEN
Definition: TER.h:303
@ tecNO_PERMISSION
Definition: TER.h:305
@ tecDST_TAG_NEEDED
Definition: TER.h:309
@ tecPATH_PARTIAL
Definition: TER.h:282
@ tecNO_LINE
Definition: TER.h:301
@ tecPATH_DRY
Definition: TER.h:294
@ tecINSUFFICIENT_RESERVE
Definition: TER.h:307
@ tecEXPIRED
Definition: TER.h:314
@ tecNO_AUTH
Definition: TER.h:300
@ tesSUCCESS
Definition: TER.h:244
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 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:117
@ 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:314
Execution context for applying a JSON transaction.
Definition: JTx.h:45
Type used to specify DeliverMin for cashing a check.
Definition: check.h:40