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->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, supported_amendments() - 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};
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};
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};
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};
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  Account const gw{"gateway"};
608  Account const alice{"alice"};
609  Account const bob{"bob"};
610  IOU const USD{gw["USD"]};
611  {
612  // Simple IOU check cashed with Amount (with failures).
613  Env env{*this};
614 
615  env.fund(XRP(1000), gw, alice, bob);
616 
617  // alice writes the check before she gets the funds.
618  uint256 const chkId1{getCheckIndex(alice, env.seq(alice))};
619  env(check::create(alice, bob, USD(10)));
620  env.close();
621 
622  // bob attempts to cash the check. Should fail.
623  env(check::cash(bob, chkId1, USD(10)), ter(tecPATH_PARTIAL));
624  env.close();
625 
626  // alice gets almost enough funds. bob tries and fails again.
627  env(trust(alice, USD(20)));
628  env.close();
629  env(pay(gw, alice, USD(9.5)));
630  env.close();
631  env(check::cash(bob, chkId1, USD(10)), ter(tecPATH_PARTIAL));
632  env.close();
633 
634  // alice gets the last of the necessary funds. bob tries again
635  // and fails because he hasn't got a trust line for USD.
636  env(pay(gw, alice, USD(0.5)));
637  env.close();
638  env(check::cash(bob, chkId1, USD(10)), ter(tecNO_LINE));
639  env.close();
640 
641  // bob sets up the trust line, but not at a high enough limit.
642  env(trust(bob, USD(9.5)));
643  env.close();
644  env(check::cash(bob, chkId1, USD(10)), ter(tecPATH_PARTIAL));
645  env.close();
646 
647  // bob sets the trust line limit high enough but asks for more
648  // than the check's SendMax.
649  env(trust(bob, USD(10.5)));
650  env.close();
651  env(check::cash(bob, chkId1, USD(10.5)), ter(tecPATH_PARTIAL));
652  env.close();
653 
654  // bob asks for exactly the check amount and the check clears.
655  env(check::cash(bob, chkId1, USD(10)));
656  env.close();
657  env.require(balance(alice, USD(0)));
658  env.require(balance(bob, USD(10)));
659  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
660  BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
661  BEAST_EXPECT(ownerCount(env, alice) == 1);
662  BEAST_EXPECT(ownerCount(env, bob) == 1);
663 
664  // bob tries to cash the same check again, which fails.
665  env(check::cash(bob, chkId1, USD(10)), ter(tecNO_ENTRY));
666  env.close();
667 
668  // bob pays alice USD(7) so he can try another case.
669  env(pay(bob, alice, USD(7)));
670  env.close();
671 
672  uint256 const chkId2{getCheckIndex(alice, env.seq(alice))};
673  env(check::create(alice, bob, USD(7)));
674  env.close();
675  BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
676  BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
677 
678  // bob cashes the check for less than the face amount. That works,
679  // consumes the check, and bob receives as much as he asked for.
680  env(check::cash(bob, chkId2, USD(5)));
681  env.close();
682  env.require(balance(alice, USD(2)));
683  env.require(balance(bob, USD(8)));
684  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
685  BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
686  BEAST_EXPECT(ownerCount(env, alice) == 1);
687  BEAST_EXPECT(ownerCount(env, bob) == 1);
688 
689  // alice writes two checks for USD(2), although she only has USD(2).
690  uint256 const chkId3{getCheckIndex(alice, env.seq(alice))};
691  env(check::create(alice, bob, USD(2)));
692  env.close();
693  uint256 const chkId4{getCheckIndex(alice, env.seq(alice))};
694  env(check::create(alice, bob, USD(2)));
695  env.close();
696  BEAST_EXPECT(checksOnAccount(env, alice).size() == 2);
697  BEAST_EXPECT(checksOnAccount(env, bob).size() == 2);
698 
699  // bob cashes the second check for the face amount.
700  env(check::cash(bob, chkId4, USD(2)));
701  env.close();
702  env.require(balance(alice, USD(0)));
703  env.require(balance(bob, USD(10)));
704  BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
705  BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
706  BEAST_EXPECT(ownerCount(env, alice) == 2);
707  BEAST_EXPECT(ownerCount(env, bob) == 1);
708 
709  // bob is not allowed to cash the last check for USD(0), he must
710  // use check::cancel instead.
711  env(check::cash(bob, chkId3, USD(0)), ter(temBAD_AMOUNT));
712  env.close();
713  env.require(balance(alice, USD(0)));
714  env.require(balance(bob, USD(10)));
715  BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
716  BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
717  BEAST_EXPECT(ownerCount(env, alice) == 2);
718  BEAST_EXPECT(ownerCount(env, bob) == 1);
719 
720  // ... so bob cancels alice's remaining check.
721  env(check::cancel(bob, chkId3));
722  env.close();
723  env.require(balance(alice, USD(0)));
724  env.require(balance(bob, USD(10)));
725  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
726  BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
727  BEAST_EXPECT(ownerCount(env, alice) == 1);
728  BEAST_EXPECT(ownerCount(env, bob) == 1);
729  }
730  {
731  // Simple IOU check cashed with DeliverMin (with failures).
732  Env env{*this};
733 
734  env.fund(XRP(1000), gw, alice, bob);
735 
736  env(trust(alice, USD(20)));
737  env(trust(bob, USD(20)));
738  env.close();
739  env(pay(gw, alice, USD(8)));
740  env.close();
741 
742  // alice creates several checks ahead of time.
743  uint256 const chkId9{getCheckIndex(alice, env.seq(alice))};
744  env(check::create(alice, bob, USD(9)));
745  env.close();
746  uint256 const chkId8{getCheckIndex(alice, env.seq(alice))};
747  env(check::create(alice, bob, USD(8)));
748  env.close();
749  uint256 const chkId7{getCheckIndex(alice, env.seq(alice))};
750  env(check::create(alice, bob, USD(7)));
751  env.close();
752  uint256 const chkId6{getCheckIndex(alice, env.seq(alice))};
753  env(check::create(alice, bob, USD(6)));
754  env.close();
755 
756  // bob attempts to cash a check for the amount on the check.
757  // Should fail, since alice doesn't have the funds.
758  env(check::cash(bob, chkId9, check::DeliverMin(USD(9))),
759  ter(tecPATH_PARTIAL));
760  env.close();
761 
762  // bob sets a DeliverMin of 7 and gets all that alice has.
763  env(check::cash(bob, chkId9, check::DeliverMin(USD(7))));
764  verifyDeliveredAmount(env, USD(8));
765  env.require(balance(alice, USD(0)));
766  env.require(balance(bob, USD(8)));
767  BEAST_EXPECT(checksOnAccount(env, alice).size() == 3);
768  BEAST_EXPECT(checksOnAccount(env, bob).size() == 3);
769  BEAST_EXPECT(ownerCount(env, alice) == 4);
770  BEAST_EXPECT(ownerCount(env, bob) == 1);
771 
772  // bob pays alice USD(7) so he can use another check.
773  env(pay(bob, alice, USD(7)));
774  env.close();
775 
776  // Using DeliverMin for the SendMax value of the check (and no
777  // transfer fees) should work just like setting Amount.
778  env(check::cash(bob, chkId7, check::DeliverMin(USD(7))));
779  verifyDeliveredAmount(env, USD(7));
780  env.require(balance(alice, USD(0)));
781  env.require(balance(bob, USD(8)));
782  BEAST_EXPECT(checksOnAccount(env, alice).size() == 2);
783  BEAST_EXPECT(checksOnAccount(env, bob).size() == 2);
784  BEAST_EXPECT(ownerCount(env, alice) == 3);
785  BEAST_EXPECT(ownerCount(env, bob) == 1);
786 
787  // bob pays alice USD(8) so he can use the last two checks.
788  env(pay(bob, alice, USD(8)));
789  env.close();
790 
791  // alice has USD(8). If bob uses the check for USD(6) and uses a
792  // DeliverMin of 4, he should get the SendMax value of the check.
793  env(check::cash(bob, chkId6, check::DeliverMin(USD(4))));
794  verifyDeliveredAmount(env, USD(6));
795  env.require(balance(alice, USD(2)));
796  env.require(balance(bob, USD(6)));
797  BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
798  BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
799  BEAST_EXPECT(ownerCount(env, alice) == 2);
800  BEAST_EXPECT(ownerCount(env, bob) == 1);
801 
802  // bob cashes the last remaining check setting a DeliverMin.
803  // of exactly alice's remaining USD.
804  env(check::cash(bob, chkId8, check::DeliverMin(USD(2))));
805  verifyDeliveredAmount(env, USD(2));
806  env.require(balance(alice, USD(0)));
807  env.require(balance(bob, USD(8)));
808  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
809  BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
810  BEAST_EXPECT(ownerCount(env, alice) == 1);
811  BEAST_EXPECT(ownerCount(env, bob) == 1);
812  }
813  {
814  // Examine the effects of the asfRequireAuth flag.
815  Env env{*this};
816 
817  env.fund(XRP(1000), gw, alice, bob);
818  env(fset(gw, asfRequireAuth));
819  env.close();
820  env(trust(gw, alice["USD"](100)), txflags(tfSetfAuth));
821  env(trust(alice, USD(20)));
822  env.close();
823  env(pay(gw, alice, USD(8)));
824  env.close();
825 
826  // alice writes a check to bob for USD. bob can't cash it
827  // because he is not authorized to hold gw["USD"].
828  uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
829  env(check::create(alice, bob, USD(7)));
830  env.close();
831 
832  env(check::cash(bob, chkId, USD(7)), ter(tecNO_LINE));
833  env.close();
834 
835  // Now give bob a trustline for USD. bob still can't cash the
836  // check because he is not authorized.
837  env(trust(bob, USD(5)));
838  env.close();
839 
840  env(check::cash(bob, chkId, USD(7)), ter(tecNO_AUTH));
841  env.close();
842 
843  // bob gets authorization to hold gw["USD"].
844  env(trust(gw, bob["USD"](1)), txflags(tfSetfAuth));
845  env.close();
846 
847  // bob tries to cash the check again but fails because his trust
848  // limit is too low.
849  env(check::cash(bob, chkId, USD(7)), ter(tecPATH_PARTIAL));
850  env.close();
851 
852  // Since bob set his limit low, he cashes the check with a
853  // DeliverMin and hits his trust limit.
854  env(check::cash(bob, chkId, check::DeliverMin(USD(4))));
855  verifyDeliveredAmount(env, USD(5));
856  env.require(balance(alice, USD(3)));
857  env.require(balance(bob, USD(5)));
858  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
859  BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
860  BEAST_EXPECT(ownerCount(env, alice) == 1);
861  BEAST_EXPECT(ownerCount(env, bob) == 1);
862  }
863 
864  // Use a regular key and also multisign to cash a check.
865  // featureMultiSignReserve changes the reserve on a SignerList, so
866  // check both before and after.
867  FeatureBitset const allSupported{supported_amendments()};
868  for (auto const features :
869  {allSupported - featureMultiSignReserve,
870  allSupported | featureMultiSignReserve})
871  {
872  Env env{*this, features};
873 
874  env.fund(XRP(1000), gw, alice, bob);
875 
876  // alice creates her checks ahead of time.
877  uint256 const chkId1{getCheckIndex(alice, env.seq(alice))};
878  env(check::create(alice, bob, USD(1)));
879  env.close();
880 
881  uint256 const chkId2{getCheckIndex(alice, env.seq(alice))};
882  env(check::create(alice, bob, USD(2)));
883  env.close();
884 
885  env(trust(alice, USD(20)));
886  env(trust(bob, USD(20)));
887  env.close();
888  env(pay(gw, alice, USD(8)));
889  env.close();
890 
891  // Give bob a regular key and signers
892  Account const bobby{"bobby", KeyType::secp256k1};
893  env(regkey(bob, bobby));
894  env.close();
895 
896  Account const bogie{"bogie", KeyType::secp256k1};
897  Account const demon{"demon", KeyType::ed25519};
898  env(signers(bob, 2, {{bogie, 1}, {demon, 1}}), sig(bobby));
899  env.close();
900 
901  // If featureMultiSignReserve is enabled then bob's signer list
902  // has an owner count of 1, otherwise it's 4.
903  int const signersCount{features[featureMultiSignReserve] ? 1 : 4};
904  BEAST_EXPECT(ownerCount(env, bob) == signersCount + 1);
905 
906  // bob uses his regular key to cash a check.
907  env(check::cash(bob, chkId1, (USD(1))), sig(bobby));
908  env.close();
909  env.require(balance(alice, USD(7)));
910  env.require(balance(bob, USD(1)));
911  BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
912  BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
913  BEAST_EXPECT(ownerCount(env, alice) == 2);
914  BEAST_EXPECT(ownerCount(env, bob) == signersCount + 1);
915 
916  // bob uses multisigning to cash a check.
917  XRPAmount const baseFeeDrops{env.current()->fees().base};
918  env(check::cash(bob, chkId2, (USD(2))),
919  msig(bogie, demon),
920  fee(3 * baseFeeDrops));
921  env.close();
922  env.require(balance(alice, USD(5)));
923  env.require(balance(bob, USD(3)));
924  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
925  BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
926  BEAST_EXPECT(ownerCount(env, alice) == 1);
927  BEAST_EXPECT(ownerCount(env, bob) == signersCount + 1);
928  }
929  }
930 
931  void
933  {
934  // Look at behavior when the issuer charges a transfer fee.
935  testcase("Cash with transfer fee");
936 
937  using namespace test::jtx;
938 
939  Account const gw{"gateway"};
940  Account const alice{"alice"};
941  Account const bob{"bob"};
942  IOU const USD{gw["USD"]};
943 
944  Env env{*this};
945 
946  env.fund(XRP(1000), gw, alice, bob);
947 
948  env(trust(alice, USD(1000)));
949  env(trust(bob, USD(1000)));
950  env.close();
951  env(pay(gw, alice, USD(1000)));
952  env.close();
953 
954  // Set gw's transfer rate and see the consequences when cashing a check.
955  env(rate(gw, 1.25));
956  env.close();
957 
958  // alice writes a check with a SendMax of USD(125). The most bob
959  // can get is USD(100) because of the transfer rate.
960  uint256 const chkId125{getCheckIndex(alice, env.seq(alice))};
961  env(check::create(alice, bob, USD(125)));
962  env.close();
963 
964  // alice writes another check that won't get cashed until the transfer
965  // rate changes so we can see the rate applies when the check is
966  // cashed, not when it is created.
967  uint256 const chkId120{getCheckIndex(alice, env.seq(alice))};
968  env(check::create(alice, bob, USD(120)));
969  env.close();
970 
971  // bob attempts to cash the check for face value. Should fail.
972  env(check::cash(bob, chkId125, USD(125)), ter(tecPATH_PARTIAL));
973  env.close();
974  env(check::cash(bob, chkId125, check::DeliverMin(USD(101))),
975  ter(tecPATH_PARTIAL));
976  env.close();
977 
978  // bob decides that he'll accept anything USD(75) or up.
979  // He gets USD(100).
980  env(check::cash(bob, chkId125, check::DeliverMin(USD(75))));
981  verifyDeliveredAmount(env, USD(100));
982  env.require(balance(alice, USD(1000 - 125)));
983  env.require(balance(bob, USD(0 + 100)));
984  BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
985  BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
986 
987  // Adjust gw's rate...
988  env(rate(gw, 1.2));
989  env.close();
990 
991  // bob cashes the second check for less than the face value. The new
992  // rate applies to the actual value transferred.
993  env(check::cash(bob, chkId120, USD(50)));
994  env.close();
995  env.require(balance(alice, USD(1000 - 125 - 60)));
996  env.require(balance(bob, USD(0 + 100 + 50)));
997  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
998  BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
999  }
1000 
1001  void
1003  {
1004  // Look at the eight possible cases for Quality In/Out.
1005  testcase("Cash quality");
1006 
1007  using namespace test::jtx;
1008 
1009  Account const gw{"gateway"};
1010  Account const alice{"alice"};
1011  Account const bob{"bob"};
1012  IOU const USD{gw["USD"]};
1013 
1014  Env env{*this};
1015 
1016  env.fund(XRP(1000), gw, alice, bob);
1017 
1018  env(trust(alice, USD(1000)));
1019  env(trust(bob, USD(1000)));
1020  env.close();
1021  env(pay(gw, alice, USD(1000)));
1022  env.close();
1023 
1024  //
1025  // Quality effects on transfers between two non-issuers.
1026  //
1027 
1028  // Provide lambdas that return a qualityInPercent and qualityOutPercent.
1029  auto qIn = [](double percent) { return qualityInPercent(percent); };
1030  auto qOut = [](double percent) { return qualityOutPercent(percent); };
1031 
1032  // There are two test lambdas: one for a Payment and one for a Check.
1033  // This shows whether a Payment and a Check behave the same.
1034  auto testNonIssuerQPay = [&env, &alice, &bob, &USD](
1035  Account const& truster,
1036  IOU const& iou,
1037  auto const& inOrOut,
1038  double pct,
1039  double amount) {
1040  // Capture bob's and alice's balances so we can test at the end.
1041  STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1042  STAmount const bobStart{env.balance(bob, USD.issue()).value()};
1043 
1044  // Set the modified quality.
1045  env(trust(truster, iou(1000)), inOrOut(pct));
1046  env.close();
1047 
1048  env(pay(alice, bob, USD(amount)), sendmax(USD(10)));
1049  env.close();
1050  env.require(balance(alice, aliceStart - USD(10)));
1051  env.require(balance(bob, bobStart + USD(10)));
1052 
1053  // Return the quality to the unmodified state so it doesn't
1054  // interfere with upcoming tests.
1055  env(trust(truster, iou(1000)), inOrOut(0));
1056  env.close();
1057  };
1058 
1059  auto testNonIssuerQCheck = [&env, &alice, &bob, &USD](
1060  Account const& truster,
1061  IOU const& iou,
1062  auto const& inOrOut,
1063  double pct,
1064  double amount) {
1065  // Capture bob's and alice's balances so we can test at the end.
1066  STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1067  STAmount const bobStart{env.balance(bob, USD.issue()).value()};
1068 
1069  // Set the modified quality.
1070  env(trust(truster, iou(1000)), inOrOut(pct));
1071  env.close();
1072 
1073  uint256 const chkId = getCheckIndex(alice, env.seq(alice));
1074  env(check::create(alice, bob, USD(10)));
1075  env.close();
1076 
1077  env(check::cash(bob, chkId, USD(amount)));
1078  env.close();
1079  env.require(balance(alice, aliceStart - USD(10)));
1080  env.require(balance(bob, bobStart + USD(10)));
1081 
1082  // Return the quality to the unmodified state so it doesn't
1083  // interfere with upcoming tests.
1084  env(trust(truster, iou(1000)), inOrOut(0));
1085  env.close();
1086  };
1087 
1088  // pct amount
1089  testNonIssuerQPay(alice, gw["USD"], qIn, 50, 10);
1090  testNonIssuerQCheck(alice, gw["USD"], qIn, 50, 10);
1091 
1092  // This is the only case where the Quality affects the outcome.
1093  testNonIssuerQPay(bob, gw["USD"], qIn, 50, 5);
1094  testNonIssuerQCheck(bob, gw["USD"], qIn, 50, 5);
1095 
1096  testNonIssuerQPay(gw, alice["USD"], qIn, 50, 10);
1097  testNonIssuerQCheck(gw, alice["USD"], qIn, 50, 10);
1098 
1099  testNonIssuerQPay(gw, bob["USD"], qIn, 50, 10);
1100  testNonIssuerQCheck(gw, bob["USD"], qIn, 50, 10);
1101 
1102  testNonIssuerQPay(alice, gw["USD"], qOut, 200, 10);
1103  testNonIssuerQCheck(alice, gw["USD"], qOut, 200, 10);
1104 
1105  testNonIssuerQPay(bob, gw["USD"], qOut, 200, 10);
1106  testNonIssuerQCheck(bob, gw["USD"], qOut, 200, 10);
1107 
1108  testNonIssuerQPay(gw, alice["USD"], qOut, 200, 10);
1109  testNonIssuerQCheck(gw, alice["USD"], qOut, 200, 10);
1110 
1111  testNonIssuerQPay(gw, bob["USD"], qOut, 200, 10);
1112  testNonIssuerQCheck(gw, bob["USD"], qOut, 200, 10);
1113 
1114  //
1115  // Quality effects on transfers between an issuer and a non-issuer.
1116  //
1117 
1118  // There are two test lambdas for the same reason as before.
1119  auto testIssuerQPay = [&env, &gw, &alice, &USD](
1120  Account const& truster,
1121  IOU const& iou,
1122  auto const& inOrOut,
1123  double pct,
1124  double amt1,
1125  double max1,
1126  double amt2,
1127  double max2) {
1128  // Capture alice's balance so we can test at the end. It doesn't
1129  // make any sense to look at the balance of a gateway.
1130  STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1131 
1132  // Set the modified quality.
1133  env(trust(truster, iou(1000)), inOrOut(pct));
1134  env.close();
1135 
1136  // alice pays gw.
1137  env(pay(alice, gw, USD(amt1)), sendmax(USD(max1)));
1138  env.close();
1139  env.require(balance(alice, aliceStart - USD(10)));
1140 
1141  // gw pays alice.
1142  env(pay(gw, alice, USD(amt2)), sendmax(USD(max2)));
1143  env.close();
1144  env.require(balance(alice, aliceStart));
1145 
1146  // Return the quality to the unmodified state so it doesn't
1147  // interfere with upcoming tests.
1148  env(trust(truster, iou(1000)), inOrOut(0));
1149  env.close();
1150  };
1151 
1152  auto testIssuerQCheck = [&env, &gw, &alice, &USD](
1153  Account const& truster,
1154  IOU const& iou,
1155  auto const& inOrOut,
1156  double pct,
1157  double amt1,
1158  double max1,
1159  double amt2,
1160  double max2) {
1161  // Capture alice's balance so we can test at the end. It doesn't
1162  // make any sense to look at the balance of the issuer.
1163  STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1164 
1165  // Set the modified quality.
1166  env(trust(truster, iou(1000)), inOrOut(pct));
1167  env.close();
1168 
1169  // alice writes check to gw. gw cashes.
1170  uint256 const chkAliceId{getCheckIndex(alice, env.seq(alice))};
1171  env(check::create(alice, gw, USD(max1)));
1172  env.close();
1173 
1174  env(check::cash(gw, chkAliceId, USD(amt1)));
1175  env.close();
1176  env.require(balance(alice, aliceStart - USD(10)));
1177 
1178  // gw writes check to alice. alice cashes.
1179  uint256 const chkGwId{getCheckIndex(gw, env.seq(gw))};
1180  env(check::create(gw, alice, USD(max2)));
1181  env.close();
1182 
1183  env(check::cash(alice, chkGwId, USD(amt2)));
1184  env.close();
1185  env.require(balance(alice, aliceStart));
1186 
1187  // Return the quality to the unmodified state so it doesn't
1188  // interfere with upcoming tests.
1189  env(trust(truster, iou(1000)), inOrOut(0));
1190  env.close();
1191  };
1192 
1193  // The first case is the only one where the quality affects the outcome.
1194  // pct amt1 max1 amt2 max2
1195  testIssuerQPay(alice, gw["USD"], qIn, 50, 10, 10, 5, 10);
1196  testIssuerQCheck(alice, gw["USD"], qIn, 50, 10, 10, 5, 10);
1197 
1198  testIssuerQPay(gw, alice["USD"], qIn, 50, 10, 10, 10, 10);
1199  testIssuerQCheck(gw, alice["USD"], qIn, 50, 10, 10, 10, 10);
1200 
1201  testIssuerQPay(alice, gw["USD"], qOut, 200, 10, 10, 10, 10);
1202  testIssuerQCheck(alice, gw["USD"], qOut, 200, 10, 10, 10, 10);
1203 
1204  testIssuerQPay(gw, alice["USD"], qOut, 200, 10, 10, 10, 10);
1205  testIssuerQCheck(gw, alice["USD"], qOut, 200, 10, 10, 10, 10);
1206  }
1207 
1208  void
1210  {
1211  // Explore many of the ways to fail at cashing a check.
1212  testcase("Cash invalid");
1213 
1214  using namespace test::jtx;
1215 
1216  Account const gw{"gateway"};
1217  Account const alice{"alice"};
1218  Account const bob{"bob"};
1219  Account const zoe{"zoe"};
1220  IOU const USD{gw["USD"]};
1221 
1222  Env env{*this};
1223 
1224  env.fund(XRP(1000), gw, alice, bob, zoe);
1225 
1226  // Now set up alice's trustline.
1227  env(trust(alice, USD(20)));
1228  env.close();
1229  env(pay(gw, alice, USD(20)));
1230  env.close();
1231 
1232  // Before bob gets a trustline, have him try to cash a check.
1233  // Should fail.
1234  {
1235  uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
1236  env(check::create(alice, bob, USD(20)));
1237  env.close();
1238 
1239  env(check::cash(bob, chkId, USD(20)), ter(tecNO_LINE));
1240  env.close();
1241  }
1242 
1243  // Now set up bob's trustline.
1244  env(trust(bob, USD(20)));
1245  env.close();
1246 
1247  // bob tries to cash a non-existent check from alice.
1248  {
1249  uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
1250  env(check::cash(bob, chkId, USD(20)), ter(tecNO_ENTRY));
1251  env.close();
1252  }
1253 
1254  // alice creates her checks ahead of time.
1255  uint256 const chkIdU{getCheckIndex(alice, env.seq(alice))};
1256  env(check::create(alice, bob, USD(20)));
1257  env.close();
1258 
1259  uint256 const chkIdX{getCheckIndex(alice, env.seq(alice))};
1260  env(check::create(alice, bob, XRP(10)));
1261  env.close();
1262 
1263  using namespace std::chrono_literals;
1264  uint256 const chkIdExp{getCheckIndex(alice, env.seq(alice))};
1265  env(check::create(alice, bob, XRP(10)), expiration(env.now() + 1s));
1266  env.close();
1267 
1268  uint256 const chkIdFroz1{getCheckIndex(alice, env.seq(alice))};
1269  env(check::create(alice, bob, USD(1)));
1270  env.close();
1271 
1272  uint256 const chkIdFroz2{getCheckIndex(alice, env.seq(alice))};
1273  env(check::create(alice, bob, USD(2)));
1274  env.close();
1275 
1276  uint256 const chkIdFroz3{getCheckIndex(alice, env.seq(alice))};
1277  env(check::create(alice, bob, USD(3)));
1278  env.close();
1279 
1280  uint256 const chkIdFroz4{getCheckIndex(alice, env.seq(alice))};
1281  env(check::create(alice, bob, USD(4)));
1282  env.close();
1283 
1284  uint256 const chkIdNoDest1{getCheckIndex(alice, env.seq(alice))};
1285  env(check::create(alice, bob, USD(1)));
1286  env.close();
1287 
1288  uint256 const chkIdHasDest2{getCheckIndex(alice, env.seq(alice))};
1289  env(check::create(alice, bob, USD(2)), dest_tag(7));
1290  env.close();
1291 
1292  // Same set of failing cases for both IOU and XRP check cashing.
1293  auto failingCases = [&env, &gw, &alice, &bob](
1294  uint256 const& chkId, STAmount const& amount) {
1295  // Bad fee.
1296  env(check::cash(bob, chkId, amount),
1297  fee(drops(-10)),
1298  ter(temBAD_FEE));
1299  env.close();
1300 
1301  // Bad flags.
1302  env(check::cash(bob, chkId, amount),
1303  txflags(tfImmediateOrCancel),
1304  ter(temINVALID_FLAG));
1305  env.close();
1306 
1307  // Missing both Amount and DeliverMin.
1308  {
1309  Json::Value tx{check::cash(bob, chkId, amount)};
1311  env(tx, ter(temMALFORMED));
1312  env.close();
1313  }
1314  // Both Amount and DeliverMin present.
1315  {
1316  Json::Value tx{check::cash(bob, chkId, amount)};
1317  tx[sfDeliverMin.jsonName] = amount.getJson(JsonOptions::none);
1318  env(tx, ter(temMALFORMED));
1319  env.close();
1320  }
1321 
1322  // Negative or zero amount.
1323  {
1324  STAmount neg{amount};
1325  neg.negate();
1326  env(check::cash(bob, chkId, neg), ter(temBAD_AMOUNT));
1327  env.close();
1328  env(check::cash(bob, chkId, amount.zeroed()),
1329  ter(temBAD_AMOUNT));
1330  env.close();
1331  }
1332 
1333  // Bad currency.
1334  if (!amount.native())
1335  {
1336  Issue const badIssue{badCurrency(), amount.getIssuer()};
1337  STAmount badAmount{amount};
1338  badAmount.setIssue(Issue{badCurrency(), amount.getIssuer()});
1339  env(check::cash(bob, chkId, badAmount), ter(temBAD_CURRENCY));
1340  env.close();
1341  }
1342 
1343  // Not destination cashing check.
1344  env(check::cash(alice, chkId, amount), ter(tecNO_PERMISSION));
1345  env.close();
1346  env(check::cash(gw, chkId, amount), ter(tecNO_PERMISSION));
1347  env.close();
1348 
1349  // Currency mismatch.
1350  {
1351  IOU const wrongCurrency{gw["EUR"]};
1352  STAmount badAmount{amount};
1353  badAmount.setIssue(wrongCurrency.issue());
1354  env(check::cash(bob, chkId, badAmount), ter(temMALFORMED));
1355  env.close();
1356  }
1357 
1358  // Issuer mismatch.
1359  {
1360  IOU const wrongIssuer{alice["USD"]};
1361  STAmount badAmount{amount};
1362  badAmount.setIssue(wrongIssuer.issue());
1363  env(check::cash(bob, chkId, badAmount), ter(temMALFORMED));
1364  env.close();
1365  }
1366 
1367  // Amount bigger than SendMax.
1368  env(check::cash(bob, chkId, amount + amount), ter(tecPATH_PARTIAL));
1369  env.close();
1370 
1371  // DeliverMin bigger than SendMax.
1372  env(check::cash(bob, chkId, check::DeliverMin(amount + amount)),
1373  ter(tecPATH_PARTIAL));
1374  env.close();
1375  };
1376 
1377  failingCases(chkIdX, XRP(10));
1378  failingCases(chkIdU, USD(20));
1379 
1380  // Verify that those two checks really were cashable.
1381  env(check::cash(bob, chkIdU, USD(20)));
1382  env.close();
1383  env(check::cash(bob, chkIdX, check::DeliverMin(XRP(10))));
1384  verifyDeliveredAmount(env, XRP(10));
1385 
1386  // Try to cash an expired check.
1387  env(check::cash(bob, chkIdExp, XRP(10)), ter(tecEXPIRED));
1388  env.close();
1389 
1390  // Cancel the expired check. Anyone can cancel an expired check.
1391  env(check::cancel(zoe, chkIdExp));
1392  env.close();
1393 
1394  // Can we cash a check with frozen currency?
1395  {
1396  env(pay(bob, alice, USD(20)));
1397  env.close();
1398  env.require(balance(alice, USD(20)));
1399  env.require(balance(bob, USD(0)));
1400 
1401  // Global freeze
1402  env(fset(gw, asfGlobalFreeze));
1403  env.close();
1404 
1405  env(check::cash(bob, chkIdFroz1, USD(1)), ter(tecPATH_PARTIAL));
1406  env.close();
1407  env(check::cash(bob, chkIdFroz1, check::DeliverMin(USD(0.5))),
1408  ter(tecPATH_PARTIAL));
1409  env.close();
1410 
1411  env(fclear(gw, asfGlobalFreeze));
1412  env.close();
1413 
1414  // No longer frozen. Success.
1415  env(check::cash(bob, chkIdFroz1, USD(1)));
1416  env.close();
1417  env.require(balance(alice, USD(19)));
1418  env.require(balance(bob, USD(1)));
1419 
1420  // Freeze individual trustlines.
1421  env(trust(gw, alice["USD"](0), tfSetFreeze));
1422  env.close();
1423  env(check::cash(bob, chkIdFroz2, USD(2)), ter(tecPATH_PARTIAL));
1424  env.close();
1425  env(check::cash(bob, chkIdFroz2, check::DeliverMin(USD(1))),
1426  ter(tecPATH_PARTIAL));
1427  env.close();
1428 
1429  // Clear that freeze. Now check cashing works.
1430  env(trust(gw, alice["USD"](0), tfClearFreeze));
1431  env.close();
1432  env(check::cash(bob, chkIdFroz2, USD(2)));
1433  env.close();
1434  env.require(balance(alice, USD(17)));
1435  env.require(balance(bob, USD(3)));
1436 
1437  // Freeze bob's trustline. bob can't cash the check.
1438  env(trust(gw, bob["USD"](0), tfSetFreeze));
1439  env.close();
1440  env(check::cash(bob, chkIdFroz3, USD(3)), ter(tecFROZEN));
1441  env.close();
1442  env(check::cash(bob, chkIdFroz3, check::DeliverMin(USD(1))),
1443  ter(tecFROZEN));
1444  env.close();
1445 
1446  // Clear that freeze. Now check cashing works again.
1447  env(trust(gw, bob["USD"](0), tfClearFreeze));
1448  env.close();
1449  env(check::cash(bob, chkIdFroz3, check::DeliverMin(USD(1))));
1450  verifyDeliveredAmount(env, USD(3));
1451  env.require(balance(alice, USD(14)));
1452  env.require(balance(bob, USD(6)));
1453 
1454  // Set bob's freeze bit in the other direction. Check
1455  // cashing fails.
1456  env(trust(bob, USD(20), tfSetFreeze));
1457  env.close();
1458  env(check::cash(bob, chkIdFroz4, USD(4)), ter(terNO_LINE));
1459  env.close();
1460  env(check::cash(bob, chkIdFroz4, check::DeliverMin(USD(1))),
1461  ter(terNO_LINE));
1462  env.close();
1463 
1464  // Clear bob's freeze bit and the check should be cashable.
1465  env(trust(bob, USD(20), tfClearFreeze));
1466  env.close();
1467  env(check::cash(bob, chkIdFroz4, USD(4)));
1468  env.close();
1469  env.require(balance(alice, USD(10)));
1470  env.require(balance(bob, USD(10)));
1471  }
1472  {
1473  // Set the RequireDest flag on bob's account (after the check
1474  // was created) then cash a check without a destination tag.
1475  env(fset(bob, asfRequireDest));
1476  env.close();
1477  env(check::cash(bob, chkIdNoDest1, USD(1)), ter(tecDST_TAG_NEEDED));
1478  env.close();
1479  env(check::cash(bob, chkIdNoDest1, check::DeliverMin(USD(0.5))),
1480  ter(tecDST_TAG_NEEDED));
1481  env.close();
1482 
1483  // bob can cash a check with a destination tag.
1484  env(check::cash(bob, chkIdHasDest2, USD(2)));
1485  env.close();
1486  env.require(balance(alice, USD(8)));
1487  env.require(balance(bob, USD(12)));
1488 
1489  // Clear the RequireDest flag on bob's account so he can
1490  // cash the check with no DestinationTag.
1491  env(fclear(bob, asfRequireDest));
1492  env.close();
1493  env(check::cash(bob, chkIdNoDest1, USD(1)));
1494  env.close();
1495  env.require(balance(alice, USD(7)));
1496  env.require(balance(bob, USD(13)));
1497  }
1498  }
1499 
1500  void
1502  {
1503  // Explore many of the ways to cancel a check.
1504  testcase("Cancel valid");
1505 
1506  using namespace test::jtx;
1507 
1508  Account const gw{"gateway"};
1509  Account const alice{"alice"};
1510  Account const bob{"bob"};
1511  Account const zoe{"zoe"};
1512  IOU const USD{gw["USD"]};
1513 
1514  // featureMultiSignReserve changes the reserve on a SignerList, so
1515  // check both before and after.
1516  FeatureBitset const allSupported{supported_amendments()};
1517  for (auto const features :
1518  {allSupported - featureMultiSignReserve,
1519  allSupported | featureMultiSignReserve})
1520  {
1521  Env env{*this, features};
1522 
1523  env.fund(XRP(1000), gw, alice, bob, zoe);
1524 
1525  // alice creates her checks ahead of time.
1526  // Three ordinary checks with no expiration.
1527  uint256 const chkId1{getCheckIndex(alice, env.seq(alice))};
1528  env(check::create(alice, bob, USD(10)));
1529  env.close();
1530 
1531  uint256 const chkId2{getCheckIndex(alice, env.seq(alice))};
1532  env(check::create(alice, bob, XRP(10)));
1533  env.close();
1534 
1535  uint256 const chkId3{getCheckIndex(alice, env.seq(alice))};
1536  env(check::create(alice, bob, USD(10)));
1537  env.close();
1538 
1539  // Three checks that expire in 10 minutes.
1540  using namespace std::chrono_literals;
1541  uint256 const chkIdNotExp1{getCheckIndex(alice, env.seq(alice))};
1542  env(check::create(alice, bob, XRP(10)),
1543  expiration(env.now() + 600s));
1544  env.close();
1545 
1546  uint256 const chkIdNotExp2{getCheckIndex(alice, env.seq(alice))};
1547  env(check::create(alice, bob, USD(10)),
1548  expiration(env.now() + 600s));
1549  env.close();
1550 
1551  uint256 const chkIdNotExp3{getCheckIndex(alice, env.seq(alice))};
1552  env(check::create(alice, bob, XRP(10)),
1553  expiration(env.now() + 600s));
1554  env.close();
1555 
1556  // Three checks that expire in one second.
1557  uint256 const chkIdExp1{getCheckIndex(alice, env.seq(alice))};
1558  env(check::create(alice, bob, USD(10)), expiration(env.now() + 1s));
1559  env.close();
1560 
1561  uint256 const chkIdExp2{getCheckIndex(alice, env.seq(alice))};
1562  env(check::create(alice, bob, XRP(10)), expiration(env.now() + 1s));
1563  env.close();
1564 
1565  uint256 const chkIdExp3{getCheckIndex(alice, env.seq(alice))};
1566  env(check::create(alice, bob, USD(10)), expiration(env.now() + 1s));
1567  env.close();
1568 
1569  // Two checks to cancel using a regular key and using multisigning.
1570  uint256 const chkIdReg{getCheckIndex(alice, env.seq(alice))};
1571  env(check::create(alice, bob, USD(10)));
1572  env.close();
1573 
1574  uint256 const chkIdMSig{getCheckIndex(alice, env.seq(alice))};
1575  env(check::create(alice, bob, XRP(10)));
1576  env.close();
1577  BEAST_EXPECT(checksOnAccount(env, alice).size() == 11);
1578  BEAST_EXPECT(ownerCount(env, alice) == 11);
1579 
1580  // Creator, destination, and an outsider cancel the checks.
1581  env(check::cancel(alice, chkId1));
1582  env.close();
1583  BEAST_EXPECT(checksOnAccount(env, alice).size() == 10);
1584  BEAST_EXPECT(ownerCount(env, alice) == 10);
1585 
1586  env(check::cancel(bob, chkId2));
1587  env.close();
1588  BEAST_EXPECT(checksOnAccount(env, alice).size() == 9);
1589  BEAST_EXPECT(ownerCount(env, alice) == 9);
1590 
1591  env(check::cancel(zoe, chkId3), ter(tecNO_PERMISSION));
1592  env.close();
1593  BEAST_EXPECT(checksOnAccount(env, alice).size() == 9);
1594  BEAST_EXPECT(ownerCount(env, alice) == 9);
1595 
1596  // Creator, destination, and an outsider cancel unexpired checks.
1597  env(check::cancel(alice, chkIdNotExp1));
1598  env.close();
1599  BEAST_EXPECT(checksOnAccount(env, alice).size() == 8);
1600  BEAST_EXPECT(ownerCount(env, alice) == 8);
1601 
1602  env(check::cancel(bob, chkIdNotExp2));
1603  env.close();
1604  BEAST_EXPECT(checksOnAccount(env, alice).size() == 7);
1605  BEAST_EXPECT(ownerCount(env, alice) == 7);
1606 
1607  env(check::cancel(zoe, chkIdNotExp3), ter(tecNO_PERMISSION));
1608  env.close();
1609  BEAST_EXPECT(checksOnAccount(env, alice).size() == 7);
1610  BEAST_EXPECT(ownerCount(env, alice) == 7);
1611 
1612  // Creator, destination, and an outsider cancel expired checks.
1613  env(check::cancel(alice, chkIdExp1));
1614  env.close();
1615  BEAST_EXPECT(checksOnAccount(env, alice).size() == 6);
1616  BEAST_EXPECT(ownerCount(env, alice) == 6);
1617 
1618  env(check::cancel(bob, chkIdExp2));
1619  env.close();
1620  BEAST_EXPECT(checksOnAccount(env, alice).size() == 5);
1621  BEAST_EXPECT(ownerCount(env, alice) == 5);
1622 
1623  env(check::cancel(zoe, chkIdExp3));
1624  env.close();
1625  BEAST_EXPECT(checksOnAccount(env, alice).size() == 4);
1626  BEAST_EXPECT(ownerCount(env, alice) == 4);
1627 
1628  // Use a regular key and also multisign to cancel checks.
1629  Account const alie{"alie", KeyType::ed25519};
1630  env(regkey(alice, alie));
1631  env.close();
1632 
1633  Account const bogie{"bogie", KeyType::secp256k1};
1634  Account const demon{"demon", KeyType::ed25519};
1635  env(signers(alice, 2, {{bogie, 1}, {demon, 1}}), sig(alie));
1636  env.close();
1637 
1638  // If featureMultiSignReserve is enabled then alices's signer list
1639  // has an owner count of 1, otherwise it's 4.
1640  int const signersCount{features[featureMultiSignReserve] ? 1 : 4};
1641 
1642  // alice uses her regular key to cancel a check.
1643  env(check::cancel(alice, chkIdReg), sig(alie));
1644  env.close();
1645  BEAST_EXPECT(checksOnAccount(env, alice).size() == 3);
1646  BEAST_EXPECT(ownerCount(env, alice) == signersCount + 3);
1647 
1648  // alice uses multisigning to cancel a check.
1649  XRPAmount const baseFeeDrops{env.current()->fees().base};
1650  env(check::cancel(alice, chkIdMSig),
1651  msig(bogie, demon),
1652  fee(3 * baseFeeDrops));
1653  env.close();
1654  BEAST_EXPECT(checksOnAccount(env, alice).size() == 2);
1655  BEAST_EXPECT(ownerCount(env, alice) == signersCount + 2);
1656 
1657  // Creator and destination cancel the remaining unexpired checks.
1658  env(check::cancel(alice, chkId3), sig(alice));
1659  env.close();
1660  BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
1661  BEAST_EXPECT(ownerCount(env, alice) == signersCount + 1);
1662 
1663  env(check::cancel(bob, chkIdNotExp3));
1664  env.close();
1665  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
1666  BEAST_EXPECT(ownerCount(env, alice) == signersCount + 0);
1667  }
1668  }
1669 
1670  void
1672  {
1673  // Explore many of the ways to fail at canceling a check.
1674  testcase("Cancel invalid");
1675 
1676  using namespace test::jtx;
1677 
1678  Account const alice{"alice"};
1679  Account const bob{"bob"};
1680 
1681  Env env{*this};
1682 
1683  env.fund(XRP(1000), alice, bob);
1684 
1685  // Bad fee.
1686  env(check::cancel(bob, getCheckIndex(alice, env.seq(alice))),
1687  fee(drops(-10)),
1688  ter(temBAD_FEE));
1689  env.close();
1690 
1691  // Bad flags.
1692  env(check::cancel(bob, getCheckIndex(alice, env.seq(alice))),
1693  txflags(tfImmediateOrCancel),
1694  ter(temINVALID_FLAG));
1695  env.close();
1696 
1697  // Non-existent check.
1698  env(check::cancel(bob, getCheckIndex(alice, env.seq(alice))),
1699  ter(tecNO_ENTRY));
1700  env.close();
1701  }
1702 
1703  void
1705  {
1706  testcase("Fix1623 enable");
1707 
1708  using namespace test::jtx;
1709 
1710  auto testEnable = [this](
1711  FeatureBitset const& features, bool hasFields) {
1712  // Unless fix1623 is enabled a "tx" RPC command should return
1713  // neither "DeliveredAmount" nor "delivered_amount" on a CheckCash
1714  // transaction.
1715  Account const alice{"alice"};
1716  Account const bob{"bob"};
1717 
1718  Env env{*this, features};
1719 
1720  env.fund(XRP(1000), alice, bob);
1721  env.close();
1722 
1723  uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
1724  env(check::create(alice, bob, XRP(200)));
1725  env.close();
1726 
1727  env(check::cash(bob, chkId, check::DeliverMin(XRP(100))));
1728 
1729  // Get the hash for the most recent transaction.
1730  std::string const txHash{
1731  env.tx()->getJson(JsonOptions::none)[jss::hash].asString()};
1732 
1733  // DeliveredAmount and delivered_amount are either present or
1734  // not present in the metadata returned by "tx" based on fix1623.
1735  env.close();
1736  Json::Value const meta =
1737  env.rpc("tx", txHash)[jss::result][jss::meta];
1738 
1739  BEAST_EXPECT(
1740  meta.isMember(sfDeliveredAmount.jsonName) == hasFields);
1741  BEAST_EXPECT(meta.isMember(jss::delivered_amount) == hasFields);
1742  };
1743 
1744  // Run both the disabled and enabled cases.
1745  testEnable(supported_amendments() - fix1623, false);
1746  testEnable(supported_amendments(), true);
1747  }
1748 
1749  void
1751  {
1752  testcase("With Tickets");
1753 
1754  using namespace test::jtx;
1755 
1756  Account const gw{"gw"};
1757  Account const alice{"alice"};
1758  Account const bob{"bob"};
1759  IOU const USD{gw["USD"]};
1760 
1761  Env env{*this};
1762  env.fund(XRP(1000), gw, alice, bob);
1763  env.close();
1764 
1765  // alice and bob grab enough tickets for all of the following
1766  // transactions. Note that once the tickets are acquired alice's
1767  // and bob's account sequence numbers should not advance.
1768  std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
1769  env(ticket::create(alice, 10));
1770  std::uint32_t const aliceSeq{env.seq(alice)};
1771 
1772  std::uint32_t bobTicketSeq{env.seq(bob) + 1};
1773  env(ticket::create(bob, 10));
1774  std::uint32_t const bobSeq{env.seq(bob)};
1775 
1776  env.close();
1777  env.require(owners(alice, 10));
1778  env.require(owners(bob, 10));
1779 
1780  // alice gets enough USD to write a few checks.
1781  env(trust(alice, USD(1000)), ticket::use(aliceTicketSeq++));
1782  env(trust(bob, USD(1000)), ticket::use(bobTicketSeq++));
1783  env.close();
1784  env.require(owners(alice, 10));
1785  env.require(owners(bob, 10));
1786 
1787  env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1788  BEAST_EXPECT(env.seq(alice) == aliceSeq);
1789 
1790  env.require(tickets(bob, env.seq(bob) - bobTicketSeq));
1791  BEAST_EXPECT(env.seq(bob) == bobSeq);
1792 
1793  env(pay(gw, alice, USD(900)));
1794  env.close();
1795 
1796  // alice creates four checks; two XRP, two IOU. Bob will cash
1797  // one of each and cancel one of each.
1798  uint256 const chkIdXrp1{getCheckIndex(alice, aliceTicketSeq)};
1799  env(check::create(alice, bob, XRP(200)), ticket::use(aliceTicketSeq++));
1800 
1801  uint256 const chkIdXrp2{getCheckIndex(alice, aliceTicketSeq)};
1802  env(check::create(alice, bob, XRP(300)), ticket::use(aliceTicketSeq++));
1803 
1804  uint256 const chkIdUsd1{getCheckIndex(alice, aliceTicketSeq)};
1805  env(check::create(alice, bob, USD(200)), ticket::use(aliceTicketSeq++));
1806 
1807  uint256 const chkIdUsd2{getCheckIndex(alice, aliceTicketSeq)};
1808  env(check::create(alice, bob, USD(300)), ticket::use(aliceTicketSeq++));
1809 
1810  env.close();
1811  // Alice used four tickets but created four checks.
1812  env.require(owners(alice, 10));
1813  env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1814  BEAST_EXPECT(checksOnAccount(env, alice).size() == 4);
1815  BEAST_EXPECT(env.seq(alice) == aliceSeq);
1816 
1817  env.require(owners(bob, 10));
1818  BEAST_EXPECT(env.seq(bob) == bobSeq);
1819 
1820  // Bob cancels two of alice's checks.
1821  env(check::cancel(bob, chkIdXrp1), ticket::use(bobTicketSeq++));
1822  env(check::cancel(bob, chkIdUsd2), ticket::use(bobTicketSeq++));
1823  env.close();
1824 
1825  env.require(owners(alice, 8));
1826  env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1827  BEAST_EXPECT(checksOnAccount(env, alice).size() == 2);
1828  BEAST_EXPECT(env.seq(alice) == aliceSeq);
1829 
1830  env.require(owners(bob, 8));
1831  BEAST_EXPECT(env.seq(bob) == bobSeq);
1832 
1833  // Bob cashes alice's two remaining checks.
1834  env(check::cash(bob, chkIdXrp2, XRP(300)), ticket::use(bobTicketSeq++));
1835  env(check::cash(bob, chkIdUsd1, USD(200)), ticket::use(bobTicketSeq++));
1836  env.close();
1837 
1838  env.require(owners(alice, 6));
1839  env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1840  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
1841  BEAST_EXPECT(env.seq(alice) == aliceSeq);
1842  env.require(balance(alice, USD(700)));
1843  env.require(balance(alice, drops(699'999'940)));
1844 
1845  env.require(owners(bob, 6));
1846  BEAST_EXPECT(env.seq(bob) == bobSeq);
1847  env.require(balance(bob, USD(200)));
1848  env.require(balance(bob, drops(1'299'999'940)));
1849  }
1850 
1851 public:
1852  void
1853  run() override
1854  {
1855  testEnabled();
1856  testCreateValid();
1857  testCreateInvalid();
1858  testCashXRP();
1859  testCashIOU();
1860  testCashXferFee();
1861  testCashQuality();
1862  testCashInvalid();
1863  testCancelValid();
1864  testCancelInvalid();
1865  testFix1623Enable();
1866  testWithTickets();
1867  }
1868 };
1869 
1870 BEAST_DEFINE_TESTSUITE(Check, tx, ripple);
1871 
1872 } // 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:138
ripple::sfOwnerCount
const SF_UINT32 sfOwnerCount
ripple::STAmount::negate
void negate()
Definition: STAmount.h:272
ripple::tecFROZEN
@ tecFROZEN
Definition: TER.h:264
ripple::sfSourceTag
const SF_UINT32 sfSourceTag
ripple::Issue
A currency issued by an account.
Definition: Issue.h:34
std::string
STL class.
std::shared_ptr
STL class.
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:372
ripple::terNO_LINE
@ terNO_LINE
Definition: TER.h:194
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::Check_test::testEnabled
void testEnabled()
Definition: Check_test.cpp:148
ripple::asfGlobalFreeze
const std::uint32_t asfGlobalFreeze
Definition: TxFlags.h:71
std::vector
STL class.
ripple::STAmount::getJson
Json::Value getJson(JsonOptions) const override
Definition: STAmount.cpp:594
ripple::test::jtx::dest_tag::dest_tag
dest_tag(std::uint32_t tag)
Definition: Check_test.cpp:72
ripple::tecDST_TAG_NEEDED
@ tecDST_TAG_NEEDED
Definition: TER.h:270
ripple::test::jtx::expiration::operator()
void operator()(Env &, JTx &jt) const
Definition: Check_test.cpp:41
ripple::featureMultiSignReserve
const uint256 featureMultiSignReserve
Definition: Feature.cpp:177
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::SField::jsonName
const Json::StaticString jsonName
Definition: SField.h:133
ripple::Check_test::testWithTickets
void testWithTickets()
Definition: Check_test.cpp:1750
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:251
ripple::Check_test::testCashXferFee
void testCashXferFee()
Definition: Check_test.cpp:932
ripple::KeyType::ed25519
@ ed25519
ripple::test::jtx::expiration
Set Expiration on a JTx.
Definition: Check_test.cpp:29
ripple::Keylet::key
uint256 key
Definition: Keylet.h:41
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::temINVALID_FLAG
@ temINVALID_FLAG
Definition: TER.h:106
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::test::jtx::JTx
Execution context for applying a JSON transaction.
Definition: JTx.h:41
ripple::test::jtx::dest_tag::operator()
void operator()(Env &, JTx &jt) const
Definition: Check_test.cpp:77
ripple::fix1623
const uint256 fix1623
Definition: Feature.cpp:173
ripple::Check_test::testCashXRP
void testCashXRP()
Definition: Check_test.cpp:481
ripple::STAmount
Definition: STAmount.h:42
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
ripple::Check_test::testCashIOU
void testCashIOU()
Definition: Check_test.cpp:600
std::uint32_t
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:424
ripple::tecPATH_PARTIAL
@ tecPATH_PARTIAL
Definition: TER.h:243
ripple::featureChecks
const uint256 featureChecks
Definition: Feature.cpp:170
ripple::Check_test::testCancelValid
void testCancelValid()
Definition: Check_test.cpp:1501
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::KeyType::secp256k1
@ secp256k1
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
Json::Value::removeMember
Value removeMember(const char *key)
Remove and return the named member.
Definition: json_value.cpp:907
ripple::tecNO_LINE
@ tecNO_LINE
Definition: TER.h:262
ripple::tecEXPIRED
@ tecEXPIRED
Definition: TER.h:275
ripple::Check_test::testCashInvalid
void testCashInvalid()
Definition: Check_test.cpp:1209
ripple::temDISABLED
@ temDISABLED
Definition: TER.h:109
ripple::test::jtx::Env::close
bool close(NetClock::time_point closeTime, boost::optional< std::chrono::milliseconds > consensusDelay=boost::none)
Close and advance the ledger.
Definition: Env.cpp:121
ripple::Check_test
Definition: Check_test.cpp:86
ripple::test::jtx::Env::le
std::shared_ptr< SLE const > le(Account const &account) const
Return an account root.
Definition: Env.cpp:207
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::tecNO_PERMISSION
@ tecNO_PERMISSION
Definition: TER.h:266
ripple::FeatureBitset
Definition: Feature.h:156
ripple::tecPATH_DRY
@ tecPATH_DRY
Definition: TER.h:255
ripple::tecINSUFFICIENT_RESERVE
@ tecINSUFFICIENT_RESERVE
Definition: TER.h:268
std::size_t
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
ripple::Check_test::testCreateInvalid
void testCreateInvalid()
Definition: Check_test.cpp:297
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:267
ripple::Check_test::testFix1623Enable
void testFix1623Enable()
Definition: Check_test.cpp:1704
ripple::temMALFORMED
@ temMALFORMED
Definition: TER.h:82
ripple::Check_test::testCreateValid
void testCreateValid()
Definition: Check_test.cpp:198
ripple::test::jtx::expiration::expiration
expiration(NetClock::time_point const &expiry)
Definition: Check_test.cpp:35
ripple::tecNO_AUTH
@ tecNO_AUTH
Definition: TER.h:261
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:282
ripple::tfSetfAuth
const std::uint32_t tfSetfAuth
Definition: TxFlags.h:91
ripple::test::jtx::dest_tag::tag_
const std::uint32_t tag_
Definition: Check_test.cpp:69
ripple::test::jtx::Env::current
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition: Env.h:299
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:115
ripple::tecNO_DST
@ tecNO_DST
Definition: TER.h:251
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
ripple::Check_test::testCashQuality
void testCashQuality()
Definition: Check_test.cpp:1002
ripple::Check_test::testCancelInvalid
void testCancelInvalid()
Definition: Check_test.cpp:1671
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::XRPAmount
Definition: XRPAmount.h:46
ripple::test::jtx::source_tag::operator()
void operator()(Env &, JTx &jt) const
Definition: Check_test.cpp:59