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