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