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