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