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