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