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