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