rippled
DepositAuth_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 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 <test/jtx.h>
22 
23 namespace ripple {
24 namespace test {
25 
26 // Helper function that returns the reserve on an account based on
27 // the passed in number of owners.
28 static XRPAmount
30 {
31  return env.current()->fees().accountReserve(count);
32 }
33 
34 // Helper function that returns true if acct has the lsfDepostAuth flag set.
35 static bool
36 hasDepositAuth(jtx::Env const& env, jtx::Account const& acct)
37 {
38  return ((*env.le(acct))[sfFlags] & lsfDepositAuth) == lsfDepositAuth;
39 }
40 
41 struct DepositAuth_test : public beast::unit_test::suite
42 {
43  void
45  {
46  testcase("Enable");
47 
48  using namespace jtx;
49  Account const alice{"alice"};
50 
51  {
52  // featureDepositAuth is disabled.
54  env.fund(XRP(10000), alice);
55 
56  // Note that, to support old behavior, invalid flags are ignored.
57  env(fset(alice, asfDepositAuth));
58  env.close();
59  BEAST_EXPECT(!hasDepositAuth(env, alice));
60 
61  env(fclear(alice, asfDepositAuth));
62  env.close();
63  BEAST_EXPECT(!hasDepositAuth(env, alice));
64  }
65  {
66  // featureDepositAuth is enabled.
67  Env env(*this);
68  env.fund(XRP(10000), alice);
69 
70  env(fset(alice, asfDepositAuth));
71  env.close();
72  BEAST_EXPECT(hasDepositAuth(env, alice));
73 
74  env(fclear(alice, asfDepositAuth));
75  env.close();
76  BEAST_EXPECT(!hasDepositAuth(env, alice));
77  }
78  }
79 
80  void
82  {
83  // Exercise IOU payments and non-direct XRP payments to an account
84  // that has the lsfDepositAuth flag set.
85  testcase("Pay IOU");
86 
87  using namespace jtx;
88  Account const alice{"alice"};
89  Account const bob{"bob"};
90  Account const carol{"carol"};
91  Account const gw{"gw"};
92  IOU const USD = gw["USD"];
93 
94  Env env(*this);
95 
96  env.fund(XRP(10000), alice, bob, carol, gw);
97  env.trust(USD(1000), alice, bob);
98  env.close();
99 
100  env(pay(gw, alice, USD(150)));
101  env(offer(carol, USD(100), XRP(100)));
102  env.close();
103 
104  // Make sure bob's trust line is all set up so he can receive USD.
105  env(pay(alice, bob, USD(50)));
106  env.close();
107 
108  // bob sets the lsfDepositAuth flag.
109  env(fset(bob, asfDepositAuth), require(flags(bob, asfDepositAuth)));
110  env.close();
111 
112  // None of the following payments should succeed.
113  auto failedIouPayments = [this, &env, &alice, &bob, &USD]() {
114  env.require(flags(bob, asfDepositAuth));
115 
116  // Capture bob's balances before hand to confirm they don't change.
117  PrettyAmount const bobXrpBalance{env.balance(bob, XRP)};
118  PrettyAmount const bobUsdBalance{env.balance(bob, USD)};
119 
120  env(pay(alice, bob, USD(50)), ter(tecNO_PERMISSION));
121  env.close();
122 
123  // Note that even though alice is paying bob in XRP, the payment
124  // is still not allowed since the payment passes through an offer.
125  env(pay(alice, bob, drops(1)),
126  sendmax(USD(1)),
128  env.close();
129 
130  BEAST_EXPECT(bobXrpBalance == env.balance(bob, XRP));
131  BEAST_EXPECT(bobUsdBalance == env.balance(bob, USD));
132  };
133 
134  // Test when bob has an XRP balance > base reserve.
135  failedIouPayments();
136 
137  // Set bob's XRP balance == base reserve. Also demonstrate that
138  // bob can make payments while his lsfDepositAuth flag is set.
139  env(pay(bob, alice, USD(25)));
140  env.close();
141 
142  {
143  STAmount const bobPaysXRP{env.balance(bob, XRP) - reserve(env, 1)};
144  XRPAmount const bobPaysFee{reserve(env, 1) - reserve(env, 0)};
145  env(pay(bob, alice, bobPaysXRP), fee(bobPaysFee));
146  env.close();
147  }
148 
149  // Test when bob's XRP balance == base reserve.
150  BEAST_EXPECT(env.balance(bob, XRP) == reserve(env, 0));
151  BEAST_EXPECT(env.balance(bob, USD) == USD(25));
152  failedIouPayments();
153 
154  // Test when bob has an XRP balance == 0.
155  env(noop(bob), fee(reserve(env, 0)));
156  env.close();
157 
158  BEAST_EXPECT(env.balance(bob, XRP) == XRP(0));
159  failedIouPayments();
160 
161  // Give bob enough XRP for the fee to clear the lsfDepositAuth flag.
162  env(pay(alice, bob, drops(env.current()->fees().base)));
163 
164  // bob clears the lsfDepositAuth and the next payment succeeds.
165  env(fclear(bob, asfDepositAuth));
166  env.close();
167 
168  env(pay(alice, bob, USD(50)));
169  env.close();
170 
171  env(pay(alice, bob, drops(1)), sendmax(USD(1)));
172  env.close();
173  }
174 
175  void
177  {
178  // Exercise direct XRP payments to an account that has the
179  // lsfDepositAuth flag set.
180  testcase("Pay XRP");
181 
182  using namespace jtx;
183  Account const alice{"alice"};
184  Account const bob{"bob"};
185 
186  Env env(*this);
187 
188  env.fund(XRP(10000), alice, bob);
189 
190  // bob sets the lsfDepositAuth flag.
191  env(fset(bob, asfDepositAuth), fee(drops(10)));
192  env.close();
193  BEAST_EXPECT(env.balance(bob, XRP) == XRP(10000) - drops(10));
194 
195  // bob has more XRP than the base reserve. Any XRP payment should fail.
196  env(pay(alice, bob, drops(1)), ter(tecNO_PERMISSION));
197  env.close();
198  BEAST_EXPECT(env.balance(bob, XRP) == XRP(10000) - drops(10));
199 
200  // Change bob's XRP balance to exactly the base reserve.
201  {
202  STAmount const bobPaysXRP{env.balance(bob, XRP) - reserve(env, 1)};
203  XRPAmount const bobPaysFee{reserve(env, 1) - reserve(env, 0)};
204  env(pay(bob, alice, bobPaysXRP), fee(bobPaysFee));
205  env.close();
206  }
207 
208  // bob has exactly the base reserve. A small enough direct XRP
209  // payment should succeed.
210  BEAST_EXPECT(env.balance(bob, XRP) == reserve(env, 0));
211  env(pay(alice, bob, drops(1)));
212  env.close();
213 
214  // bob has exactly the base reserve + 1. No payment should succeed.
215  BEAST_EXPECT(env.balance(bob, XRP) == reserve(env, 0) + drops(1));
216  env(pay(alice, bob, drops(1)), ter(tecNO_PERMISSION));
217  env.close();
218 
219  // Take bob down to a balance of 0 XRP.
220  env(noop(bob), fee(reserve(env, 0) + drops(1)));
221  env.close();
222  BEAST_EXPECT(env.balance(bob, XRP) == drops(0));
223 
224  // We should not be able to pay bob more than the base reserve.
225  env(pay(alice, bob, reserve(env, 0) + drops(1)), ter(tecNO_PERMISSION));
226  env.close();
227 
228  // However a payment of exactly the base reserve should succeed.
229  env(pay(alice, bob, reserve(env, 0) + drops(0)));
230  env.close();
231  BEAST_EXPECT(env.balance(bob, XRP) == reserve(env, 0));
232 
233  // We should be able to pay bob the base reserve one more time.
234  env(pay(alice, bob, reserve(env, 0) + drops(0)));
235  env.close();
236  BEAST_EXPECT(
237  env.balance(bob, XRP) == (reserve(env, 0) + reserve(env, 0)));
238 
239  // bob's above the threshold again. Any payment should fail.
240  env(pay(alice, bob, drops(1)), ter(tecNO_PERMISSION));
241  env.close();
242  BEAST_EXPECT(
243  env.balance(bob, XRP) == (reserve(env, 0) + reserve(env, 0)));
244 
245  // Take bob back down to a zero XRP balance.
246  env(noop(bob), fee(env.balance(bob, XRP)));
247  env.close();
248  BEAST_EXPECT(env.balance(bob, XRP) == drops(0));
249 
250  // bob should not be able to clear lsfDepositAuth.
252  env.close();
253 
254  // We should be able to pay bob 1 drop now.
255  env(pay(alice, bob, drops(1)));
256  env.close();
257  BEAST_EXPECT(env.balance(bob, XRP) == drops(1));
258 
259  // Pay bob enough so he can afford the fee to clear lsfDepositAuth.
260  env(pay(alice, bob, drops(9)));
261  env.close();
262 
263  // Interestingly, at this point the terINSUF_FEE_B retry grabs the
264  // request to clear lsfDepositAuth. So the balance should be zero
265  // and lsfDepositAuth should be cleared.
266  BEAST_EXPECT(env.balance(bob, XRP) == drops(0));
267  env.require(nflags(bob, asfDepositAuth));
268 
269  // Since bob no longer has lsfDepositAuth set we should be able to
270  // pay him more than the base reserve.
271  env(pay(alice, bob, reserve(env, 0) + drops(1)));
272  env.close();
273  BEAST_EXPECT(env.balance(bob, XRP) == reserve(env, 0) + drops(1));
274  }
275 
276  void
278  {
279  // It its current incarnation the DepositAuth flag does not change
280  // any behaviors regarding rippling and the NoRipple flag.
281  // Demonstrate that.
282  testcase("No Ripple");
283 
284  using namespace jtx;
285  Account const gw1("gw1");
286  Account const gw2("gw2");
287  Account const alice("alice");
288  Account const bob("bob");
289 
290  IOU const USD1(gw1["USD"]);
291  IOU const USD2(gw2["USD"]);
292 
293  auto testIssuer = [&](FeatureBitset const& features,
294  bool noRipplePrev,
295  bool noRippleNext,
296  bool withDepositAuth) {
297  assert(!withDepositAuth || features[featureDepositAuth]);
298 
299  Env env(*this, features);
300 
301  env.fund(XRP(10000), gw1, alice, bob);
302  env(trust(gw1, alice["USD"](10), noRipplePrev ? tfSetNoRipple : 0));
303  env(trust(gw1, bob["USD"](10), noRippleNext ? tfSetNoRipple : 0));
304  env.trust(USD1(10), alice, bob);
305 
306  env(pay(gw1, alice, USD1(10)));
307 
308  if (withDepositAuth)
309  env(fset(gw1, asfDepositAuth));
310 
311  TER const result = (noRippleNext && noRipplePrev) ? TER{tecPATH_DRY}
312  : TER{tesSUCCESS};
313  env(pay(alice, bob, USD1(10)), path(gw1), ter(result));
314  };
315 
316  auto testNonIssuer = [&](FeatureBitset const& features,
317  bool noRipplePrev,
318  bool noRippleNext,
319  bool withDepositAuth) {
320  assert(!withDepositAuth || features[featureDepositAuth]);
321 
322  Env env(*this, features);
323 
324  env.fund(XRP(10000), gw1, gw2, alice);
325  env(trust(alice, USD1(10), noRipplePrev ? tfSetNoRipple : 0));
326  env(trust(alice, USD2(10), noRippleNext ? tfSetNoRipple : 0));
327  env(pay(gw2, alice, USD2(10)));
328 
329  if (withDepositAuth)
330  env(fset(alice, asfDepositAuth));
331 
332  TER const result = (noRippleNext && noRipplePrev) ? TER{tecPATH_DRY}
333  : TER{tesSUCCESS};
334  env(pay(gw1, gw2, USD2(10)),
335  path(alice),
336  sendmax(USD1(10)),
337  ter(result));
338  };
339 
340  // Test every combo of noRipplePrev, noRippleNext, and withDepositAuth
341  for (int i = 0; i < 8; ++i)
342  {
343  auto const noRipplePrev = i & 0x1;
344  auto const noRippleNext = i & 0x2;
345  auto const withDepositAuth = i & 0x4;
346  testIssuer(
348  noRipplePrev,
349  noRippleNext,
350  withDepositAuth);
351 
352  if (!withDepositAuth)
353  testIssuer(
355  noRipplePrev,
356  noRippleNext,
357  withDepositAuth);
358 
359  testNonIssuer(
361  noRipplePrev,
362  noRippleNext,
363  withDepositAuth);
364 
365  if (!withDepositAuth)
366  testNonIssuer(
368  noRipplePrev,
369  noRippleNext,
370  withDepositAuth);
371  }
372  }
373 
374  void
375  run() override
376  {
377  testEnable();
378  testPayIOU();
379  testPayXRP();
380  testNoRipple();
381  }
382 };
383 
384 struct DepositPreauth_test : public beast::unit_test::suite
385 {
386  void
388  {
389  testcase("Enable");
390 
391  using namespace jtx;
392  Account const alice{"alice"};
393  Account const becky{"becky"};
394  {
395  // featureDepositPreauth is disabled.
397  env.fund(XRP(10000), alice, becky);
398  env.close();
399 
400  // Should not be able to add a DepositPreauth to alice.
401  env(deposit::auth(alice, becky), ter(temDISABLED));
402  env.close();
403  env.require(owners(alice, 0));
404  env.require(owners(becky, 0));
405 
406  // Should not be able to remove a DepositPreauth from alice.
407  env(deposit::unauth(alice, becky), ter(temDISABLED));
408  env.close();
409  env.require(owners(alice, 0));
410  env.require(owners(becky, 0));
411  }
412  {
413  // featureDepositPreauth is enabled. The valid case is really
414  // simple:
415  // o We should be able to add and remove an entry, and
416  // o That entry should cost one reserve.
417  // o The reserve should be returned when the entry is removed.
418  Env env(*this);
419  env.fund(XRP(10000), alice, becky);
420  env.close();
421 
422  // Add a DepositPreauth to alice.
423  env(deposit::auth(alice, becky));
424  env.close();
425  env.require(owners(alice, 1));
426  env.require(owners(becky, 0));
427 
428  // Remove a DepositPreauth from alice.
429  env(deposit::unauth(alice, becky));
430  env.close();
431  env.require(owners(alice, 0));
432  env.require(owners(becky, 0));
433  }
434  {
435  // Verify that an account can be preauthorized and unauthorized
436  // using tickets.
437  Env env(*this);
438  env.fund(XRP(10000), alice, becky);
439  env.close();
440 
441  env(ticket::create(alice, 2));
442  std::uint32_t const aliceSeq{env.seq(alice)};
443  env.close();
444  env.require(tickets(alice, 2));
445 
446  // Consume the tickets from biggest seq to smallest 'cuz we can.
447  std::uint32_t aliceTicketSeq{env.seq(alice)};
448 
449  // Add a DepositPreauth to alice.
450  env(deposit::auth(alice, becky), ticket::use(--aliceTicketSeq));
451  env.close();
452  // Alice uses a ticket but gains a preauth entry.
453  env.require(tickets(alice, 1));
454  env.require(owners(alice, 2));
455  BEAST_EXPECT(env.seq(alice) == aliceSeq);
456  env.require(owners(becky, 0));
457 
458  // Remove a DepositPreauth from alice.
459  env(deposit::unauth(alice, becky), ticket::use(--aliceTicketSeq));
460  env.close();
461  env.require(tickets(alice, 0));
462  env.require(owners(alice, 0));
463  BEAST_EXPECT(env.seq(alice) == aliceSeq);
464  env.require(owners(becky, 0));
465  }
466  }
467 
468  void
470  {
471  testcase("Invalid");
472 
473  using namespace jtx;
474  Account const alice{"alice"};
475  Account const becky{"becky"};
476  Account const carol{"carol"};
477 
478  Env env(*this);
479 
480  // Tell env about alice, becky and carol since they are not yet funded.
481  env.memoize(alice);
482  env.memoize(becky);
483  env.memoize(carol);
484 
485  // Add DepositPreauth to an unfunded account.
486  env(deposit::auth(alice, becky), seq(1), ter(terNO_ACCOUNT));
487 
488  env.fund(XRP(10000), alice, becky);
489  env.close();
490 
491  // Bad fee.
492  env(deposit::auth(alice, becky), fee(drops(-10)), ter(temBAD_FEE));
493  env.close();
494 
495  // Bad flags.
496  env(deposit::auth(alice, becky), txflags(tfSell), ter(temINVALID_FLAG));
497  env.close();
498 
499  {
500  // Neither auth not unauth.
501  Json::Value tx{deposit::auth(alice, becky)};
503  env(tx, ter(temMALFORMED));
504  env.close();
505  }
506  {
507  // Both auth and unauth.
508  Json::Value tx{deposit::auth(alice, becky)};
509  tx[sfUnauthorize.jsonName] = becky.human();
510  env(tx, ter(temMALFORMED));
511  env.close();
512  }
513  {
514  // Alice authorizes a zero account.
515  Json::Value tx{deposit::auth(alice, becky)};
517  env(tx, ter(temINVALID_ACCOUNT_ID));
518  env.close();
519  }
520 
521  // alice authorizes herself.
522  env(deposit::auth(alice, alice), ter(temCANNOT_PREAUTH_SELF));
523  env.close();
524 
525  // alice authorizes an unfunded account.
526  env(deposit::auth(alice, carol), ter(tecNO_TARGET));
527  env.close();
528 
529  // alice successfully authorizes becky.
530  env.require(owners(alice, 0));
531  env.require(owners(becky, 0));
532  env(deposit::auth(alice, becky));
533  env.close();
534  env.require(owners(alice, 1));
535  env.require(owners(becky, 0));
536 
537  // alice attempts to create a duplicate authorization.
538  env(deposit::auth(alice, becky), ter(tecDUPLICATE));
539  env.close();
540  env.require(owners(alice, 1));
541  env.require(owners(becky, 0));
542 
543  // carol attempts to preauthorize but doesn't have enough reserve.
544  env.fund(drops(249'999'999), carol);
545  env.close();
546 
547  env(deposit::auth(carol, becky), ter(tecINSUFFICIENT_RESERVE));
548  env.close();
549  env.require(owners(carol, 0));
550  env.require(owners(becky, 0));
551 
552  // carol gets enough XRP to (barely) meet the reserve.
553  env(pay(alice, carol, drops(11)));
554  env.close();
555  env(deposit::auth(carol, becky));
556  env.close();
557  env.require(owners(carol, 1));
558  env.require(owners(becky, 0));
559 
560  // But carol can't meet the reserve for another preauthorization.
561  env(deposit::auth(carol, alice), ter(tecINSUFFICIENT_RESERVE));
562  env.close();
563  env.require(owners(carol, 1));
564  env.require(owners(becky, 0));
565  env.require(owners(alice, 1));
566 
567  // alice attempts to remove an authorization she doesn't have.
568  env(deposit::unauth(alice, carol), ter(tecNO_ENTRY));
569  env.close();
570  env.require(owners(alice, 1));
571  env.require(owners(becky, 0));
572 
573  // alice successfully removes her authorization of becky.
574  env(deposit::unauth(alice, becky));
575  env.close();
576  env.require(owners(alice, 0));
577  env.require(owners(becky, 0));
578 
579  // alice removes becky again and gets an error.
580  env(deposit::unauth(alice, becky), ter(tecNO_ENTRY));
581  env.close();
582  env.require(owners(alice, 0));
583  env.require(owners(becky, 0));
584  }
585 
586  void
588  {
589  testcase("Payment");
590 
591  using namespace jtx;
592  Account const alice{"alice"};
593  Account const becky{"becky"};
594  Account const gw{"gw"};
595  IOU const USD(gw["USD"]);
596 
597  bool const supportsPreauth = {features[featureDepositPreauth]};
598 
599  {
600  // The initial implementation of DepositAuth had a bug where an
601  // account with the DepositAuth flag set could not make a payment
602  // to itself. That bug was fixed in the DepositPreauth amendment.
603  Env env(*this, features);
604  env.fund(XRP(5000), alice, becky, gw);
605  env.close();
606 
607  env.trust(USD(1000), alice);
608  env.trust(USD(1000), becky);
609  env.close();
610 
611  env(pay(gw, alice, USD(500)));
612  env.close();
613 
614  env(offer(alice, XRP(100), USD(100), tfPassive),
615  require(offers(alice, 1)));
616  env.close();
617 
618  // becky pays herself USD (10) by consuming part of alice's offer.
619  // Make sure the payment works if PaymentAuth is not involved.
620  env(pay(becky, becky, USD(10)), path(~USD), sendmax(XRP(10)));
621  env.close();
622 
623  // becky decides to require authorization for deposits.
624  env(fset(becky, asfDepositAuth));
625  env.close();
626 
627  // becky pays herself again. Whether it succeeds depends on
628  // whether featureDepositPreauth is enabled.
629  TER const expect{
630  supportsPreauth ? TER{tesSUCCESS} : TER{tecNO_PERMISSION}};
631 
632  env(pay(becky, becky, USD(10)),
633  path(~USD),
634  sendmax(XRP(10)),
635  ter(expect));
636  env.close();
637  }
638 
639  if (supportsPreauth)
640  {
641  // Make sure DepositPreauthorization works for payments.
642 
643  Account const carol{"carol"};
644 
645  Env env(*this, features);
646  env.fund(XRP(5000), alice, becky, carol, gw);
647  env.close();
648 
649  env.trust(USD(1000), alice);
650  env.trust(USD(1000), becky);
651  env.trust(USD(1000), carol);
652  env.close();
653 
654  env(pay(gw, alice, USD(1000)));
655  env.close();
656 
657  // Make XRP and IOU payments from alice to becky. Should be fine.
658  env(pay(alice, becky, XRP(100)));
659  env(pay(alice, becky, USD(100)));
660  env.close();
661 
662  // becky decides to require authorization for deposits.
663  env(fset(becky, asfDepositAuth));
664  env.close();
665 
666  // alice can no longer pay becky.
667  env(pay(alice, becky, XRP(100)), ter(tecNO_PERMISSION));
668  env(pay(alice, becky, USD(100)), ter(tecNO_PERMISSION));
669  env.close();
670 
671  // becky preauthorizes carol for deposit, which doesn't provide
672  // authorization for alice.
673  env(deposit::auth(becky, carol));
674  env.close();
675 
676  // alice still can't pay becky.
677  env(pay(alice, becky, XRP(100)), ter(tecNO_PERMISSION));
678  env(pay(alice, becky, USD(100)), ter(tecNO_PERMISSION));
679  env.close();
680 
681  // becky preauthorizes alice for deposit.
682  env(deposit::auth(becky, alice));
683  env.close();
684 
685  // alice can now pay becky.
686  env(pay(alice, becky, XRP(100)));
687  env(pay(alice, becky, USD(100)));
688  env.close();
689 
690  // alice decides to require authorization for deposits.
691  env(fset(alice, asfDepositAuth));
692  env.close();
693 
694  // Even though alice is authorized to pay becky, becky is not
695  // authorized to pay alice.
696  env(pay(becky, alice, XRP(100)), ter(tecNO_PERMISSION));
697  env(pay(becky, alice, USD(100)), ter(tecNO_PERMISSION));
698  env.close();
699 
700  // becky unauthorizes carol. Should have no impact on alice.
701  env(deposit::unauth(becky, carol));
702  env.close();
703 
704  env(pay(alice, becky, XRP(100)));
705  env(pay(alice, becky, USD(100)));
706  env.close();
707 
708  // becky unauthorizes alice. alice now can't pay becky.
709  env(deposit::unauth(becky, alice));
710  env.close();
711 
712  env(pay(alice, becky, XRP(100)), ter(tecNO_PERMISSION));
713  env(pay(alice, becky, USD(100)), ter(tecNO_PERMISSION));
714  env.close();
715 
716  // becky decides to remove authorization for deposits. Now
717  // alice can pay becky again.
718  env(fclear(becky, asfDepositAuth));
719  env.close();
720 
721  env(pay(alice, becky, XRP(100)));
722  env(pay(alice, becky, USD(100)));
723  env.close();
724  }
725  }
726 
727  void
728  run() override
729  {
730  testEnable();
731  testInvalid();
732  auto const supported{jtx::supported_amendments()};
733  testPayment(supported - featureDepositPreauth);
734  testPayment(supported);
735  }
736 };
737 
738 BEAST_DEFINE_TESTSUITE(DepositAuth, app, ripple);
740 
741 } // namespace test
742 } // namespace ripple
ripple::test::jtx::noop
Json::Value noop(Account const &account)
The null transaction.
Definition: noop.h:31
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:105
ripple::test::DepositAuth_test::testNoRipple
void testNoRipple()
Definition: DepositAuth_test.cpp:277
ripple::tecNO_TARGET
@ tecNO_TARGET
Definition: TER.h:271
ripple::asfDepositAuth
constexpr std::uint32_t asfDepositAuth
Definition: TxFlags.h:82
ripple::test::DepositPreauth_test::run
void run() override
Definition: DepositAuth_test.cpp:728
ripple::test::jtx::drops
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Definition: amount.h:241
ripple::terINSUF_FEE_B
@ terINSUF_FEE_B
Definition: TER.h:197
ripple::test::jtx::ter
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition: ter.h:33
ripple::test::jtx::owners
Match the number of items in the account's owner directory.
Definition: owners.h:69
ripple::test::jtx::Env::require
void require(Args const &... args)
Check a set of requirements.
Definition: Env.h:466
ripple::test::DepositAuth_test
Definition: DepositAuth_test.cpp:41
ripple::featureDepositPreauth
const uint256 featureDepositPreauth
ripple::test::jtx::trust
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Definition: trust.cpp:30
ripple::tfSetNoRipple
constexpr std::uint32_t tfSetNoRipple
Definition: TxFlags.h:109
ripple::featureDepositAuth
const uint256 featureDepositAuth
ripple::test::jtx::require
Check a set of conditions.
Definition: require.h:63
ripple::DepositPreauth
Definition: DepositPreauth.h:27
ripple::temCANNOT_PREAUTH_SELF
@ temCANNOT_PREAUTH_SELF
Definition: TER.h:118
ripple::test::DepositPreauth_test::testPayment
void testPayment(FeatureBitset features)
Definition: DepositAuth_test.cpp:587
ripple::test::jtx::Env::balance
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
Definition: Env.cpp:183
ripple::tfPassive
constexpr std::uint32_t tfPassive
Definition: TxFlags.h:93
ripple::test::DepositAuth_test::testEnable
void testEnable()
Definition: DepositAuth_test.cpp:44
ripple::SField::jsonName
const Json::StaticString jsonName
Definition: SField.h:136
ripple::test::jtx::Env::trust
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
Definition: Env.cpp:259
ripple::lsfDepositAuth
@ lsfDepositAuth
Definition: LedgerFormats.h:234
ripple::test::DepositAuth_test::run
void run() override
Definition: DepositAuth_test.cpp:375
ripple::test::jtx::ticket::use
Set a ticket sequence on a JTx.
Definition: ticket.h:47
ripple::temINVALID_FLAG
@ temINVALID_FLAG
Definition: TER.h:109
ripple::test::hasDepositAuth
static bool hasDepositAuth(jtx::Env const &env, jtx::Account const &acct)
Definition: DepositAuth_test.cpp:36
ripple::sfUnauthorize
const SF_ACCOUNT sfUnauthorize
ripple::tecDUPLICATE
@ tecDUPLICATE
Definition: TER.h:282
ripple::TERSubset< CanCvtToTER >
ripple::test::jtx::sendmax
Sets the SendMax on a JTx.
Definition: sendmax.h:31
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::test::reserve
static XRPAmount reserve(jtx::Env &env, std::uint32_t count)
Definition: DepositAuth_test.cpp:29
ripple::test::jtx::txflags
Set the flags on a JTx.
Definition: txflags.h:30
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:45
ripple::xrpAccount
AccountID const & xrpAccount()
Compute AccountID from public key.
Definition: AccountID.cpp:168
ripple::test::DepositAuth_test::testPayIOU
void testPayIOU()
Definition: DepositAuth_test.cpp:81
ripple::test::jtx::path
Add a path.
Definition: paths.h:55
ripple::test::jtx::supported_amendments
FeatureBitset supported_amendments()
Definition: Env.h:70
ripple::sfAuthorize
const SF_ACCOUNT sfAuthorize
std::uint32_t
ripple::test::jtx::Env::seq
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
Definition: Env.cpp:207
ripple::temBAD_FEE
@ temBAD_FEE
Definition: TER.h:90
ripple::test::jtx::fclear
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Definition: flags.h:40
ripple::test::jtx::fee
Set the fee on a JTx.
Definition: fee.h:35
ripple::terNO_ACCOUNT
@ terNO_ACCOUNT
Definition: TER.h:198
ripple::test::DepositPreauth_test::testInvalid
void testInvalid()
Definition: DepositAuth_test.cpp:469
ripple::test::jtx::seq
Set the sequence number on a JTx.
Definition: seq.h:33
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::tfSell
constexpr std::uint32_t tfSell
Definition: TxFlags.h:96
ripple::test::jtx::flags
Match set account flags.
Definition: flags.h:108
ripple::temINVALID_ACCOUNT_ID
@ temINVALID_ACCOUNT_ID
Definition: TER.h:117
Json::Value::removeMember
Value removeMember(const char *key)
Remove and return the named member.
Definition: json_value.cpp:907
ripple::test::jtx::IOU
Converts to IOU Issue or STAmount.
Definition: amount.h:291
ripple::test::jtx::pay
Json::Value pay(Account const &account, Account const &to, AnyAmount amount)
Create a payment.
Definition: pay.cpp:29
ripple::temDISABLED
@ temDISABLED
Definition: TER.h:112
ripple::sfFlags
const SF_UINT32 sfFlags
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:228
ripple::test::jtx::Env::le
std::shared_ptr< SLE const > le(Account const &account) const
Return an account root.
Definition: Env.cpp:216
ripple::tecNO_PERMISSION
@ tecNO_PERMISSION
Definition: TER.h:272
ripple::FeatureBitset
Definition: Feature.h:113
ripple::tecPATH_DRY
@ tecPATH_DRY
Definition: TER.h:261
ripple::tecINSUFFICIENT_RESERVE
@ tecINSUFFICIENT_RESERVE
Definition: TER.h:274
ripple::test::jtx::nflags
Match clear account flags.
Definition: flags.h:125
ripple::test::DepositPreauth_test::testEnable
void testEnable()
Definition: DepositAuth_test.cpp:387
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
ripple::test::DepositAuth_test::testPayXRP
void testPayXRP()
Definition: DepositAuth_test.cpp:176
ripple::test::DepositPreauth_test
Definition: DepositAuth_test.cpp:384
ripple::tecNO_ENTRY
@ tecNO_ENTRY
Definition: TER.h:273
ripple::temMALFORMED
@ temMALFORMED
Definition: TER.h:85
ripple::test::jtx::Env::memoize
void memoize(Account const &account)
Associate AccountID with account.
Definition: Env.cpp:156
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:222
ripple::test::jtx::Env::current
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition: Env.h:300
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:116
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::test::jtx::PrettyAmount
Represents an XRP or IOU quantity This customizes the string conversion and supports XRP conversions ...
Definition: amount.h:73
ripple::XRPAmount
Definition: XRPAmount.h:46
ripple::test::jtx::owner_count
Definition: owners.h:49
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(DeliverMin, app, ripple)