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::const_ref 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 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: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:407
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:734
int exponent() const noexcept
Definition STAmount.h:459
AccountID const & getIssuer() const
Definition STAmount.h:516
std::shared_ptr< STLedgerEntry const > const & const_ref
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:1056
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:338
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:253
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
@ terNO_LINE
Definition TER.h:215
@ terNO_RIPPLE
Definition TER.h:220
TypedField< STAmount > SF_AMOUNT
Definition SField.h:355
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:676
TERSubset< CanCvtToTER > TER
Definition TER.h:647
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:295
@ tecPATH_PARTIAL
Definition TER.h:285
@ tecNO_ENTRY
Definition TER.h:309
@ tecPATH_DRY
Definition TER.h:297
@ tecNO_AUTH
Definition TER.h:303
@ tecFROZEN
Definition TER.h:306
@ tecUNFUNDED_OFFER
Definition TER.h:287
@ tecEXPIRED
Definition TER.h:317
@ tecNO_LINE
Definition TER.h:304
@ tecINSUFFICIENT_RESERVE
Definition TER.h:310
@ tecNO_PERMISSION
Definition TER.h:308
@ tecDST_TAG_NEEDED
Definition TER.h:312
@ tecNO_DST
Definition TER.h:293
std::uint32_t ownerCount(SLE::const_ref 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").
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:580
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, xrpl)
@ tesSUCCESS
Definition TER.h:245
uint256 key
Definition Keylet.h:21