2#include <test/jtx/Account.h>
3#include <test/jtx/Env.h>
4#include <test/jtx/amount.h>
5#include <test/jtx/balance.h>
6#include <test/jtx/escrow.h>
7#include <test/jtx/fee.h>
8#include <test/jtx/flags.h>
9#include <test/jtx/mpt.h>
10#include <test/jtx/pay.h>
11#include <test/jtx/rate.h>
12#include <test/jtx/ter.h>
13#include <test/jtx/trust.h>
14#include <test/jtx/txflags.h>
16#include <xrpl/beast/unit_test/suite.h>
17#include <xrpl/beast/utility/Journal.h>
18#include <xrpl/core/ServiceRegistry.h>
19#include <xrpl/json/json_value.h>
20#include <xrpl/json/to_string.h>
21#include <xrpl/ledger/ApplyView.h>
22#include <xrpl/ledger/Dir.h>
23#include <xrpl/ledger/OpenView.h>
24#include <xrpl/ledger/Sandbox.h>
25#include <xrpl/protocol/AccountID.h>
26#include <xrpl/protocol/Feature.h>
27#include <xrpl/protocol/Indexes.h>
28#include <xrpl/protocol/Issue.h>
29#include <xrpl/protocol/MPTIssue.h>
30#include <xrpl/protocol/Protocol.h>
31#include <xrpl/protocol/SField.h>
32#include <xrpl/protocol/STAmount.h>
33#include <xrpl/protocol/SeqProxy.h>
34#include <xrpl/protocol/TER.h>
35#include <xrpl/protocol/TxFlags.h>
36#include <xrpl/protocol/UintTypes.h>
37#include <xrpl/protocol/jss.h>
53 if (sle && sle->isFieldPresent(sfLockedAmount))
54 return (*sle)[sfLockedAmount];
62 if (sle && sle->isFieldPresent(sfLockedAmount))
63 return (*sle)[sfLockedAmount];
71 params[jss::account] = account.human();
72 auto jrr = env.
rpc(
"json",
"gateway_balances",
to_string(params));
73 auto const result = jrr[jss::result];
75 if (obligations.isNull())
76 return {
STAmount(issue, 0), account.name()};
78 return {amount, account.name()};
85 params[jss::account] = account.human();
86 auto jrr = env.
rpc(
"json",
"gateway_balances",
to_string(params));
87 auto const result = jrr[jss::result];
90 return {
STAmount(issue, 0), account.name()};
92 return {amount, account.name()};
103 for (
bool const withTokenEscrow : {
false,
true})
105 auto const amend = withTokenEscrow ? features : features - featureTokenEscrow;
106 Env env{*
this, amend};
107 auto const baseFee = env.
current()->fees().base;
108 auto const alice =
Account(
"alice");
109 auto const bob =
Account(
"bob");
110 auto const gw =
Account{
"gateway"};
111 auto const usd = gw[
"USD"];
112 env.
fund(
XRP(5000), alice, bob, gw);
113 env(
fset(gw, asfAllowTrustLineLocking));
115 env.
trust(usd(10'000), alice, bob);
117 env(
pay(gw, alice, usd(5000)));
118 env(
pay(gw, bob, usd(5000)));
124 auto const seq1 = env.
seq(alice);
138 auto const seq2 = env.
seq(alice);
150 for (
bool const withTokenEscrow : {
false,
true})
152 auto const amend = withTokenEscrow ? features : features - featureTokenEscrow;
153 Env env{*
this, amend};
154 auto const baseFee = env.
current()->fees().base;
155 auto const alice =
Account(
"alice");
156 auto const bob =
Account(
"bob");
157 auto const gw =
Account{
"gateway"};
158 auto const usd = gw[
"USD"];
159 env.
fund(
XRP(5000), alice, bob, gw);
160 env(
fset(gw, asfAllowTrustLineLocking));
162 env.
trust(usd(10'000), alice, bob);
164 env(
pay(gw, alice, usd(5000)));
165 env(
pay(gw, bob, usd(5000)));
168 auto const seq1 = env.
seq(alice);
189 Env env{*
this, features};
190 auto const baseFee = env.
current()->fees().base;
191 auto const alice =
Account(
"alice");
192 auto const bob =
Account(
"bob");
193 auto const gw =
Account{
"gateway"};
194 auto const usd = gw[
"USD"];
195 env.
fund(
XRP(5000), alice, bob, gw);
196 env(
fset(gw, asfAllowTrustLineLocking));
198 env.
trust(usd(10'000), alice, bob);
200 env(
pay(gw, alice, usd(5000)));
201 env(
pay(gw, bob, usd(5000)));
205 auto const seq1 = env.
seq(alice);
213 auto const seq2 = env.
seq(alice);
222 env(
fclear(gw, asfAllowTrustLineLocking));
256 Env env{*
this, features};
257 auto const alice =
Account(
"alice");
258 auto const bob =
Account(
"bob");
259 auto const gw =
Account{
"gateway"};
260 auto const usd = gw[
"USD"];
261 env.
fund(
XRP(5000), alice, bob, gw);
272 Env env{*
this, features};
273 auto const baseFee = env.
current()->fees().base;
274 auto const alice =
Account(
"alice");
275 auto const bob =
Account(
"bob");
276 auto const gw =
Account{
"gateway"};
277 auto const usd = gw[
"USD"];
278 env.
fund(
XRP(5000), alice, bob, gw);
290 Env env{*
this, features};
291 auto const baseFee = env.
current()->fees().base;
292 auto const alice =
Account(
"alice");
293 auto const bob =
Account(
"bob");
294 auto const gw =
Account{
"gateway"};
296 env.
fund(
XRP(5000), alice, bob, gw);
316 Env env{*
this, features};
317 auto const baseFee = env.
current()->fees().base;
318 auto const alice =
Account(
"alice");
319 auto const bob =
Account(
"bob");
320 auto const gw =
Account{
"gateway"};
321 auto const usd = gw[
"USD"];
322 env.
fund(
XRP(5000), alice, bob, gw);
334 Env env{*
this, features};
335 auto const baseFee = env.
current()->fees().base;
336 auto const alice =
Account(
"alice");
337 auto const bob =
Account(
"bob");
338 auto const gw =
Account{
"gateway"};
339 auto const usd = gw[
"USD"];
340 env.
fund(
XRP(5000), alice, bob);
354 Env env{*
this, features};
355 auto const baseFee = env.
current()->fees().base;
356 auto const alice =
Account(
"alice");
357 auto const bob =
Account(
"bob");
358 auto const gw =
Account{
"gateway"};
359 auto const usd = gw[
"USD"];
360 env.
fund(
XRP(5000), alice, bob, gw);
362 env.
trust(usd(10'000), alice, bob);
364 env(
pay(gw, alice, usd(5000)));
365 env(
pay(gw, bob, usd(5000)));
378 Env env{*
this, features};
379 auto const baseFee = env.
current()->fees().base;
380 auto const alice =
Account(
"alice");
381 auto const bob =
Account(
"bob");
382 auto const gw =
Account{
"gateway"};
383 auto const usd = gw[
"USD"];
384 env.
fund(
XRP(5000), alice, bob, gw);
385 env(
fset(gw, asfAllowTrustLineLocking));
399 Env env{*
this, features};
400 auto const baseFee = env.
current()->fees().base;
401 auto const alice =
Account(
"alice");
402 auto const bob =
Account(
"bob");
403 auto const gw =
Account{
"gateway"};
404 auto const usd = gw[
"USD"];
405 env.
fund(
XRP(5000), alice, bob, gw);
406 env(
fset(gw, asfAllowTrustLineLocking));
407 env(
fset(gw, asfRequireAuth));
409 env.
trust(usd(10'000), alice, bob);
422 Env env{*
this, features};
423 auto const baseFee = env.
current()->fees().base;
424 auto const alice =
Account(
"alice");
425 auto const bob =
Account(
"bob");
426 auto const gw =
Account{
"gateway"};
427 auto const usd = gw[
"USD"];
428 auto const aliceUSD = alice[
"USD"];
429 env.
fund(
XRP(5000), alice, bob, gw);
430 env(
fset(gw, asfAllowTrustLineLocking));
431 env(
fset(gw, asfRequireAuth));
434 env.
trust(usd(10'000), alice, bob);
448 Env env{*
this, features};
449 auto const alice =
Account(
"alice");
450 auto const bob =
Account(
"bob");
451 auto const gw =
Account{
"gateway"};
452 auto const usd = gw[
"USD"];
453 auto const baseFee = env.
current()->fees().base;
454 env.
fund(
XRP(10'000), alice, bob, gw);
455 env(
fset(gw, asfAllowTrustLineLocking));
457 env(
trust(alice, usd(100'000)));
458 env(
trust(bob, usd(100'000)));
460 env(
pay(gw, alice, usd(10'000)));
461 env(
pay(gw, bob, usd(10'000)));
465 env(
trust(gw, usd(10'000), alice, tfSetFreeze));
479 Env env{*
this, features};
480 auto const alice =
Account(
"alice");
481 auto const bob =
Account(
"bob");
482 auto const gw =
Account{
"gateway"};
483 auto const usd = gw[
"USD"];
484 auto const baseFee = env.
current()->fees().base;
485 env.
fund(
XRP(10'000), alice, bob, gw);
486 env(
fset(gw, asfAllowTrustLineLocking));
488 env(
trust(alice, usd(100'000)));
489 env(
trust(bob, usd(100'000)));
491 env(
pay(gw, alice, usd(10'000)));
492 env(
pay(gw, bob, usd(10'000)));
496 env(
trust(gw, usd(10'000), bob, tfSetFreeze));
510 Env env{*
this, features};
511 auto const alice =
Account(
"alice");
512 auto const bob =
Account(
"bob");
513 auto const gw =
Account{
"gateway"};
514 auto const usd = gw[
"USD"];
515 auto const baseFee = env.
current()->fees().base;
516 env.
fund(
XRP(10'000), alice, bob, gw);
517 env(
fset(gw, asfAllowTrustLineLocking));
519 env(
trust(alice, usd(100'000)));
520 env(
trust(bob, usd(100'000)));
534 Env env{*
this, features};
535 auto const alice =
Account(
"alice");
536 auto const bob =
Account(
"bob");
537 auto const gw =
Account{
"gateway"};
538 auto const usd = gw[
"USD"];
539 auto const baseFee = env.
current()->fees().base;
540 env.
fund(
XRP(10'000), alice, bob, gw);
541 env(
fset(gw, asfAllowTrustLineLocking));
543 env(
trust(alice, usd(100'000)));
544 env(
trust(bob, usd(100'000)));
546 env(
pay(gw, alice, usd(10'000)));
547 env(
pay(gw, bob, usd(10'000)));
560 Env env{*
this, features};
561 auto const alice =
Account(
"alice");
562 auto const bob =
Account(
"bob");
563 auto const gw =
Account{
"gateway"};
564 auto const usd = gw[
"USD"];
565 auto const baseFee = env.
current()->fees().base;
566 env.
fund(
XRP(10'000), alice, bob, gw);
567 env(
fset(gw, asfAllowTrustLineLocking));
569 env.
trust(usd(100000000000000000), alice);
570 env.
trust(usd(100000000000000000), bob);
572 env(
pay(gw, alice, usd(10000000000000000)));
573 env(
pay(gw, bob, usd(1)));
576 bool const largeMantissa =
577 features[featureSingleAssetVault] || features[featureLendingProtocol];
598 Env env{*
this, features};
599 auto const baseFee = env.
current()->fees().base;
600 auto const alice =
Account(
"alice");
601 auto const bob =
Account(
"bob");
602 auto const gw =
Account{
"gateway"};
603 auto const usd = gw[
"USD"];
604 auto const aliceUSD = alice[
"USD"];
605 auto const bobUSD = bob[
"USD"];
606 env.
fund(
XRP(5000), alice, bob, gw);
607 env(
fset(gw, asfAllowTrustLineLocking));
608 env(
fset(gw, asfRequireAuth));
612 env.
trust(usd(10'000), alice, bob);
614 env(
pay(gw, alice, usd(10'000)));
615 env(
pay(gw, bob, usd(10'000)));
618 auto const seq1 = env.
seq(alice);
626 env(
pay(bob, gw, usd(10'000)));
628 env(
trust(bob, usd(0)));
631 env.
trust(usd(10'000), bob);
645 Env env{*
this, features};
646 auto const baseFee = env.
current()->fees().base;
647 auto const alice =
Account(
"alice");
648 auto const bob =
Account(
"bob");
649 auto const gw =
Account{
"gateway"};
650 auto const usd = gw[
"USD"];
651 env.
fund(
XRP(5000), alice, bob, gw);
652 env(
fset(gw, asfAllowTrustLineLocking));
654 env.
trust(usd(10'000), alice, bob);
656 env(
pay(gw, alice, usd(10'000)));
657 env(
pay(gw, bob, usd(10'000)));
660 auto const seq1 = env.
seq(alice);
669 env(
trust(gw, usd(10'000), bob, tfSetFreeze | tfSetDeepFreeze));
690 Env env{*
this, features};
691 auto const baseFee = env.
current()->fees().base;
692 auto const acctReserve = env.
current()->fees().reserve;
693 auto const incReserve = env.
current()->fees().increment;
694 auto const alice =
Account(
"alice");
695 auto const bob =
Account(
"bob");
696 auto const gw =
Account{
"gateway"};
697 auto const usd = gw[
"USD"];
698 env.
fund(
XRP(5000), alice, gw);
699 env.
fund(acctReserve + (incReserve - 1), bob);
701 env(
fset(gw, asfAllowTrustLineLocking));
703 env.
trust(usd(10'000), alice);
705 env(
pay(gw, alice, usd(10'000)));
708 auto const seq1 = env.
seq(alice);
727 Env env{*
this, features};
728 auto const baseFee = env.
current()->fees().base;
729 auto const alice =
Account(
"alice");
730 auto const bob =
Account(
"bob");
731 auto const gw =
Account{
"gateway"};
732 auto const usd = gw[
"USD"];
733 env.
fund(
XRP(5000), alice, bob, gw);
735 env(
fset(gw, asfAllowTrustLineLocking));
737 env.
trust(usd(10'000), alice);
739 env(
pay(gw, alice, usd(10'000)));
742 auto const seq1 = env.
seq(alice);
761 Env env{*
this, features};
762 auto const baseFee = env.
current()->fees().base;
763 auto const alice =
Account(
"alice");
764 auto const bob =
Account(
"bob");
765 auto const gw =
Account{
"gateway"};
766 auto const usd = gw[
"USD"];
767 env.
fund(
XRP(5000), alice, bob, gw);
769 env(
fset(gw, asfAllowTrustLineLocking));
771 env.
trust(usd(1000), alice, bob);
773 env(
pay(gw, alice, usd(1000)));
776 auto const seq1 = env.
seq(alice);
784 env.
trust(usd(1), bob);
798 Env env{*
this, features};
799 auto const baseFee = env.
current()->fees().base;
800 auto const alice =
Account(
"alice");
801 auto const bob =
Account(
"bob");
802 auto const gw =
Account{
"gateway"};
803 auto const usd = gw[
"USD"];
804 env.
fund(
XRP(5000), alice, bob, gw);
806 env(
fset(gw, asfAllowTrustLineLocking));
808 env.
trust(usd(1000), alice, bob);
810 env(
pay(gw, alice, usd(1000)));
813 auto const seq1 = env.
seq(alice);
821 env.
trust(usd(1), bob);
825 auto const bobPreLimit = env.
limit(bob, usd);
835 BEAST_EXPECT(env.
limit(bob, usd) == bobPreLimit);
848 Env env{*
this, features};
849 auto const baseFee = env.
current()->fees().base;
850 auto const alice =
Account(
"alice");
851 auto const bob =
Account(
"bob");
852 auto const gw =
Account{
"gateway"};
853 auto const usd = gw[
"USD"];
854 auto const aliceUSD = alice[
"USD"];
855 auto const bobUSD = bob[
"USD"];
856 env.
fund(
XRP(5000), alice, bob, gw);
857 env(
fset(gw, asfAllowTrustLineLocking));
858 env(
fset(gw, asfRequireAuth));
862 env.
trust(usd(10'000), alice, bob);
864 env(
pay(gw, alice, usd(10'000)));
865 env(
pay(gw, bob, usd(10'000)));
868 auto const seq1 = env.
seq(alice);
876 env(
pay(alice, gw, usd(9'999)));
878 env(
trust(alice, usd(0)));
881 env.
trust(usd(10'000), alice);
898 Env env{*
this, features};
899 auto const baseFee = env.
current()->fees().base;
900 auto const alice =
Account(
"alice");
901 auto const bob =
Account(
"bob");
903 auto const usd = gw[
"USD"];
905 env.
fund(
XRP(10'000), alice, bob, gw);
908 env(
fset(gw, asfAllowTrustLineLocking));
911 env.
trust(usd(100'000), alice);
912 env.
trust(usd(100'000), bob);
915 env(
pay(gw, alice, usd(10'000)));
918 auto const seq = env.
seq(alice);
925 BEAST_EXPECT(env.
balance(alice, usd) == usd(9'000));
927 env(
pay(alice, gw, usd(9'000)));
930 env(
trust(alice, usd(0)));
934 BEAST_EXPECT(!env.
current()->exists(trustLineKey));
939 auto const expectedResult = env.
current()->rules().enabled(fixCleanup3_2_0)
945 if (env.
current()->rules().enabled(fixCleanup3_2_0))
948 BEAST_EXPECT(env.
current()->exists(trustLineKey));
949 BEAST_EXPECT(env.
balance(alice, usd) == usd(1'000));
962 Env env{*
this, features};
963 auto const baseFee = env.
current()->fees().base;
964 auto const alice =
Account(
"alice");
965 auto const bob =
Account(
"bob");
966 auto const gw =
Account{
"gateway"};
967 auto const usd = gw[
"USD"];
968 env.
fund(
XRP(5000), alice, bob, gw);
969 env(
fset(gw, asfAllowTrustLineLocking));
971 env.
trust(usd(10'000), alice, bob);
973 env(
pay(gw, alice, usd(5'000)));
974 env(
pay(gw, bob, usd(5'000)));
977 auto const outstandingUSD = usd(10'000);
980 auto const seq1 = env.
seq(alice);
982 auto const preAliceUSD = env.
balance(alice, usd);
983 auto const preBobUSD = env.
balance(bob, usd);
991 BEAST_EXPECT(env.
balance(alice, usd) == preAliceUSD - usd(1'000));
992 BEAST_EXPECT(env.
balance(bob, usd) == preBobUSD);
993 BEAST_EXPECT(
issuerBalance(env, gw, usd) == outstandingUSD - usd(1'000));
997 auto const preAliceUSD = env.
balance(alice, usd);
998 auto const preBobUSD = env.
balance(bob, usd);
1006 BEAST_EXPECT(env.
balance(alice, usd) == preAliceUSD);
1007 BEAST_EXPECT(env.
balance(bob, usd) == preBobUSD + usd(1'000));
1008 BEAST_EXPECT(
issuerBalance(env, gw, usd) == outstandingUSD);
1013 auto const seq2 = env.
seq(alice);
1015 auto const preAliceUSD = env.
balance(alice, usd);
1016 auto const preBobUSD = env.
balance(bob, usd);
1025 BEAST_EXPECT(env.
balance(alice, usd) == preAliceUSD - usd(1'000));
1026 BEAST_EXPECT(env.
balance(bob, usd) == preBobUSD);
1027 BEAST_EXPECT(
issuerBalance(env, gw, usd) == outstandingUSD - usd(1'000));
1031 auto const preAliceUSD = env.
balance(alice, usd);
1032 auto const preBobUSD = env.
balance(bob, usd);
1036 BEAST_EXPECT(env.
balance(alice, usd) == preAliceUSD + usd(1'000));
1037 BEAST_EXPECT(env.
balance(bob, usd) == preBobUSD);
1038 BEAST_EXPECT(
issuerBalance(env, gw, usd) == outstandingUSD);
1046 using namespace jtx;
1049 auto const alice =
Account(
"alice");
1050 auto const bob =
Account(
"bob");
1051 auto const carol =
Account(
"carol");
1052 auto const gw =
Account{
"gateway"};
1053 auto const usd = gw[
"USD"];
1057 Env env{*
this, features};
1058 env.
fund(
XRP(5000), alice, bob, carol, gw);
1059 env(
fset(gw, asfAllowTrustLineLocking));
1061 env.
trust(usd(10'000), alice, bob, carol);
1063 env(
pay(gw, alice, usd(5000)));
1064 env(
pay(gw, bob, usd(5000)));
1065 env(
pay(gw, carol, usd(5000)));
1067 auto const aseq = env.
seq(alice);
1068 auto const bseq = env.
seq(bob);
1168 Env env{*
this, features};
1169 env.
fund(
XRP(5000), alice, bob, carol, gw);
1170 env(
fset(gw, asfAllowTrustLineLocking));
1172 env.
trust(usd(10'000), alice, bob, carol);
1174 env(
pay(gw, alice, usd(5000)));
1175 env(
pay(gw, bob, usd(5000)));
1176 env(
pay(gw, carol, usd(5000)));
1178 auto const aseq = env.
seq(alice);
1179 auto const bseq = env.
seq(bob);
1300 testcase(
"IOU Metadata to issuer");
1302 Env env{*
this, features};
1303 env.
fund(
XRP(5000), alice, carol, gw);
1304 env(
fset(gw, asfAllowTrustLineLocking));
1306 env.
trust(usd(10'000), alice, carol);
1308 env(
pay(gw, alice, usd(5000)));
1309 env(
pay(gw, carol, usd(5000)));
1311 auto const aseq = env.
seq(alice);
1374 struct TestAccountData
1388 .hasTrustline =
false,
1394 .hasTrustline =
false,
1400 .hasTrustline =
false,
1406 .hasTrustline =
false,
1412 .hasTrustline =
true,
1418 .hasTrustline =
true,
1424 .hasTrustline =
true,
1430 .hasTrustline =
true,
1434 for (
auto const& t :
tests)
1436 Env env{*
this, features};
1437 auto const baseFee = env.
current()->fees().base;
1438 auto const usd = t.gw[
"USD"];
1439 env.
fund(
XRP(5000), t.src, t.dst, t.gw);
1440 env(
fset(t.gw, asfAllowTrustLineLocking));
1445 env.
trust(usd(100'000), t.src, t.dst);
1449 env.
trust(usd(100'000), t.src);
1453 env(
pay(t.gw, t.src, usd(10'000)));
1455 env(
pay(t.gw, t.dst, usd(10'000)));
1459 auto const seq1 = env.
seq(t.src);
1460 auto const delta = usd(1'000);
1464 Fee(baseFee * 150));
1468 auto const preSrc = env.
balance(t.src, usd);
1469 auto const preDst = env.
balance(t.dst, usd);
1474 Fee(baseFee * 150));
1477 BEAST_EXPECT(env.
balance(t.src, usd) == preSrc);
1478 BEAST_EXPECT(env.
balance(t.dst, usd) == preDst + delta);
1489 struct TestAccountData
1498 auto const gw =
Account{
"gateway"};
1499 auto const alice =
Account{
"alice"};
1500 Env env{*
this, features};
1501 auto const baseFee = env.
current()->fees().base;
1502 auto const usd = gw[
"USD"];
1503 env.
fund(
XRP(5000), alice, gw);
1504 env(
fset(gw, asfAllowTrustLineLocking));
1506 env.
trust(usd(100'000), alice);
1509 env(
pay(gw, alice, usd(10'000)));
1523 {.src =
Account(
"alice2"), .dst =
Account{
"gw0"}, .hasTrustline =
true},
1525 {.src =
Account(
"carol0"), .dst =
Account{
"gw1"}, .hasTrustline =
true},
1527 {.src =
Account(
"dan1"), .dst =
Account{
"gw0"}, .hasTrustline =
true},
1529 {.src =
Account(
"bob0"), .dst =
Account{
"gw1"}, .hasTrustline =
true},
1533 for (
auto const& t : gwDstTests)
1535 Env env{*
this, features};
1536 auto const baseFee = env.
current()->fees().base;
1537 auto const usd = t.dst[
"USD"];
1538 env.
fund(
XRP(5000), t.dst, t.src);
1539 env(
fset(t.dst, asfAllowTrustLineLocking));
1542 env.
trust(usd(100'000), t.src);
1545 env(
pay(t.dst, t.src, usd(10'000)));
1549 auto const seq1 = env.
seq(t.src);
1550 auto const preSrc = env.
balance(t.src, usd);
1554 Fee(baseFee * 150));
1561 Fee(baseFee * 150));
1563 auto const preAmount = 10'000;
1564 BEAST_EXPECT(preSrc == usd(preAmount));
1565 auto const postAmount = 9000;
1566 BEAST_EXPECT(env.
balance(t.src, usd) == usd(postAmount));
1567 BEAST_EXPECT(env.
balance(t.dst, usd) == usd(0));
1572 auto const gw =
Account{
"gateway"};
1573 auto const usd = gw[
"USD"];
1574 Env env{*
this, features};
1575 auto const baseFee = env.
current()->fees().base;
1577 env(
fset(gw, asfAllowTrustLineLocking));
1597 auto const alice =
Account(
"alice");
1598 auto const bob =
Account(
"bob");
1599 auto const carol =
Account(
"carol");
1600 auto const gw =
Account{
"gateway"};
1601 auto const usd = gw[
"USD"];
1605 Env env{*
this, features};
1606 auto const baseFee = env.
current()->fees().base;
1607 env.
fund(
XRP(10'000), alice, bob, gw);
1608 env(
fset(gw, asfAllowTrustLineLocking));
1609 env(
rate(gw, 1.25));
1611 env.
trust(usd(100'000), alice);
1612 env.
trust(usd(100'000), bob);
1614 env(
pay(gw, alice, usd(10'000)));
1615 env(
pay(gw, bob, usd(10'000)));
1619 auto const preAlice = env.
balance(alice, usd);
1620 auto const seq1 = env.
seq(alice);
1621 auto const delta = usd(125);
1625 Fee(baseFee * 150));
1634 Fee(baseFee * 150));
1637 BEAST_EXPECT(env.
balance(alice, usd) == preAlice - delta);
1638 BEAST_EXPECT(env.
balance(bob, usd) == usd(10'100));
1642 Env env{*
this, features};
1643 auto const baseFee = env.
current()->fees().base;
1644 env.
fund(
XRP(10'000), alice, bob, gw);
1645 env(
fset(gw, asfAllowTrustLineLocking));
1646 env(
rate(gw, 1.25));
1648 env.
trust(usd(100'000), alice);
1649 env.
trust(usd(100'000), bob);
1651 env(
pay(gw, alice, usd(10'000)));
1652 env(
pay(gw, bob, usd(10'000)));
1656 auto const preAlice = env.
balance(alice, usd);
1657 auto const seq1 = env.
seq(alice);
1658 auto const delta = usd(125);
1662 Fee(baseFee * 150));
1668 env(
rate(gw, 1.26));
1675 Fee(baseFee * 150));
1678 BEAST_EXPECT(env.
balance(alice, usd) == preAlice - delta);
1679 BEAST_EXPECT(env.
balance(bob, usd) == usd(10'100));
1684 Env env{*
this, features};
1685 auto const baseFee = env.
current()->fees().base;
1686 env.
fund(
XRP(10'000), alice, bob, gw);
1687 env(
fset(gw, asfAllowTrustLineLocking));
1688 env(
rate(gw, 1.25));
1690 env.
trust(usd(100'000), alice);
1691 env.
trust(usd(100'000), bob);
1693 env(
pay(gw, alice, usd(10'000)));
1694 env(
pay(gw, bob, usd(10'000)));
1698 auto const preAlice = env.
balance(alice, usd);
1699 auto const seq1 = env.
seq(alice);
1700 auto const delta = usd(125);
1704 Fee(baseFee * 150));
1710 env(
rate(gw, 1.00));
1717 Fee(baseFee * 150));
1720 BEAST_EXPECT(env.
balance(alice, usd) == preAlice - delta);
1721 BEAST_EXPECT(env.
balance(bob, usd) == usd(10125));
1726 Env env{*
this, features};
1727 auto const baseFee = env.
current()->fees().base;
1728 env.
fund(
XRP(10'000), alice, bob, gw);
1729 env(
fset(gw, asfAllowTrustLineLocking));
1730 env(
rate(gw, 1.25));
1732 env.
trust(usd(100'000), alice);
1733 env.
trust(usd(100'000), bob);
1735 env(
pay(gw, alice, usd(10'000)));
1736 env(
pay(gw, bob, usd(10'000)));
1740 auto const preAlice = env.
balance(alice, usd);
1741 auto const seq1 = env.
seq(alice);
1742 auto const delta = usd(125);
1752 env(
rate(gw, 1.00));
1759 BEAST_EXPECT(env.
balance(alice, usd) == preAlice);
1760 BEAST_EXPECT(env.
balance(bob, usd) == usd(10000));
1771 auto const alice =
Account(
"alice");
1772 auto const bob =
Account(
"bob");
1773 auto const gw =
Account{
"gateway"};
1774 auto const usd = gw[
"USD"];
1778 Env env{*
this, features};
1779 auto const baseFee = env.
current()->fees().base;
1780 env.
fund(
XRP(1'000), alice, bob, gw);
1781 env(
fset(gw, asfAllowTrustLineLocking));
1783 env.
trust(usd(10'000), alice, bob);
1785 env(
pay(gw, alice, usd(1'000)));
1786 env(
pay(gw, bob, usd(1'000)));
1790 auto seq1 = env.
seq(alice);
1791 auto const delta = usd(125);
1795 Fee(baseFee * 150));
1799 auto const preBobLimit = env.
limit(bob, usd);
1803 Fee(baseFee * 150));
1805 auto const postBobLimit = env.
limit(bob, usd);
1807 BEAST_EXPECT(postBobLimit == preBobLimit);
1818 auto const alice =
Account(
"alice");
1819 auto const bob =
Account(
"bob");
1820 auto const carol =
Account(
"carol");
1821 auto const gw =
Account{
"gateway"};
1822 auto const usd = gw[
"USD"];
1824 auto const aliceUSD = alice[
"USD"];
1825 auto const bobUSD = bob[
"USD"];
1827 Env env{*
this, features};
1828 auto const baseFee = env.
current()->fees().base;
1829 env.
fund(
XRP(1'000), alice, bob, gw);
1830 env(
fset(gw, asfAllowTrustLineLocking));
1831 env(
fset(gw, asfRequireAuth));
1834 env(
trust(alice, usd(10'000)));
1835 env(
trust(bob, usd(10'000)));
1837 env(
pay(gw, alice, usd(1'000)));
1841 auto seq1 = env.
seq(alice);
1842 auto const delta = usd(125);
1852 env(
trust(bob, usd(10'000)));
1854 env(
pay(gw, bob, usd(1'000)));
1858 seq1 = env.
seq(alice);
1862 Fee(baseFee * 150));
1869 Fee(baseFee * 150));
1880 auto const alice =
Account(
"alice");
1881 auto const bob =
Account(
"bob");
1882 auto const carol =
Account(
"carol");
1883 auto const gw =
Account{
"gateway"};
1884 auto const usd = gw[
"USD"];
1888 Env env{*
this, features};
1889 auto const baseFee = env.
current()->fees().base;
1890 env.
fund(
XRP(10'000), alice, bob, gw);
1891 env(
fset(gw, asfAllowTrustLineLocking));
1893 env.
trust(usd(100'000), alice);
1894 env.
trust(usd(100'000), bob);
1896 env(
pay(gw, alice, usd(10'000)));
1897 env(
pay(gw, bob, usd(10'000)));
1899 env(
fset(gw, asfGlobalFreeze));
1903 auto seq1 = env.
seq(alice);
1904 auto const delta = usd(125);
1915 env(
fclear(gw, asfGlobalFreeze));
1919 seq1 = env.
seq(alice);
1923 Fee(baseFee * 150));
1927 env(
fset(gw, asfGlobalFreeze));
1934 Fee(baseFee * 150));
1938 env(
fclear(gw, asfGlobalFreeze));
1942 seq1 = env.
seq(alice);
1946 Fee(baseFee * 150));
1950 env(
fset(gw, asfGlobalFreeze));
1961 Env env{*
this, features};
1962 auto const baseFee = env.
current()->fees().base;
1963 env.
fund(
XRP(10'000), alice, bob, gw);
1964 env(
fset(gw, asfAllowTrustLineLocking));
1966 env(
trust(alice, usd(100'000)));
1967 env(
trust(bob, usd(100'000)));
1969 env(
pay(gw, alice, usd(10'000)));
1970 env(
pay(gw, bob, usd(10'000)));
1974 env(
trust(gw, usd(10'000), alice, tfSetFreeze));
1978 auto seq1 = env.
seq(alice);
1979 auto const delta = usd(125);
1990 env(
trust(gw, usd(10'000), alice, tfClearFreeze));
1994 seq1 = env.
seq(alice);
1998 Fee(baseFee * 150));
2002 env(
trust(gw, usd(10'000), bob, tfSetFreeze));
2009 Fee(baseFee * 150));
2013 env(
trust(gw, usd(10'000), alice, tfClearFreeze));
2014 env(
trust(gw, usd(10'000), bob, tfClearFreeze));
2018 seq1 = env.
seq(alice);
2022 Fee(baseFee * 150));
2026 env(
trust(gw, usd(10'000), bob, tfSetFreeze));
2037 Env env{*
this, features};
2038 auto const baseFee = env.
current()->fees().base;
2039 env.
fund(
XRP(10'000), alice, bob, gw);
2040 env(
fset(gw, asfAllowTrustLineLocking));
2042 env(
trust(alice, usd(100'000)));
2043 env(
trust(bob, usd(100'000)));
2045 env(
pay(gw, alice, usd(10'000)));
2046 env(
pay(gw, bob, usd(10'000)));
2050 env(
trust(gw, usd(10'000), alice, tfSetFreeze | tfSetDeepFreeze));
2054 auto seq1 = env.
seq(alice);
2055 auto const delta = usd(125);
2066 env(
trust(gw, usd(10'000), alice, tfClearFreeze | tfClearDeepFreeze));
2070 seq1 = env.
seq(alice);
2074 Fee(baseFee * 150));
2078 env(
trust(gw, usd(10'000), bob, tfSetFreeze | tfSetDeepFreeze));
2090 env(
trust(gw, usd(10'000), alice, tfClearFreeze | tfClearDeepFreeze));
2091 env(
trust(gw, usd(10'000), bob, tfClearFreeze | tfClearDeepFreeze));
2095 seq1 = env.
seq(alice);
2099 Fee(baseFee * 150));
2103 env(
trust(gw, usd(10'000), bob, tfSetFreeze | tfSetDeepFreeze));
2114 testcase(
"IOU Insufficient Funds");
2118 auto const alice =
Account(
"alice");
2119 auto const bob =
Account(
"bob");
2120 auto const carol =
Account(
"carol");
2121 auto const gw =
Account{
"gateway"};
2122 auto const usd = gw[
"USD"];
2126 Env env{*
this, features};
2127 auto const baseFee = env.
current()->fees().base;
2128 env.
fund(
XRP(10'000), alice, bob, gw);
2129 env(
fset(gw, asfAllowTrustLineLocking));
2131 env.
trust(usd(100'000), alice);
2132 env.
trust(usd(100'000), bob);
2134 env(
pay(gw, alice, usd(10'000)));
2135 env(
pay(gw, bob, usd(10'000)));
2139 auto const delta = usd(1'000);
2143 Fee(baseFee * 150));
2150 Env env{*
this, features};
2151 auto const baseFee = env.
current()->fees().base;
2152 env.
fund(
XRP(10'000), alice, bob, gw);
2153 env(
fset(gw, asfAllowTrustLineLocking));
2155 env.
trust(usd(100'000), alice);
2156 env.
trust(usd(100'000), bob);
2158 env(
pay(gw, alice, usd(10'000)));
2159 env(
pay(gw, bob, usd(10'000)));
2162 auto const delta = usd(1'000);
2166 Fee(baseFee * 150));
2185 auto const alice =
Account(
"alice");
2186 auto const bob =
Account(
"bob");
2187 auto const gw =
Account{
"gateway"};
2188 auto const usd = gw[
"USD"];
2192 Env env(*
this, features);
2193 auto const baseFee = env.
current()->fees().base;
2194 env.
fund(
XRP(10'000), alice, bob, gw);
2195 env(
fset(gw, asfAllowTrustLineLocking));
2197 env.
trust(usd(100000000000000000), alice);
2198 env.
trust(usd(100000000000000000), bob);
2200 env(
pay(gw, alice, usd(10000000000000000)));
2201 env(
pay(gw, bob, usd(1)));
2204 bool const largeMantissa =
2205 features[featureSingleAssetVault] || features[featureLendingProtocol];
2215 auto const seq1 = env.
seq(alice);
2220 Fee(baseFee * 150));
2227 Fee(baseFee * 150));
2237 using namespace jtx;
2240 for (
bool const withTokenEscrow : {
false,
true})
2242 auto const amend = withTokenEscrow ? features : features - featureTokenEscrow;
2243 Env env{*
this, amend};
2244 auto const baseFee = env.
current()->fees().base;
2245 auto const alice =
Account(
"alice");
2246 auto const bob =
Account(
"bob");
2247 auto const gw =
Account(
"gw");
2250 MPTTester mptGw(env, gw, {.holders = {alice}});
2252 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2253 mptGw.authorize({.account = alice});
2254 auto const mpt = mptGw[
"MPT"];
2255 env(
pay(gw, alice, mpt(10'000)));
2261 auto const seq1 = env.
seq(alice);
2274 auto const seq2 = env.
seq(alice);
2294 for (
bool const withMPT : {
true,
false})
2296 auto const amend = withMPT ? features : features - featureMPTokensV1;
2297 Env env{*
this, amend};
2298 auto const baseFee = env.
current()->fees().base;
2299 auto const alice =
Account(
"alice");
2300 auto const bob =
Account(
"bob");
2301 auto const gw =
Account(
"gw");
2302 env.
fund(
XRP(1'000), alice, bob, gw);
2306 jv[jss::Amount][jss::mpt_issuance_id] =
2307 "00000004A407AF5856CCF3C42619DAA925813FC955C72983";
2308 jv[jss::Amount][jss::value] =
"-1";
2321 Env env{*
this, features};
2322 auto const baseFee = env.
current()->fees().base;
2323 auto const alice =
Account(
"alice");
2324 auto const bob =
Account(
"bob");
2325 auto const gw =
Account(
"gw");
2327 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2329 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2330 mptGw.authorize({.account = alice});
2331 mptGw.authorize({.account = bob});
2332 auto const mpt = mptGw[
"MPT"];
2333 env(
pay(gw, alice, mpt(10'000)));
2334 env(
pay(gw, bob, mpt(10'000)));
2355 Env env{*
this, features};
2356 auto const baseFee = env.
current()->fees().base;
2357 auto const alice =
Account(
"alice");
2358 auto const gw =
Account(
"gw");
2360 MPTTester mptGw(env, gw, {.holders = {alice}});
2362 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2363 mptGw.authorize({.account = alice});
2364 auto const mpt = mptGw[
"MPT"];
2365 env(
pay(gw, alice, mpt(10'000)));
2378 Env env{*
this, features};
2379 auto const baseFee = env.
current()->fees().base;
2380 auto const alice =
Account(
"alice");
2381 auto const bob =
Account(
"bob");
2382 auto const gw =
Account(
"gw");
2383 env.
fund(
XRP(10'000), alice, bob, gw);
2388 jv[jss::Amount][jss::mpt_issuance_id] =
2389 "00000004A407AF5856CCF3C42619DAA925813FC955C72983";
2400 Env env{*
this, features};
2401 auto const baseFee = env.
current()->fees().base;
2402 auto const alice =
Account(
"alice");
2403 auto const bob =
Account(
"bob");
2404 auto const gw =
Account(
"gw");
2406 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2407 mptGw.
create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer});
2408 mptGw.authorize({.account = alice});
2409 mptGw.authorize({.account = bob});
2410 auto const mpt = mptGw[
"MPT"];
2411 env(
pay(gw, alice, mpt(10'000)));
2412 env(
pay(gw, bob, mpt(10'000)));
2425 Env env{*
this, features};
2426 auto const baseFee = env.
current()->fees().base;
2427 auto const alice =
Account(
"alice");
2428 auto const bob =
Account(
"bob");
2429 auto const gw =
Account(
"gw");
2431 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2433 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2434 auto const mpt = mptGw[
"MPT"];
2446 Env env{*
this, features};
2447 auto const baseFee = env.
current()->fees().base;
2448 auto const alice =
Account(
"alice");
2449 auto const bob =
Account(
"bob");
2450 auto const gw =
Account(
"gw");
2452 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2456 .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth});
2457 mptGw.authorize({.account = alice});
2458 mptGw.authorize({.account = gw, .holder = alice});
2459 auto const mpt = mptGw[
"MPT"];
2460 env(
pay(gw, alice, mpt(10'000)));
2464 mptGw.authorize({.account = gw, .holder = alice, .flags = tfMPTUnauthorize});
2476 Env env{*
this, features};
2477 auto const baseFee = env.
current()->fees().base;
2478 auto const alice =
Account(
"alice");
2479 auto const bob =
Account(
"bob");
2480 auto const gw =
Account(
"gw");
2482 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2486 .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth});
2487 mptGw.authorize({.account = alice});
2488 mptGw.authorize({.account = gw, .holder = alice});
2489 mptGw.authorize({.account = bob});
2490 mptGw.authorize({.account = gw, .holder = bob});
2491 auto const mpt = mptGw[
"MPT"];
2492 env(
pay(gw, alice, mpt(10'000)));
2493 env(
pay(gw, bob, mpt(10'000)));
2497 mptGw.authorize({.account = gw, .holder = bob, .flags = tfMPTUnauthorize});
2509 Env env{*
this, features};
2510 auto const baseFee = env.
current()->fees().base;
2511 auto const alice =
Account(
"alice");
2512 auto const bob =
Account(
"bob");
2513 auto const gw =
Account(
"gw");
2515 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2519 .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTCanLock});
2520 mptGw.authorize({.account = alice});
2521 mptGw.authorize({.account = bob});
2522 auto const mpt = mptGw[
"MPT"];
2523 env(
pay(gw, alice, mpt(10'000)));
2524 env(
pay(gw, bob, mpt(10'000)));
2528 mptGw.set({.account = gw, .holder = alice, .flags = tfMPTLock});
2540 Env env{*
this, features};
2541 auto const baseFee = env.
current()->fees().base;
2542 auto const alice =
Account(
"alice");
2543 auto const bob =
Account(
"bob");
2544 auto const gw =
Account(
"gw");
2546 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2550 .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTCanLock});
2551 mptGw.authorize({.account = alice});
2552 mptGw.authorize({.account = bob});
2553 auto const mpt = mptGw[
"MPT"];
2554 env(
pay(gw, alice, mpt(10'000)));
2555 env(
pay(gw, bob, mpt(10'000)));
2559 mptGw.set({.account = gw, .holder = bob, .flags = tfMPTLock});
2571 Env env{*
this, features};
2572 auto const baseFee = env.
current()->fees().base;
2573 auto const alice =
Account(
"alice");
2574 auto const bob =
Account(
"bob");
2575 auto const gw =
Account(
"gw");
2577 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2578 mptGw.
create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow});
2579 mptGw.authorize({.account = alice});
2580 mptGw.authorize({.account = bob});
2581 auto const mpt = mptGw[
"MPT"];
2582 env(
pay(gw, alice, mpt(10'000)));
2583 env(
pay(gw, bob, mpt(10'000)));
2596 Env env{*
this, features};
2597 auto const baseFee = env.
current()->fees().base;
2598 auto const alice =
Account(
"alice");
2599 auto const bob =
Account(
"bob");
2600 auto const gw =
Account(
"gw");
2602 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2604 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2605 mptGw.authorize({.account = alice});
2606 mptGw.authorize({.account = bob});
2607 auto const mpt = mptGw[
"MPT"];
2608 env(
pay(gw, bob, mpt(10)));
2621 Env env{*
this, features};
2622 auto const baseFee = env.
current()->fees().base;
2623 auto const alice =
Account(
"alice");
2624 auto const bob =
Account(
"bob");
2625 auto const gw =
Account(
"gw");
2627 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2629 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2630 mptGw.authorize({.account = alice});
2631 mptGw.authorize({.account = bob});
2632 auto const mpt = mptGw[
"MPT"];
2633 env(
pay(gw, alice, mpt(10)));
2634 env(
pay(gw, bob, mpt(10)));
2655 Env env{*
this, features};
2656 auto const baseFee = env.
current()->fees().base;
2657 auto const alice =
Account(
"alice");
2658 auto const bob =
Account(
"bob");
2659 auto const gw =
Account(
"gw");
2661 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2665 .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth});
2666 mptGw.authorize({.account = alice});
2667 mptGw.authorize({.account = gw, .holder = alice});
2668 mptGw.authorize({.account = bob});
2669 mptGw.authorize({.account = gw, .holder = bob});
2670 auto const mpt = mptGw[
"MPT"];
2671 env(
pay(gw, alice, mpt(10'000)));
2672 env(
pay(gw, bob, mpt(10'000)));
2675 auto const seq1 = env.
seq(alice);
2684 mptGw.authorize({.account = gw, .holder = bob, .flags = tfMPTUnauthorize});
2696 Env env{*
this, features};
2697 auto const baseFee = env.
current()->fees().base;
2698 auto const alice =
Account(
"alice");
2699 auto const bob =
Account(
"bob");
2700 env.
fund(
XRP(10'000), alice, bob);
2703 auto const seq1 = env.
seq(alice);
2710 sleNew->setAccountID(sfDestination, bob);
2711 sleNew->setFieldAmount(sfAmount, amt);
2727 Env env{*
this, features};
2728 auto const baseFee = env.
current()->fees().base;
2729 auto const alice =
Account(
"alice");
2730 auto const bob =
Account(
"bob");
2731 auto const gw =
Account(
"gw");
2733 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2737 .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTCanLock});
2738 mptGw.authorize({.account = alice});
2739 mptGw.authorize({.account = bob});
2740 auto const mpt = mptGw[
"MPT"];
2741 env(
pay(gw, alice, mpt(10'000)));
2742 env(
pay(gw, bob, mpt(10'000)));
2745 auto const seq1 = env.
seq(alice);
2754 mptGw.set({.account = gw, .holder = bob, .flags = tfMPTLock});
2774 Env env{*
this, features};
2775 auto const baseFee = env.
current()->fees().base;
2776 auto const acctReserve = env.
current()->fees().reserve;
2777 auto const incReserve = env.
current()->fees().increment;
2779 auto const alice =
Account(
"alice");
2780 auto const bob =
Account(
"bob");
2781 auto const gw =
Account(
"gw");
2782 env.
fund(acctReserve + (incReserve - 1), bob);
2785 MPTTester mptGw(env, gw, {.holders = {alice}});
2787 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2788 mptGw.authorize({.account = alice});
2789 auto const mpt = mptGw[
"MPT"];
2790 env(
pay(gw, alice, mpt(10'000)));
2793 auto const seq1 = env.
seq(alice);
2811 Env env{*
this, features};
2812 auto const baseFee = env.
current()->fees().base;
2813 auto const alice =
Account(
"alice");
2814 auto const bob =
Account(
"bob");
2815 auto const gw =
Account(
"gw");
2819 MPTTester mptGw(env, gw, {.holders = {alice}});
2821 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2822 mptGw.authorize({.account = alice});
2823 auto const mpt = mptGw[
"MPT"];
2824 env(
pay(gw, alice, mpt(10'000)));
2827 auto const seq1 = env.
seq(alice);
2845 Env env{*
this, features};
2846 auto const baseFee = env.
current()->fees().base;
2847 auto const alice =
Account(
"alice");
2848 auto const bob =
Account(
"bob");
2849 auto const carol =
Account(
"carol");
2850 auto const gw =
Account(
"gw");
2851 env.
fund(
XRP(10'000), bob, carol);
2854 MPTTester mptGw(env, gw, {.holders = {alice}});
2856 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2857 mptGw.authorize({.account = alice});
2858 auto const mpt = mptGw[
"MPT"];
2859 env(
pay(gw, alice, mpt(10'000)));
2862 auto const seq1 = env.
seq(alice);
2888 Env env{*
this, features};
2889 auto const baseFee = env.
current()->fees().base;
2890 auto const alice =
Account(
"alice");
2891 auto const bob =
Account(
"bob");
2892 auto const gw =
Account(
"gw");
2894 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2898 .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth});
2899 mptGw.authorize({.account = alice});
2900 mptGw.authorize({.account = gw, .holder = alice});
2901 mptGw.authorize({.account = bob});
2902 mptGw.authorize({.account = gw, .holder = bob});
2903 auto const mpt = mptGw[
"MPT"];
2904 env(
pay(gw, alice, mpt(10'000)));
2905 env(
pay(gw, bob, mpt(10'000)));
2908 auto const seq1 = env.
seq(alice);
2917 mptGw.authorize({.account = gw, .holder = alice, .flags = tfMPTUnauthorize});
2925 Env env{*
this, features};
2926 auto const baseFee = env.
current()->fees().base;
2927 auto const alice =
Account(
"alice");
2928 auto const bob =
Account(
"bob");
2929 env.
fund(
XRP(10'000), alice, bob);
2931 auto const seq1 = env.
seq(alice);
2938 sleNew->setAccountID(sfDestination, bob);
2939 sleNew->setFieldAmount(sfAmount, amt);
2955 using namespace jtx;
2958 Env env{*
this, features};
2959 auto const baseFee = env.
current()->fees().base;
2960 auto const alice =
Account(
"alice");
2961 auto const bob =
Account(
"bob");
2962 auto const carol =
Account(
"carol");
2963 auto const gw =
Account(
"gw");
2966 MPTTester mptGw(env, gw, {.holders = {alice, carol}});
2968 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2969 mptGw.authorize({.account = alice});
2970 mptGw.authorize({.account = carol});
2971 auto const mpt = mptGw[
"MPT"];
2972 env(
pay(gw, alice, mpt(10'000)));
2973 env(
pay(gw, carol, mpt(10'000)));
2976 auto outstandingMPT = env.
balance(gw, mpt);
2979 auto const seq1 = env.
seq(alice);
2981 auto const preAliceMPT = env.
balance(alice, mpt);
2982 auto const preBobMPT = env.
balance(bob, mpt);
2990 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT - mpt(1'000));
2991 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == 1'000);
2992 BEAST_EXPECT(env.
balance(bob, mpt) == preBobMPT);
2994 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
2998 auto const preAliceMPT = env.
balance(alice, mpt);
2999 auto const preBobMPT = env.
balance(bob, mpt);
3007 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT);
3009 BEAST_EXPECT(env.
balance(bob, mpt) == preBobMPT + mpt(1'000));
3011 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3016 auto const seq2 = env.
seq(alice);
3018 auto const preAliceMPT = env.
balance(alice, mpt);
3019 auto const preBobMPT = env.
balance(bob, mpt);
3028 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT - mpt(1'000));
3029 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == 1'000);
3030 BEAST_EXPECT(env.
balance(bob, mpt) == preBobMPT);
3032 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3036 auto const preAliceMPT = env.
balance(alice, mpt);
3037 auto const preBobMPT = env.
balance(bob, mpt);
3041 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT + mpt(1'000));
3043 BEAST_EXPECT(env.
balance(bob, mpt) == preBobMPT);
3045 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3051 auto const seq = env.
seq(alice);
3052 auto const preAliceMPT = env.
balance(alice, mpt);
3060 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT - mpt(1'000));
3061 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == 1'000);
3062 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3072 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT);
3074 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3080 auto const seq = env.
seq(alice);
3081 auto const preAliceMPT = env.
balance(alice, mpt);
3090 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT - mpt(1'000));
3091 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == 1'000);
3092 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3098 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT);
3100 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3106 auto const preAliceMPT = env.
balance(alice, mpt);
3107 auto const preBobMPT = env.
balance(bob, mpt);
3108 auto const preCarolMPT = env.
balance(carol, mpt);
3123 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT - mpt(1'000));
3124 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == 1'000);
3125 BEAST_EXPECT(env.
balance(bob, mpt) == preBobMPT);
3127 BEAST_EXPECT(env.
balance(carol, mpt) == preCarolMPT - mpt(1'000));
3128 BEAST_EXPECT(
mptEscrowed(env, carol, mpt) == 1'000);
3129 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3135 Env env{*
this, features};
3136 auto const baseFee = env.
current()->fees().base;
3137 auto const alice =
Account(
"alice");
3138 auto const bob =
Account(
"bob");
3139 auto const gw =
Account(
"gw");
3141 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
3143 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3144 mptGw.authorize({.account = alice});
3145 mptGw.authorize({.account = bob});
3146 auto const mpt = mptGw[
"MPT"];
3150 auto const preAliceMPT = env.
balance(alice, mpt);
3151 auto const preBobMPT = env.
balance(bob, mpt);
3152 auto const outstandingMPT = env.
balance(gw, mpt);
3154 auto const seq1 = env.
seq(alice);
3158 Fee(baseFee * 150));
3161 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT - mpt(1));
3163 BEAST_EXPECT(env.
balance(bob, mpt) == preBobMPT);
3165 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3175 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT - mpt(1));
3179 BEAST_EXPECT(env.
balance(bob, mpt) == preBobMPT + mpt(1));
3181 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3189 Env env{*
this, features};
3190 auto const baseFee = env.
current()->fees().base;
3191 auto const alice =
Account(
"alice");
3192 auto const bob =
Account(
"bob");
3193 auto const gw =
Account(
"gw");
3195 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
3197 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3198 mptGw.authorize({.account = alice});
3199 mptGw.authorize({.account = bob});
3200 auto const mpt = mptGw[
"MPT"];
3204 auto const preAliceMPT = env.
balance(alice, mpt);
3205 auto const preBobMPT = env.
balance(bob, mpt);
3206 auto const outstandingMPT = env.
balance(gw, mpt);
3209 auto const seq1 = env.
seq(alice);
3213 Fee(baseFee * 150));
3217 auto const seq2 = env.
seq(alice);
3221 Fee(baseFee * 150));
3226 BEAST_EXPECT(env.
balance(bob, mpt) == preBobMPT);
3228 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3249 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3257 using namespace jtx;
3260 auto const alice =
Account(
"alice");
3261 auto const bob =
Account(
"bob");
3262 auto const carol =
Account(
"carol");
3263 auto const gw =
Account{
"gateway"};
3267 Env env{*
this, features};
3268 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
3270 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3271 mptGw.authorize({.account = alice});
3272 mptGw.authorize({.account = bob});
3273 auto const mpt = mptGw[
"MPT"];
3274 env(
pay(gw, alice, mpt(10'000)));
3275 env(
pay(gw, bob, mpt(10'000)));
3277 auto const aseq = env.
seq(alice);
3278 auto const bseq = env.
seq(bob);
3359 Env env{*
this, features};
3360 MPTTester mptGw(env, gw, {.holders = {alice, bob, carol}});
3362 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3363 mptGw.authorize({.account = alice});
3364 mptGw.authorize({.account = bob});
3365 mptGw.authorize({.account = carol});
3366 auto const mpt = mptGw[
"MPT"];
3367 env(
pay(gw, alice, mpt(10'000)));
3368 env(
pay(gw, bob, mpt(10'000)));
3369 env(
pay(gw, carol, mpt(10'000)));
3371 auto const aseq = env.
seq(alice);
3372 auto const bseq = env.
seq(bob);
3475 Env env{*
this, features};
3476 auto const baseFee = env.
current()->fees().base;
3477 auto const alice =
Account(
"alice");
3478 auto const gw =
Account(
"gw");
3480 MPTTester mptGw(env, gw, {.holders = {alice}});
3482 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3483 mptGw.authorize({.account = alice});
3484 auto const mpt = mptGw[
"MPT"];
3485 env(
pay(gw, alice, mpt(10'000)));
3489 auto const seq1 = env.
seq(alice);
3490 auto const preAliceMPT = env.
balance(alice, mpt);
3491 auto const preOutstanding = env.
balance(gw, mpt);
3493 BEAST_EXPECT(preOutstanding == mpt(-10'000));
3494 BEAST_EXPECT(preEscrowed == 0);
3499 Fee(baseFee * 150));
3502 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT - mpt(1'000));
3503 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == 1'000);
3504 BEAST_EXPECT(env.
balance(gw, mpt) == preOutstanding);
3511 Fee(baseFee * 150));
3514 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT - mpt(1'000));
3516 BEAST_EXPECT(env.
balance(gw, mpt) == preOutstanding + mpt(1'000));
3528 auto const alice =
Account(
"alice");
3529 auto const bob =
Account(
"bob");
3530 auto const carol =
Account(
"carol");
3531 auto const gw =
Account{
"gateway"};
3532 auto const usd = gw[
"USD"];
3536 Env env{*
this, features};
3537 auto const baseFee = env.
current()->fees().base;
3538 auto const alice =
Account(
"alice");
3539 auto const bob =
Account(
"bob");
3540 auto const gw =
Account(
"gw");
3542 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
3544 {.transferFee = 25000,
3547 .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3548 mptGw.authorize({.account = alice});
3549 mptGw.authorize({.account = bob});
3550 auto const mpt = mptGw[
"MPT"];
3551 env(
pay(gw, alice, mpt(10'000)));
3552 env(
pay(gw, bob, mpt(10'000)));
3556 auto const preAlice = env.
balance(alice, mpt);
3557 auto const seq1 = env.
seq(alice);
3558 auto const delta = mpt(125);
3562 Fee(baseFee * 150));
3567 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == 125);
3569 BEAST_EXPECT(env.
balance(gw, mpt) == mpt(-20'000));
3575 Fee(baseFee * 150));
3578 BEAST_EXPECT(env.
balance(alice, mpt) == preAlice - delta);
3579 BEAST_EXPECT(env.
balance(bob, mpt) == mpt(10'100));
3581 auto const escrowedWithFix = env.
current()->rules().enabled(fixTokenEscrowV1) ? 0 : 25;
3582 auto const outstandingWithFix =
3583 env.
current()->rules().enabled(fixTokenEscrowV1) ? mpt(19'975) : mpt(20'000);
3584 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == escrowedWithFix);
3586 BEAST_EXPECT(env.
balance(gw, mpt) == -outstandingWithFix);
3591 Env env{*
this, features};
3592 auto const baseFee = env.
current()->fees().base;
3593 auto const alice =
Account(
"alice");
3594 auto const bob =
Account(
"bob");
3595 auto const gw =
Account(
"gw");
3597 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
3599 {.transferFee = 25000,
3602 .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3603 mptGw.authorize({.account = alice});
3604 mptGw.authorize({.account = bob});
3605 auto const mpt = mptGw[
"MPT"];
3606 env(
pay(gw, alice, mpt(10'000)));
3607 env(
pay(gw, bob, mpt(10'000)));
3611 auto const preAlice = env.
balance(alice, mpt);
3612 auto const preBob = env.
balance(bob, mpt);
3613 auto const seq1 = env.
seq(alice);
3614 auto const delta = mpt(125);
3619 Fee(baseFee * 150));
3628 BEAST_EXPECT(env.
balance(alice, mpt) == preAlice);
3629 BEAST_EXPECT(env.
balance(bob, mpt) == preBob);
3630 BEAST_EXPECT(env.
balance(gw, mpt) == mpt(-20'000));
3637 Env env{*
this, features};
3638 auto const baseFee = env.
current()->fees().base;
3639 auto const alice =
Account(
"alice");
3640 auto const bob =
Account(
"bob");
3641 auto const gw =
Account(
"gw");
3643 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
3645 {.transferFee = 25000,
3648 .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3649 mptGw.authorize({.account = alice});
3650 mptGw.authorize({.account = bob});
3651 auto const mpt = mptGw[
"MPT"];
3652 env(
pay(gw, alice, mpt(10'000)));
3653 env(
pay(gw, bob, mpt(10'000)));
3657 auto const preAlice = env.
balance(alice, mpt);
3658 auto const seq1 = env.
seq(alice);
3659 auto const delta = mpt(125);
3663 Fee(baseFee * 150));
3668 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == 125);
3670 BEAST_EXPECT(env.
balance(gw, mpt) == mpt(-20'000));
3676 Fee(baseFee * 150));
3679 BEAST_EXPECT(env.
balance(alice, mpt) == preAlice - delta);
3682 BEAST_EXPECT(env.
balance(gw, mpt) == mpt(-19'875));
3692 bool const withCleanup340 = features[fixCleanup3_4_0];
3695 (withCleanup340 ?
"with Cleanup340" :
"without Cleanup340"));
3697 Env env{*
this, features};
3698 auto const baseFee = env.
current()->fees().base;
3699 auto const alice =
Account(
"alice");
3700 auto const bob =
Account(
"bob");
3701 auto const gw =
Account(
"gw");
3702 env.
fund(
XRP(1'000), alice, bob, gw);
3708 .holders = {alice, bob},
3709 .transferFee = 1'000,
3710 .flags = tfMPTCanEscrow | tfMPTCanTransfer,
3712 env(
pay(gw, alice, mpt(10'000)));
3715 static constexpr int escrowCount = 10;
3716 static constexpr int splitAmount = 10;
3717 static constexpr int totalLocked = escrowCount * splitAmount;
3719 for (
auto& seq : seqs)
3721 seq = env.
seq(alice);
3725 Fee(baseFee * 150));
3729 BEAST_EXPECT(env.
balance(alice, mpt) == mpt(10'000 - totalLocked));
3730 BEAST_EXPECT(env.
balance(bob, mpt) == mpt(0));
3731 BEAST_EXPECT(env.
balance(gw, mpt) == mpt(-10'000));
3732 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == totalLocked);
3735 for (
auto const seq : seqs)
3740 Fee(baseFee * 150));
3744 auto const feeBurned = withCleanup340 ? escrowCount : 0;
3745 BEAST_EXPECT(env.
balance(alice, mpt) == mpt(10'000 - totalLocked));
3746 BEAST_EXPECT(env.
balance(bob, mpt) == mpt(totalLocked - feeBurned));
3747 BEAST_EXPECT(env.
balance(gw, mpt) == mpt(-10'000 + feeBurned));
3759 auto constexpr escrowAmount = 200'000'000'000'000'000LL;
3760 auto constexpr noOverflowEscrowAmount = 186'000'000'000'000'000LL;
3761 auto const alice =
Account(
"alice");
3762 auto const bob =
Account(
"bob");
3763 auto const gw =
Account(
"gw");
3765 for (
auto const testFeatures :
3766 {features - featureMPTokensV2 - fixCleanup3_4_0,
3767 features - featureMPTokensV2,
3768 (features | featureMPTokensV2) - fixCleanup3_4_0,
3769 features | featureMPTokensV2})
3771 bool const mptV2 = testFeatures[featureMPTokensV2];
3772 bool const tokenEscrowV1 = testFeatures[fixTokenEscrowV1];
3779 bool const cleanup340 = testFeatures[fixCleanup3_4_0];
3780 bool const noOverflow = cleanup340 || mptV2;
3788 Env env{*
this, testFeatures};
3789 env.
fund(
XRP(1'000), alice, bob, gw);
3790 auto const baseFee = env.
current()->fees().base;
3795 .holders = {alice, bob},
3796 .transferFee = 1'000,
3797 .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3798 env(
pay(gw, alice, mpt(escrowAmount)));
3801 auto const preAlice = env.
balance(alice, mpt);
3802 auto const preBob = env.
balance(bob, mpt);
3803 auto const seq = env.
seq(alice);
3808 Fee(baseFee * 150));
3811 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == escrowAmount);
3824 BEAST_EXPECT(env.
balance(alice, mpt) == preAlice - mpt(escrowAmount));
3825 auto const postBob = env.
balance(bob, mpt);
3826 BEAST_EXPECT(postBob.value() > preBob.value());
3827 BEAST_EXPECT(postBob.value() < (preBob + mpt(escrowAmount)).value());
3828 auto const xferFee = escrowAmount - (postBob.value() - preBob.value());
3829 auto const expectedEscrow = tokenEscrowV1 ? 0 : xferFee;
3830 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == expectedEscrow);
3836 BEAST_EXPECT(env.
balance(alice, mpt) == preAlice - mpt(escrowAmount));
3837 BEAST_EXPECT(env.
balance(bob, mpt) == preBob);
3838 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == escrowAmount);
3846 Env env{*
this, testFeatures};
3847 env.
fund(
XRP(1'000), alice, bob, gw);
3848 auto const baseFee = env.
current()->fees().base;
3853 .holders = {alice, bob},
3854 .transferFee = 1'000,
3855 .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3856 env(
pay(gw, alice, mpt(noOverflowEscrowAmount)));
3859 auto const preAlice = env.
balance(alice, mpt);
3860 auto const preBob = env.
balance(bob, mpt);
3861 auto const seq = env.
seq(alice);
3866 Fee(baseFee * 150));
3869 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == noOverflowEscrowAmount);
3880 BEAST_EXPECT(env.
balance(alice, mpt) == preAlice - mpt(noOverflowEscrowAmount));
3881 auto const postBob = env.
balance(bob, mpt);
3882 BEAST_EXPECT(postBob.value() > preBob.value());
3883 BEAST_EXPECT(postBob.value() < (preBob + mpt(noOverflowEscrowAmount)).value());
3884 auto const xferFee = noOverflowEscrowAmount - (postBob.value() - preBob.value());
3885 auto const expectedEscrow = tokenEscrowV1 ? 0 : xferFee;
3886 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == expectedEscrow);
3893 Env env{*
this, testFeatures};
3894 env.
fund(
XRP(1'000), alice, bob, gw);
3895 auto const baseFee = env.
current()->fees().base;
3900 .holders = {alice, bob},
3901 .transferFee = 1'000,
3902 .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3903 env(
pay(gw, alice, mpt(escrowAmount)));
3906 auto const preAlice = env.
balance(alice, mpt);
3907 auto const preBob = env.
balance(bob, mpt);
3908 auto const seq = env.
seq(alice);
3913 Fee(baseFee * 150));
3916 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == escrowAmount);
3923 BEAST_EXPECT(env.
balance(alice, mpt) == preAlice);
3924 BEAST_EXPECT(env.
balance(bob, mpt) == preBob);
3925 BEAST_EXPECT(env.
balance(gw, mpt) == -mpt(escrowAmount));
3939 Env env{*
this, features};
3940 auto const baseFee = env.
current()->fees().base;
3941 auto const alice =
Account(
"alice");
3942 auto const bob =
Account(
"bob");
3943 auto const gw =
Account(
"gw");
3945 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
3949 .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth});
3950 mptGw.authorize({.account = alice});
3951 mptGw.authorize({.account = gw, .holder = alice});
3952 mptGw.authorize({.account = bob});
3953 mptGw.authorize({.account = gw, .holder = bob});
3954 auto const mpt = mptGw[
"MPT"];
3955 env(
pay(gw, alice, mpt(10'000)));
3958 auto seq = env.
seq(alice);
3959 auto const delta = mpt(125);
3964 Fee(baseFee * 150));
3971 Fee(baseFee * 150));
3982 Env env{*
this, features};
3983 auto const baseFee = env.
current()->fees().base;
3984 auto const alice =
Account(
"alice");
3985 auto const bob =
Account(
"bob");
3986 auto const gw =
Account(
"gw");
3988 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
3992 .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTCanLock});
3993 mptGw.authorize({.account = alice});
3994 mptGw.authorize({.account = bob});
3995 auto const mpt = mptGw[
"MPT"];
3996 env(
pay(gw, alice, mpt(10'000)));
3997 env(
pay(gw, bob, mpt(10'000)));
4001 auto seq1 = env.
seq(alice);
4006 Fee(baseFee * 150));
4010 mptGw.set({.account = gw, .holder = alice, .flags = tfMPTLock});
4011 mptGw.set({.account = gw, .holder = bob, .flags = tfMPTLock});
4033 Env env{*
this, features};
4034 auto const baseFee = env.
current()->fees().base;
4035 auto const alice =
Account(
"alice");
4036 auto const bob =
Account(
"bob");
4037 auto const gw =
Account(
"gw");
4039 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
4040 mptGw.
create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow});
4041 mptGw.authorize({.account = alice});
4042 mptGw.authorize({.account = bob});
4043 auto const mpt = mptGw[
"MPT"];
4044 env(
pay(gw, alice, mpt(10'000)));
4045 env(
pay(gw, bob, mpt(10'000)));
4060 auto seq = env.
seq(alice);
4064 Fee(baseFee * 150));
4071 Fee(baseFee * 150));
4078 auto seq = env.
seq(alice);
4083 Fee(baseFee * 150));
4101 Env env{*
this, features};
4102 auto const baseFee = env.
current()->fees().base;
4103 auto const alice =
Account(
"alice");
4104 auto const bob =
Account(
"bob");
4105 auto const gw =
Account(
"gw");
4107 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
4109 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
4110 mptGw.authorize({.account = alice});
4111 mptGw.authorize({.account = bob});
4112 auto const mpt = mptGw[
"MPT"];
4113 env(
pay(gw, alice, mpt(10'000)));
4114 env(
pay(gw, bob, mpt(10'000)));
4117 auto const seq1 = env.
seq(alice);
4121 Fee(baseFee * 150));
4125 env(
pay(alice, gw, mpt(9'990)));
4126 env(
pay(bob, gw, mpt(10'000)));
4127 BEAST_EXPECT(env.
balance(alice, mpt) == mpt(0));
4129 BEAST_EXPECT(env.
balance(bob, mpt) == mpt(0));
4131 BEAST_EXPECT(env.
balance(gw, mpt) == mpt(-10));
4132 mptGw.authorize({.account = bob, .flags = tfMPTUnauthorize});
4133 mptGw.destroy({.id = mptGw.issuanceID(), .ownerCount = 1, .err =
tecHAS_OBLIGATIONS});
4142 env(
pay(bob, gw, mpt(10)));
4143 mptGw.destroy({.id = mptGw.issuanceID(), .ownerCount = 0});
4148 Env env{*
this, features};
4149 auto const baseFee = env.
current()->fees().base;
4150 auto const alice =
Account(
"alice");
4151 auto const bob =
Account(
"bob");
4152 auto const gw =
Account(
"gw");
4156 MPTTester mptGw(env, gw, {.holders = {alice}});
4158 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
4159 mptGw.authorize({.account = alice});
4160 auto const mpt = mptGw[
"MPT"];
4161 env(
pay(gw, alice, mpt(10'000)));
4164 auto const seq1 = env.
seq(alice);
4172 env(
pay(alice, gw, mpt(9'990)));
4175 BEAST_EXPECT(env.
balance(alice, mpt) == mpt(0));
4187 BEAST_EXPECT(env.
balance(alice, mpt) == mpt(0));
4189 mptGw.authorize({.account = alice, .flags = tfMPTUnauthorize});
4244 {all - featureSingleAssetVault - featureLendingProtocol, all})
A generic endpoint for log messages.
TestcaseT testcase
Memberspace for declaring test cases.
Value removeMember(char const *key)
Remove and return the named member.
A class that simplifies iterating ledger directory pages.
ConstIterator begin() const
ConstIterator end() const
A currency issued by an account.
bool modify(modify_type const &f)
Modify the open ledger.
Writable ledger view that accumulates state and tx changes.
Discardable, editable view to a ledger.
static constexpr SeqProxy rawSequence(std::uint32_t v)
Factory function to return a sequence-based SeqProxy.
virtual OpenLedger & getOpenLedger()=0
void insert(SLE::ref sle) override
Insert a new state SLE.
Immutable cryptographic account descriptor.
A transaction testing environment.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
SLE::const_pointer le(Account const &account) const
Return an account root.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
PrettyAmount limit(Account const &account, Issue const &issue) const
Returns the IOU limit on an account.
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
std::shared_ptr< STObject const > meta()
Return metadata for the last JTx.
void memoize(Account const &account)
Associate AccountID with account.
void require(Args const &... args)
Check a set of requirements.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
NetClock::time_point now()
Returns the current network time.
Converts to IOU Issue or STAmount.
Test helper for creating, mutating, and asserting MPT and confidential MPT ledger state.
void create(MPTCreate const &arg=MPTCreate{})
Converts to MPT Issue or STAmount.
xrpl::MPTID const & mpt() const
Match clear account flags.
Set the expected result code for a JTx The test will fail if the code doesn't match.
Keylet escrow(AccountID const &src, SeqProxy const &seq) noexcept
An escrow entry.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Keylet mptokenIssuance(MPTID const &issuanceID) noexcept
Keylet trustLine(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
json::Value create(AccountID const &account, AccountID const &to, STAmount const &amount)
json::Value cancel(AccountID const &account, Account const &from, std::uint32_t seq)
auto const kCancelTime
Set the "CancelAfter" time tag on a JTx.
Rate rate(Env &env, Account const &account, std::uint32_t const &seq)
auto const kFinishTime
Set the "FinishAfter" time tag on a JTx.
std::array< std::uint8_t, 39 > const kCb2
json::Value finish(AccountID const &account, AccountID const &from, std::uint32_t seq)
std::array< std::uint8_t, 4 > const kFb1
std::array< std::uint8_t, 39 > const kCb1
json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
XrpT const XRP
Converts to XRP Issue or STAmount.
json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
FeatureBitset testableAmendments()
json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
STAmount amountFromString(Asset const &asset, std::string const &amount)
std::string to_string(BaseUInt< Bits, Tag > const &a)
Rate transferRate(ReadView const &view, AccountID const &issuer)
Returns IOU issuer transfer fee as Rate.
MPTID makeMptID(std::uint32_t const sequence, AccountID const &account)
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
TERSubset< CanCvtToTER > TER
@ tecNO_LINE_INSUF_RESERVE
@ tecINSUFFICIENT_RESERVE
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
constexpr std::uint64_t kMaxMpTokenAmount
The maximum amount of MPTokenIssuance.
void testMPTLargeLockedRate(FeatureBitset features)
void testMPTCreatePreclaim(FeatureBitset features)
void testMPTFinishDoApply(FeatureBitset features)
void testMPTMetaAndOwnership(FeatureBitset features)
void testIOUBalances(FeatureBitset features)
void testMPTSplitEscrowTransferFee(FeatureBitset features)
void testIOUCreatePreclaim(FeatureBitset features)
void testMPTGateway(FeatureBitset features)
void testMPTCanTransfer(FeatureBitset features)
void testIOUFinishPreclaim(FeatureBitset features)
static jtx::PrettyAmount issuerEscrowed(jtx::Env &env, jtx::Account const &account, Issue const &issue)
void run() override
Runs the suite.
void testIOUMetaAndOwnership(FeatureBitset features)
void testIOUPrecisionLoss(FeatureBitset features)
void testMPTLock(FeatureBitset features)
void testMPTCancelPreclaim(FeatureBitset features)
void testIOUEnablement(FeatureBitset features)
void testMPTBalances(FeatureBitset features)
static jtx::PrettyAmount issuerBalance(jtx::Env &env, jtx::Account const &account, Issue const &issue)
void testMPTRequireAuth(FeatureBitset features)
void testIOUFinishDoApply(FeatureBitset features)
void testIOUFreeze(FeatureBitset features)
void testMPTEnablement(FeatureBitset features)
static uint64_t mptEscrowed(jtx::Env const &env, jtx::Account const &account, jtx::MPT const &mpt)
void testIOUCancelPreclaim(FeatureBitset features)
void testIOUGateway(FeatureBitset features)
static uint64_t issuerMPTEscrowed(jtx::Env const &env, jtx::MPT const &mpt)
void testIOULimitAmount(FeatureBitset features)
void testIOUAllowLockingFlag(FeatureBitset features)
void testMPTCreatePreflight(FeatureBitset features)
void testIOULockedRate(FeatureBitset features)
void testMPTFinishPreclaim(FeatureBitset features)
void testIOUCancelDoApply(FeatureBitset features)
void testIOUInsufficientFunds(FeatureBitset features)
void testIOUWithFeats(FeatureBitset features)
void testMPTLockedRate(FeatureBitset features)
void testMPTWithFeats(FeatureBitset features)
void testIOUCreatePreflight(FeatureBitset features)
void testIOURequireAuth(FeatureBitset features)
void testMPTDestroy(FeatureBitset features)
void testIOURippleState(FeatureBitset features)
Represents an XRP, IOU, or MPT quantity This customizes the string conversion and supports XRP conver...