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