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 = features[featureSingleAssetVault] ||
577 features[featureLendingProtocol] || features[featureMPTokensV2];
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));
957 testcase(
"IOU Cancel Reserve Recycle");
964 Env env{*
this, features};
965 bool const fixEnabled = env.
current()->rules().enabled(fixCleanup3_4_0);
967 auto const baseFee = env.
current()->fees().base;
968 auto const alice =
Account(
"alice");
969 auto const bob =
Account(
"bob");
971 auto const usd = gw[
"USD"];
973 env.
fund(
XRP(10'000), alice, bob, gw);
976 env(
fset(gw, asfAllowTrustLineLocking));
979 env.
trust(usd(10'000), alice);
982 env(
pay(gw, alice, usd(10'000)));
986 auto const cancelAfter = env.
now() + 100s;
987 auto const seq = env.
seq(alice);
996 env(
trust(alice, usd(0)));
998 BEAST_EXPECT(!env.
current()->exists(trustLineKey));
1003 auto const oneObject = env.
current()->fees().accountReserve(1, 1);
1004 auto const twoObjects = env.
current()->fees().accountReserve(2, 1);
1006 auto const feeCushion = baseFee.
drops() * 20;
1007 env(
pay(alice, bob,
drops(balance.drops() - oneObject.drops() - feeCushion)));
1012 for (; env.
now() < cancelAfter; env.
close())
1025 BEAST_EXPECT(!env.
le(escrowKey));
1026 BEAST_EXPECT(env.
current()->exists(trustLineKey));
1027 BEAST_EXPECT(env.
balance(alice, usd) == usd(10'000));
1034 BEAST_EXPECT(env.
le(escrowKey) !=
nullptr);
1035 BEAST_EXPECT(!env.
current()->exists(trustLineKey));
1038 env(
pay(bob, alice,
drops(twoObjects.drops() - oneObject.drops())));
1042 BEAST_EXPECT(!env.
le(escrowKey));
1043 BEAST_EXPECT(env.
balance(alice, usd) == usd(10'000));
1052 using namespace jtx;
1055 Env env{*
this, features};
1056 auto const baseFee = env.
current()->fees().base;
1057 auto const alice =
Account(
"alice");
1058 auto const bob =
Account(
"bob");
1059 auto const gw =
Account{
"gateway"};
1060 auto const usd = gw[
"USD"];
1061 env.
fund(
XRP(5000), alice, bob, gw);
1062 env(
fset(gw, asfAllowTrustLineLocking));
1064 env.
trust(usd(10'000), alice, bob);
1066 env(
pay(gw, alice, usd(5'000)));
1067 env(
pay(gw, bob, usd(5'000)));
1070 auto const outstandingUSD = usd(10'000);
1073 auto const seq1 = env.
seq(alice);
1075 auto const preAliceUSD = env.
balance(alice, usd);
1076 auto const preBobUSD = env.
balance(bob, usd);
1084 BEAST_EXPECT(env.
balance(alice, usd) == preAliceUSD - usd(1'000));
1085 BEAST_EXPECT(env.
balance(bob, usd) == preBobUSD);
1086 BEAST_EXPECT(
issuerBalance(env, gw, usd) == outstandingUSD - usd(1'000));
1090 auto const preAliceUSD = env.
balance(alice, usd);
1091 auto const preBobUSD = env.
balance(bob, usd);
1099 BEAST_EXPECT(env.
balance(alice, usd) == preAliceUSD);
1100 BEAST_EXPECT(env.
balance(bob, usd) == preBobUSD + usd(1'000));
1101 BEAST_EXPECT(
issuerBalance(env, gw, usd) == outstandingUSD);
1106 auto const seq2 = env.
seq(alice);
1108 auto const preAliceUSD = env.
balance(alice, usd);
1109 auto const preBobUSD = env.
balance(bob, usd);
1118 BEAST_EXPECT(env.
balance(alice, usd) == preAliceUSD - usd(1'000));
1119 BEAST_EXPECT(env.
balance(bob, usd) == preBobUSD);
1120 BEAST_EXPECT(
issuerBalance(env, gw, usd) == outstandingUSD - usd(1'000));
1124 auto const preAliceUSD = env.
balance(alice, usd);
1125 auto const preBobUSD = env.
balance(bob, usd);
1129 BEAST_EXPECT(env.
balance(alice, usd) == preAliceUSD + usd(1'000));
1130 BEAST_EXPECT(env.
balance(bob, usd) == preBobUSD);
1131 BEAST_EXPECT(
issuerBalance(env, gw, usd) == outstandingUSD);
1139 using namespace jtx;
1142 auto const alice =
Account(
"alice");
1143 auto const bob =
Account(
"bob");
1144 auto const carol =
Account(
"carol");
1145 auto const gw =
Account{
"gateway"};
1146 auto const usd = gw[
"USD"];
1150 Env env{*
this, features};
1151 env.
fund(
XRP(5000), alice, bob, carol, gw);
1152 env(
fset(gw, asfAllowTrustLineLocking));
1154 env.
trust(usd(10'000), alice, bob, carol);
1156 env(
pay(gw, alice, usd(5000)));
1157 env(
pay(gw, bob, usd(5000)));
1158 env(
pay(gw, carol, usd(5000)));
1160 auto const aseq = env.
seq(alice);
1161 auto const bseq = env.
seq(bob);
1261 Env env{*
this, features};
1262 env.
fund(
XRP(5000), alice, bob, carol, gw);
1263 env(
fset(gw, asfAllowTrustLineLocking));
1265 env.
trust(usd(10'000), alice, bob, carol);
1267 env(
pay(gw, alice, usd(5000)));
1268 env(
pay(gw, bob, usd(5000)));
1269 env(
pay(gw, carol, usd(5000)));
1271 auto const aseq = env.
seq(alice);
1272 auto const bseq = env.
seq(bob);
1393 testcase(
"IOU Metadata to issuer");
1395 Env env{*
this, features};
1396 env.
fund(
XRP(5000), alice, carol, gw);
1397 env(
fset(gw, asfAllowTrustLineLocking));
1399 env.
trust(usd(10'000), alice, carol);
1401 env(
pay(gw, alice, usd(5000)));
1402 env(
pay(gw, carol, usd(5000)));
1404 auto const aseq = env.
seq(alice);
1467 struct TestAccountData
1481 .hasTrustline =
false,
1487 .hasTrustline =
false,
1493 .hasTrustline =
false,
1499 .hasTrustline =
false,
1505 .hasTrustline =
true,
1511 .hasTrustline =
true,
1517 .hasTrustline =
true,
1523 .hasTrustline =
true,
1527 for (
auto const& t :
tests)
1529 Env env{*
this, features};
1530 auto const baseFee = env.
current()->fees().base;
1531 auto const usd = t.gw[
"USD"];
1532 env.
fund(
XRP(5000), t.src, t.dst, t.gw);
1533 env(
fset(t.gw, asfAllowTrustLineLocking));
1538 env.
trust(usd(100'000), t.src, t.dst);
1542 env.
trust(usd(100'000), t.src);
1546 env(
pay(t.gw, t.src, usd(10'000)));
1548 env(
pay(t.gw, t.dst, usd(10'000)));
1552 auto const seq1 = env.
seq(t.src);
1553 auto const delta = usd(1'000);
1557 Fee(baseFee * 150));
1561 auto const preSrc = env.
balance(t.src, usd);
1562 auto const preDst = env.
balance(t.dst, usd);
1567 Fee(baseFee * 150));
1570 BEAST_EXPECT(env.
balance(t.src, usd) == preSrc);
1571 BEAST_EXPECT(env.
balance(t.dst, usd) == preDst + delta);
1582 struct TestAccountData
1591 auto const gw =
Account{
"gateway"};
1592 auto const alice =
Account{
"alice"};
1593 Env env{*
this, features};
1594 auto const baseFee = env.
current()->fees().base;
1595 auto const usd = gw[
"USD"];
1596 env.
fund(
XRP(5000), alice, gw);
1597 env(
fset(gw, asfAllowTrustLineLocking));
1599 env.
trust(usd(100'000), alice);
1602 env(
pay(gw, alice, usd(10'000)));
1616 {.src =
Account(
"alice2"), .dst =
Account{
"gw0"}, .hasTrustline =
true},
1618 {.src =
Account(
"carol0"), .dst =
Account{
"gw1"}, .hasTrustline =
true},
1620 {.src =
Account(
"dan1"), .dst =
Account{
"gw0"}, .hasTrustline =
true},
1622 {.src =
Account(
"bob0"), .dst =
Account{
"gw1"}, .hasTrustline =
true},
1626 for (
auto const& t : gwDstTests)
1628 Env env{*
this, features};
1629 auto const baseFee = env.
current()->fees().base;
1630 auto const usd = t.dst[
"USD"];
1631 env.
fund(
XRP(5000), t.dst, t.src);
1632 env(
fset(t.dst, asfAllowTrustLineLocking));
1635 env.
trust(usd(100'000), t.src);
1638 env(
pay(t.dst, t.src, usd(10'000)));
1642 auto const seq1 = env.
seq(t.src);
1643 auto const preSrc = env.
balance(t.src, usd);
1647 Fee(baseFee * 150));
1654 Fee(baseFee * 150));
1656 auto const preAmount = 10'000;
1657 BEAST_EXPECT(preSrc == usd(preAmount));
1658 auto const postAmount = 9000;
1659 BEAST_EXPECT(env.
balance(t.src, usd) == usd(postAmount));
1660 BEAST_EXPECT(env.
balance(t.dst, usd) == usd(0));
1665 auto const gw =
Account{
"gateway"};
1666 auto const usd = gw[
"USD"];
1667 Env env{*
this, features};
1668 auto const baseFee = env.
current()->fees().base;
1670 env(
fset(gw, asfAllowTrustLineLocking));
1690 auto const alice =
Account(
"alice");
1691 auto const bob =
Account(
"bob");
1692 auto const carol =
Account(
"carol");
1693 auto const gw =
Account{
"gateway"};
1694 auto const usd = gw[
"USD"];
1698 Env env{*
this, features};
1699 auto const baseFee = env.
current()->fees().base;
1700 env.
fund(
XRP(10'000), alice, bob, gw);
1701 env(
fset(gw, asfAllowTrustLineLocking));
1702 env(
rate(gw, 1.25));
1704 env.
trust(usd(100'000), alice);
1705 env.
trust(usd(100'000), bob);
1707 env(
pay(gw, alice, usd(10'000)));
1708 env(
pay(gw, bob, usd(10'000)));
1712 auto const preAlice = env.
balance(alice, usd);
1713 auto const seq1 = env.
seq(alice);
1714 auto const delta = usd(125);
1718 Fee(baseFee * 150));
1727 Fee(baseFee * 150));
1730 BEAST_EXPECT(env.
balance(alice, usd) == preAlice - delta);
1731 BEAST_EXPECT(env.
balance(bob, usd) == usd(10'100));
1735 Env env{*
this, features};
1736 auto const baseFee = env.
current()->fees().base;
1737 env.
fund(
XRP(10'000), alice, bob, gw);
1738 env(
fset(gw, asfAllowTrustLineLocking));
1739 env(
rate(gw, 1.25));
1741 env.
trust(usd(100'000), alice);
1742 env.
trust(usd(100'000), bob);
1744 env(
pay(gw, alice, usd(10'000)));
1745 env(
pay(gw, bob, usd(10'000)));
1749 auto const preAlice = env.
balance(alice, usd);
1750 auto const seq1 = env.
seq(alice);
1751 auto const delta = usd(125);
1755 Fee(baseFee * 150));
1761 env(
rate(gw, 1.26));
1768 Fee(baseFee * 150));
1771 BEAST_EXPECT(env.
balance(alice, usd) == preAlice - delta);
1772 BEAST_EXPECT(env.
balance(bob, usd) == usd(10'100));
1777 Env env{*
this, features};
1778 auto const baseFee = env.
current()->fees().base;
1779 env.
fund(
XRP(10'000), alice, bob, gw);
1780 env(
fset(gw, asfAllowTrustLineLocking));
1781 env(
rate(gw, 1.25));
1783 env.
trust(usd(100'000), alice);
1784 env.
trust(usd(100'000), bob);
1786 env(
pay(gw, alice, usd(10'000)));
1787 env(
pay(gw, bob, usd(10'000)));
1791 auto const preAlice = env.
balance(alice, usd);
1792 auto const seq1 = env.
seq(alice);
1793 auto const delta = usd(125);
1797 Fee(baseFee * 150));
1803 env(
rate(gw, 1.00));
1810 Fee(baseFee * 150));
1813 BEAST_EXPECT(env.
balance(alice, usd) == preAlice - delta);
1814 BEAST_EXPECT(env.
balance(bob, usd) == usd(10125));
1819 Env env{*
this, features};
1820 auto const baseFee = env.
current()->fees().base;
1821 env.
fund(
XRP(10'000), alice, bob, gw);
1822 env(
fset(gw, asfAllowTrustLineLocking));
1823 env(
rate(gw, 1.25));
1825 env.
trust(usd(100'000), alice);
1826 env.
trust(usd(100'000), bob);
1828 env(
pay(gw, alice, usd(10'000)));
1829 env(
pay(gw, bob, usd(10'000)));
1833 auto const preAlice = env.
balance(alice, usd);
1834 auto const seq1 = env.
seq(alice);
1835 auto const delta = usd(125);
1845 env(
rate(gw, 1.00));
1852 BEAST_EXPECT(env.
balance(alice, usd) == preAlice);
1853 BEAST_EXPECT(env.
balance(bob, usd) == usd(10000));
1864 auto const alice =
Account(
"alice");
1865 auto const bob =
Account(
"bob");
1866 auto const gw =
Account{
"gateway"};
1867 auto const usd = gw[
"USD"];
1871 Env env{*
this, features};
1872 auto const baseFee = env.
current()->fees().base;
1873 env.
fund(
XRP(1'000), alice, bob, gw);
1874 env(
fset(gw, asfAllowTrustLineLocking));
1876 env.
trust(usd(10'000), alice, bob);
1878 env(
pay(gw, alice, usd(1'000)));
1879 env(
pay(gw, bob, usd(1'000)));
1883 auto seq1 = env.
seq(alice);
1884 auto const delta = usd(125);
1888 Fee(baseFee * 150));
1892 auto const preBobLimit = env.
limit(bob, usd);
1896 Fee(baseFee * 150));
1898 auto const postBobLimit = env.
limit(bob, usd);
1900 BEAST_EXPECT(postBobLimit == preBobLimit);
1911 auto const alice =
Account(
"alice");
1912 auto const bob =
Account(
"bob");
1913 auto const carol =
Account(
"carol");
1914 auto const gw =
Account{
"gateway"};
1915 auto const usd = gw[
"USD"];
1917 auto const aliceUSD = alice[
"USD"];
1918 auto const bobUSD = bob[
"USD"];
1920 Env env{*
this, features};
1921 auto const baseFee = env.
current()->fees().base;
1922 env.
fund(
XRP(1'000), alice, bob, gw);
1923 env(
fset(gw, asfAllowTrustLineLocking));
1924 env(
fset(gw, asfRequireAuth));
1927 env(
trust(alice, usd(10'000)));
1928 env(
trust(bob, usd(10'000)));
1930 env(
pay(gw, alice, usd(1'000)));
1934 auto seq1 = env.
seq(alice);
1935 auto const delta = usd(125);
1945 env(
trust(bob, usd(10'000)));
1947 env(
pay(gw, bob, usd(1'000)));
1951 seq1 = env.
seq(alice);
1955 Fee(baseFee * 150));
1962 Fee(baseFee * 150));
1973 auto const alice =
Account(
"alice");
1974 auto const bob =
Account(
"bob");
1975 auto const carol =
Account(
"carol");
1976 auto const gw =
Account{
"gateway"};
1977 auto const usd = gw[
"USD"];
1981 Env env{*
this, features};
1982 auto const baseFee = env.
current()->fees().base;
1983 env.
fund(
XRP(10'000), alice, bob, gw);
1984 env(
fset(gw, asfAllowTrustLineLocking));
1986 env.
trust(usd(100'000), alice);
1987 env.
trust(usd(100'000), bob);
1989 env(
pay(gw, alice, usd(10'000)));
1990 env(
pay(gw, bob, usd(10'000)));
1992 env(
fset(gw, asfGlobalFreeze));
1996 auto seq1 = env.
seq(alice);
1997 auto const delta = usd(125);
2008 env(
fclear(gw, asfGlobalFreeze));
2012 seq1 = env.
seq(alice);
2016 Fee(baseFee * 150));
2020 env(
fset(gw, asfGlobalFreeze));
2027 Fee(baseFee * 150));
2031 env(
fclear(gw, asfGlobalFreeze));
2035 seq1 = env.
seq(alice);
2039 Fee(baseFee * 150));
2043 env(
fset(gw, asfGlobalFreeze));
2054 Env env{*
this, features};
2055 auto const baseFee = env.
current()->fees().base;
2056 env.
fund(
XRP(10'000), alice, bob, gw);
2057 env(
fset(gw, asfAllowTrustLineLocking));
2059 env(
trust(alice, usd(100'000)));
2060 env(
trust(bob, usd(100'000)));
2062 env(
pay(gw, alice, usd(10'000)));
2063 env(
pay(gw, bob, usd(10'000)));
2067 env(
trust(gw, usd(10'000), alice, tfSetFreeze));
2071 auto seq1 = env.
seq(alice);
2072 auto const delta = usd(125);
2083 env(
trust(gw, usd(10'000), alice, tfClearFreeze));
2087 seq1 = env.
seq(alice);
2091 Fee(baseFee * 150));
2095 env(
trust(gw, usd(10'000), bob, tfSetFreeze));
2102 Fee(baseFee * 150));
2106 env(
trust(gw, usd(10'000), alice, tfClearFreeze));
2107 env(
trust(gw, usd(10'000), bob, tfClearFreeze));
2111 seq1 = env.
seq(alice);
2115 Fee(baseFee * 150));
2119 env(
trust(gw, usd(10'000), bob, tfSetFreeze));
2130 Env env{*
this, features};
2131 auto const baseFee = env.
current()->fees().base;
2132 env.
fund(
XRP(10'000), alice, bob, gw);
2133 env(
fset(gw, asfAllowTrustLineLocking));
2135 env(
trust(alice, usd(100'000)));
2136 env(
trust(bob, usd(100'000)));
2138 env(
pay(gw, alice, usd(10'000)));
2139 env(
pay(gw, bob, usd(10'000)));
2143 env(
trust(gw, usd(10'000), alice, tfSetFreeze | tfSetDeepFreeze));
2147 auto seq1 = env.
seq(alice);
2148 auto const delta = usd(125);
2159 env(
trust(gw, usd(10'000), alice, tfClearFreeze | tfClearDeepFreeze));
2163 seq1 = env.
seq(alice);
2167 Fee(baseFee * 150));
2171 env(
trust(gw, usd(10'000), bob, tfSetFreeze | tfSetDeepFreeze));
2183 env(
trust(gw, usd(10'000), alice, tfClearFreeze | tfClearDeepFreeze));
2184 env(
trust(gw, usd(10'000), bob, tfClearFreeze | tfClearDeepFreeze));
2188 seq1 = env.
seq(alice);
2192 Fee(baseFee * 150));
2196 env(
trust(gw, usd(10'000), bob, tfSetFreeze | tfSetDeepFreeze));
2207 testcase(
"IOU Insufficient Funds");
2211 auto const alice =
Account(
"alice");
2212 auto const bob =
Account(
"bob");
2213 auto const carol =
Account(
"carol");
2214 auto const gw =
Account{
"gateway"};
2215 auto const usd = gw[
"USD"];
2219 Env env{*
this, features};
2220 auto const baseFee = env.
current()->fees().base;
2221 env.
fund(
XRP(10'000), alice, bob, gw);
2222 env(
fset(gw, asfAllowTrustLineLocking));
2224 env.
trust(usd(100'000), alice);
2225 env.
trust(usd(100'000), bob);
2227 env(
pay(gw, alice, usd(10'000)));
2228 env(
pay(gw, bob, usd(10'000)));
2232 auto const delta = usd(1'000);
2236 Fee(baseFee * 150));
2243 Env env{*
this, features};
2244 auto const baseFee = env.
current()->fees().base;
2245 env.
fund(
XRP(10'000), alice, bob, gw);
2246 env(
fset(gw, asfAllowTrustLineLocking));
2248 env.
trust(usd(100'000), alice);
2249 env.
trust(usd(100'000), bob);
2251 env(
pay(gw, alice, usd(10'000)));
2252 env(
pay(gw, bob, usd(10'000)));
2255 auto const delta = usd(1'000);
2259 Fee(baseFee * 150));
2278 auto const alice =
Account(
"alice");
2279 auto const bob =
Account(
"bob");
2280 auto const gw =
Account{
"gateway"};
2281 auto const usd = gw[
"USD"];
2285 Env env(*
this, features);
2286 auto const baseFee = env.
current()->fees().base;
2287 env.
fund(
XRP(10'000), alice, bob, gw);
2288 env(
fset(gw, asfAllowTrustLineLocking));
2290 env.
trust(usd(100000000000000000), alice);
2291 env.
trust(usd(100000000000000000), bob);
2293 env(
pay(gw, alice, usd(10000000000000000)));
2294 env(
pay(gw, bob, usd(1)));
2297 bool const largeMantissa = features[featureSingleAssetVault] ||
2298 features[featureLendingProtocol] || features[featureMPTokensV2];
2308 auto const seq1 = env.
seq(alice);
2313 Fee(baseFee * 150));
2320 Fee(baseFee * 150));
2330 using namespace jtx;
2333 for (
bool const withTokenEscrow : {
false,
true})
2335 auto const amend = withTokenEscrow ? features : features - featureTokenEscrow;
2336 Env env{*
this, amend};
2337 auto const baseFee = env.
current()->fees().base;
2338 auto const alice =
Account(
"alice");
2339 auto const bob =
Account(
"bob");
2340 auto const gw =
Account(
"gw");
2343 MPTTester mptGw(env, gw, {.holders = {alice}});
2345 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2346 mptGw.authorize({.account = alice});
2347 auto const mpt = mptGw[
"MPT"];
2348 env(
pay(gw, alice, mpt(10'000)));
2354 auto const seq1 = env.
seq(alice);
2367 auto const seq2 = env.
seq(alice);
2387 for (
bool const withMPT : {
true,
false})
2389 auto const amend = withMPT ? features : features - featureMPTokensV1;
2390 Env env{*
this, amend};
2391 auto const baseFee = env.
current()->fees().base;
2392 auto const alice =
Account(
"alice");
2393 auto const bob =
Account(
"bob");
2394 auto const gw =
Account(
"gw");
2395 env.
fund(
XRP(1'000), alice, bob, gw);
2399 jv[jss::Amount][jss::mpt_issuance_id] =
2400 "00000004A407AF5856CCF3C42619DAA925813FC955C72983";
2401 jv[jss::Amount][jss::value] =
"-1";
2414 Env env{*
this, features};
2415 auto const baseFee = env.
current()->fees().base;
2416 auto const alice =
Account(
"alice");
2417 auto const bob =
Account(
"bob");
2418 auto const gw =
Account(
"gw");
2420 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2422 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2423 mptGw.authorize({.account = alice});
2424 mptGw.authorize({.account = bob});
2425 auto const mpt = mptGw[
"MPT"];
2426 env(
pay(gw, alice, mpt(10'000)));
2427 env(
pay(gw, bob, mpt(10'000)));
2448 Env env{*
this, features};
2449 auto const baseFee = env.
current()->fees().base;
2450 auto const alice =
Account(
"alice");
2451 auto const gw =
Account(
"gw");
2453 MPTTester mptGw(env, gw, {.holders = {alice}});
2455 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2456 mptGw.authorize({.account = alice});
2457 auto const mpt = mptGw[
"MPT"];
2458 env(
pay(gw, alice, mpt(10'000)));
2471 Env env{*
this, features};
2472 auto const baseFee = env.
current()->fees().base;
2473 auto const alice =
Account(
"alice");
2474 auto const bob =
Account(
"bob");
2475 auto const gw =
Account(
"gw");
2476 env.
fund(
XRP(10'000), alice, bob, gw);
2481 jv[jss::Amount][jss::mpt_issuance_id] =
2482 "00000004A407AF5856CCF3C42619DAA925813FC955C72983";
2493 Env env{*
this, features};
2494 auto const baseFee = env.
current()->fees().base;
2495 auto const alice =
Account(
"alice");
2496 auto const bob =
Account(
"bob");
2497 auto const gw =
Account(
"gw");
2499 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2500 mptGw.
create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer});
2501 mptGw.authorize({.account = alice});
2502 mptGw.authorize({.account = bob});
2503 auto const mpt = mptGw[
"MPT"];
2504 env(
pay(gw, alice, mpt(10'000)));
2505 env(
pay(gw, bob, mpt(10'000)));
2518 Env env{*
this, features};
2519 auto const baseFee = env.
current()->fees().base;
2520 auto const alice =
Account(
"alice");
2521 auto const bob =
Account(
"bob");
2522 auto const gw =
Account(
"gw");
2524 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2526 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2527 auto const mpt = mptGw[
"MPT"];
2539 Env env{*
this, features};
2540 auto const baseFee = env.
current()->fees().base;
2541 auto const alice =
Account(
"alice");
2542 auto const bob =
Account(
"bob");
2543 auto const gw =
Account(
"gw");
2545 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2549 .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth});
2550 mptGw.authorize({.account = alice});
2551 mptGw.authorize({.account = gw, .holder = alice});
2552 auto const mpt = mptGw[
"MPT"];
2553 env(
pay(gw, alice, mpt(10'000)));
2557 mptGw.authorize({.account = gw, .holder = alice, .flags = tfMPTUnauthorize});
2569 Env env{*
this, features};
2570 auto const baseFee = env.
current()->fees().base;
2571 auto const alice =
Account(
"alice");
2572 auto const bob =
Account(
"bob");
2573 auto const gw =
Account(
"gw");
2575 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2579 .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth});
2580 mptGw.authorize({.account = alice});
2581 mptGw.authorize({.account = gw, .holder = alice});
2582 mptGw.authorize({.account = bob});
2583 mptGw.authorize({.account = gw, .holder = bob});
2584 auto const mpt = mptGw[
"MPT"];
2585 env(
pay(gw, alice, mpt(10'000)));
2586 env(
pay(gw, bob, mpt(10'000)));
2590 mptGw.authorize({.account = gw, .holder = bob, .flags = tfMPTUnauthorize});
2602 Env env{*
this, features};
2603 auto const baseFee = env.
current()->fees().base;
2604 auto const alice =
Account(
"alice");
2605 auto const bob =
Account(
"bob");
2606 auto const gw =
Account(
"gw");
2608 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2612 .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTCanLock});
2613 mptGw.authorize({.account = alice});
2614 mptGw.authorize({.account = bob});
2615 auto const mpt = mptGw[
"MPT"];
2616 env(
pay(gw, alice, mpt(10'000)));
2617 env(
pay(gw, bob, mpt(10'000)));
2621 mptGw.set({.account = gw, .holder = alice, .flags = tfMPTLock});
2633 Env env{*
this, features};
2634 auto const baseFee = env.
current()->fees().base;
2635 auto const alice =
Account(
"alice");
2636 auto const bob =
Account(
"bob");
2637 auto const gw =
Account(
"gw");
2639 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2643 .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTCanLock});
2644 mptGw.authorize({.account = alice});
2645 mptGw.authorize({.account = bob});
2646 auto const mpt = mptGw[
"MPT"];
2647 env(
pay(gw, alice, mpt(10'000)));
2648 env(
pay(gw, bob, mpt(10'000)));
2652 mptGw.set({.account = gw, .holder = bob, .flags = tfMPTLock});
2664 Env env{*
this, features};
2665 auto const baseFee = env.
current()->fees().base;
2666 auto const alice =
Account(
"alice");
2667 auto const bob =
Account(
"bob");
2668 auto const gw =
Account(
"gw");
2670 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2671 mptGw.
create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow});
2672 mptGw.authorize({.account = alice});
2673 mptGw.authorize({.account = bob});
2674 auto const mpt = mptGw[
"MPT"];
2675 env(
pay(gw, alice, mpt(10'000)));
2676 env(
pay(gw, bob, mpt(10'000)));
2689 Env env{*
this, features};
2690 auto const baseFee = env.
current()->fees().base;
2691 auto const alice =
Account(
"alice");
2692 auto const bob =
Account(
"bob");
2693 auto const gw =
Account(
"gw");
2695 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2697 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2698 mptGw.authorize({.account = alice});
2699 mptGw.authorize({.account = bob});
2700 auto const mpt = mptGw[
"MPT"];
2701 env(
pay(gw, bob, mpt(10)));
2714 Env env{*
this, features};
2715 auto const baseFee = env.
current()->fees().base;
2716 auto const alice =
Account(
"alice");
2717 auto const bob =
Account(
"bob");
2718 auto const gw =
Account(
"gw");
2720 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2722 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2723 mptGw.authorize({.account = alice});
2724 mptGw.authorize({.account = bob});
2725 auto const mpt = mptGw[
"MPT"];
2726 env(
pay(gw, alice, mpt(10)));
2727 env(
pay(gw, bob, mpt(10)));
2748 Env env{*
this, features};
2749 auto const baseFee = env.
current()->fees().base;
2750 auto const alice =
Account(
"alice");
2751 auto const bob =
Account(
"bob");
2752 auto const gw =
Account(
"gw");
2754 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2758 .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth});
2759 mptGw.authorize({.account = alice});
2760 mptGw.authorize({.account = gw, .holder = alice});
2761 mptGw.authorize({.account = bob});
2762 mptGw.authorize({.account = gw, .holder = bob});
2763 auto const mpt = mptGw[
"MPT"];
2764 env(
pay(gw, alice, mpt(10'000)));
2765 env(
pay(gw, bob, mpt(10'000)));
2768 auto const seq1 = env.
seq(alice);
2777 mptGw.authorize({.account = gw, .holder = bob, .flags = tfMPTUnauthorize});
2789 Env env{*
this, features};
2790 auto const baseFee = env.
current()->fees().base;
2791 auto const alice =
Account(
"alice");
2792 auto const bob =
Account(
"bob");
2793 env.
fund(
XRP(10'000), alice, bob);
2796 auto const seq1 = env.
seq(alice);
2803 sleNew->setAccountID(sfDestination, bob);
2804 sleNew->setFieldAmount(sfAmount, amt);
2820 Env env{*
this, features};
2821 auto const baseFee = env.
current()->fees().base;
2822 auto const alice =
Account(
"alice");
2823 auto const bob =
Account(
"bob");
2824 auto const gw =
Account(
"gw");
2826 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2830 .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTCanLock});
2831 mptGw.authorize({.account = alice});
2832 mptGw.authorize({.account = bob});
2833 auto const mpt = mptGw[
"MPT"];
2834 env(
pay(gw, alice, mpt(10'000)));
2835 env(
pay(gw, bob, mpt(10'000)));
2838 auto const seq1 = env.
seq(alice);
2847 mptGw.set({.account = gw, .holder = bob, .flags = tfMPTLock});
2867 Env env{*
this, features};
2868 auto const baseFee = env.
current()->fees().base;
2869 auto const acctReserve = env.
current()->fees().reserve;
2870 auto const incReserve = env.
current()->fees().increment;
2872 auto const alice =
Account(
"alice");
2873 auto const bob =
Account(
"bob");
2874 auto const gw =
Account(
"gw");
2875 env.
fund(acctReserve + (incReserve - 1), bob);
2878 MPTTester mptGw(env, gw, {.holders = {alice}});
2880 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2881 mptGw.authorize({.account = alice});
2882 auto const mpt = mptGw[
"MPT"];
2883 env(
pay(gw, alice, mpt(10'000)));
2886 auto const seq1 = env.
seq(alice);
2904 Env env{*
this, features};
2905 auto const baseFee = env.
current()->fees().base;
2906 auto const alice =
Account(
"alice");
2907 auto const bob =
Account(
"bob");
2908 auto const gw =
Account(
"gw");
2912 MPTTester mptGw(env, gw, {.holders = {alice}});
2914 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2915 mptGw.authorize({.account = alice});
2916 auto const mpt = mptGw[
"MPT"];
2917 env(
pay(gw, alice, mpt(10'000)));
2920 auto const seq1 = env.
seq(alice);
2938 Env env{*
this, features};
2939 auto const baseFee = env.
current()->fees().base;
2940 auto const alice =
Account(
"alice");
2941 auto const bob =
Account(
"bob");
2942 auto const carol =
Account(
"carol");
2943 auto const gw =
Account(
"gw");
2944 env.
fund(
XRP(10'000), bob, carol);
2947 MPTTester mptGw(env, gw, {.holders = {alice}});
2949 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
2950 mptGw.authorize({.account = alice});
2951 auto const mpt = mptGw[
"MPT"];
2952 env(
pay(gw, alice, mpt(10'000)));
2955 auto const seq1 = env.
seq(alice);
2981 Env env{*
this, features};
2982 auto const baseFee = env.
current()->fees().base;
2983 auto const alice =
Account(
"alice");
2984 auto const bob =
Account(
"bob");
2985 auto const gw =
Account(
"gw");
2987 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
2991 .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth});
2992 mptGw.authorize({.account = alice});
2993 mptGw.authorize({.account = gw, .holder = alice});
2994 mptGw.authorize({.account = bob});
2995 mptGw.authorize({.account = gw, .holder = bob});
2996 auto const mpt = mptGw[
"MPT"];
2997 env(
pay(gw, alice, mpt(10'000)));
2998 env(
pay(gw, bob, mpt(10'000)));
3001 auto const seq1 = env.
seq(alice);
3010 mptGw.authorize({.account = gw, .holder = alice, .flags = tfMPTUnauthorize});
3018 Env env{*
this, features};
3019 auto const baseFee = env.
current()->fees().base;
3020 auto const alice =
Account(
"alice");
3021 auto const bob =
Account(
"bob");
3022 env.
fund(
XRP(10'000), alice, bob);
3024 auto const seq1 = env.
seq(alice);
3031 sleNew->setAccountID(sfDestination, bob);
3032 sleNew->setFieldAmount(sfAmount, amt);
3048 using namespace jtx;
3051 Env env{*
this, features};
3052 auto const baseFee = env.
current()->fees().base;
3053 auto const alice =
Account(
"alice");
3054 auto const bob =
Account(
"bob");
3055 auto const carol =
Account(
"carol");
3056 auto const gw =
Account(
"gw");
3059 MPTTester mptGw(env, gw, {.holders = {alice, carol}});
3061 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3062 mptGw.authorize({.account = alice});
3063 mptGw.authorize({.account = carol});
3064 auto const mpt = mptGw[
"MPT"];
3065 env(
pay(gw, alice, mpt(10'000)));
3066 env(
pay(gw, carol, mpt(10'000)));
3069 auto outstandingMPT = env.
balance(gw, mpt);
3072 auto const seq1 = env.
seq(alice);
3074 auto const preAliceMPT = env.
balance(alice, mpt);
3075 auto const preBobMPT = env.
balance(bob, mpt);
3083 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT - mpt(1'000));
3084 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == 1'000);
3085 BEAST_EXPECT(env.
balance(bob, mpt) == preBobMPT);
3087 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3091 auto const preAliceMPT = env.
balance(alice, mpt);
3092 auto const preBobMPT = env.
balance(bob, mpt);
3100 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT);
3102 BEAST_EXPECT(env.
balance(bob, mpt) == preBobMPT + mpt(1'000));
3104 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3109 auto const seq2 = env.
seq(alice);
3111 auto const preAliceMPT = env.
balance(alice, mpt);
3112 auto const preBobMPT = env.
balance(bob, mpt);
3121 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT - mpt(1'000));
3122 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == 1'000);
3123 BEAST_EXPECT(env.
balance(bob, mpt) == preBobMPT);
3125 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3129 auto const preAliceMPT = env.
balance(alice, mpt);
3130 auto const preBobMPT = env.
balance(bob, mpt);
3134 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT + mpt(1'000));
3136 BEAST_EXPECT(env.
balance(bob, mpt) == preBobMPT);
3138 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3144 auto const seq = env.
seq(alice);
3145 auto const preAliceMPT = env.
balance(alice, mpt);
3153 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT - mpt(1'000));
3154 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == 1'000);
3155 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3165 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT);
3167 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3173 auto const seq = env.
seq(alice);
3174 auto const preAliceMPT = env.
balance(alice, mpt);
3183 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT - mpt(1'000));
3184 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == 1'000);
3185 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3191 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT);
3193 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3199 auto const preAliceMPT = env.
balance(alice, mpt);
3200 auto const preBobMPT = env.
balance(bob, mpt);
3201 auto const preCarolMPT = env.
balance(carol, mpt);
3216 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT - mpt(1'000));
3217 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == 1'000);
3218 BEAST_EXPECT(env.
balance(bob, mpt) == preBobMPT);
3220 BEAST_EXPECT(env.
balance(carol, mpt) == preCarolMPT - mpt(1'000));
3221 BEAST_EXPECT(
mptEscrowed(env, carol, mpt) == 1'000);
3222 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3228 Env env{*
this, features};
3229 auto const baseFee = env.
current()->fees().base;
3230 auto const alice =
Account(
"alice");
3231 auto const bob =
Account(
"bob");
3232 auto const gw =
Account(
"gw");
3234 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
3236 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3237 mptGw.authorize({.account = alice});
3238 mptGw.authorize({.account = bob});
3239 auto const mpt = mptGw[
"MPT"];
3243 auto const preAliceMPT = env.
balance(alice, mpt);
3244 auto const preBobMPT = env.
balance(bob, mpt);
3245 auto const outstandingMPT = env.
balance(gw, mpt);
3247 auto const seq1 = env.
seq(alice);
3251 Fee(baseFee * 150));
3254 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT - mpt(1));
3256 BEAST_EXPECT(env.
balance(bob, mpt) == preBobMPT);
3258 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3268 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT - mpt(1));
3272 BEAST_EXPECT(env.
balance(bob, mpt) == preBobMPT + mpt(1));
3274 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3282 Env env{*
this, features};
3283 auto const baseFee = env.
current()->fees().base;
3284 auto const alice =
Account(
"alice");
3285 auto const bob =
Account(
"bob");
3286 auto const gw =
Account(
"gw");
3288 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
3290 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3291 mptGw.authorize({.account = alice});
3292 mptGw.authorize({.account = bob});
3293 auto const mpt = mptGw[
"MPT"];
3297 auto const preAliceMPT = env.
balance(alice, mpt);
3298 auto const preBobMPT = env.
balance(bob, mpt);
3299 auto const outstandingMPT = env.
balance(gw, mpt);
3302 auto const seq1 = env.
seq(alice);
3306 Fee(baseFee * 150));
3310 auto const seq2 = env.
seq(alice);
3314 Fee(baseFee * 150));
3319 BEAST_EXPECT(env.
balance(bob, mpt) == preBobMPT);
3321 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3342 BEAST_EXPECT(env.
balance(gw, mpt) == outstandingMPT);
3350 using namespace jtx;
3353 auto const alice =
Account(
"alice");
3354 auto const bob =
Account(
"bob");
3355 auto const carol =
Account(
"carol");
3356 auto const gw =
Account{
"gateway"};
3360 Env env{*
this, features};
3361 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
3363 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3364 mptGw.authorize({.account = alice});
3365 mptGw.authorize({.account = bob});
3366 auto const mpt = mptGw[
"MPT"];
3367 env(
pay(gw, alice, mpt(10'000)));
3368 env(
pay(gw, bob, mpt(10'000)));
3370 auto const aseq = env.
seq(alice);
3371 auto const bseq = env.
seq(bob);
3452 Env env{*
this, features};
3453 MPTTester mptGw(env, gw, {.holders = {alice, bob, carol}});
3455 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3456 mptGw.authorize({.account = alice});
3457 mptGw.authorize({.account = bob});
3458 mptGw.authorize({.account = carol});
3459 auto const mpt = mptGw[
"MPT"];
3460 env(
pay(gw, alice, mpt(10'000)));
3461 env(
pay(gw, bob, mpt(10'000)));
3462 env(
pay(gw, carol, mpt(10'000)));
3464 auto const aseq = env.
seq(alice);
3465 auto const bseq = env.
seq(bob);
3568 Env env{*
this, features};
3569 auto const baseFee = env.
current()->fees().base;
3570 auto const alice =
Account(
"alice");
3571 auto const gw =
Account(
"gw");
3573 MPTTester mptGw(env, gw, {.holders = {alice}});
3575 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3576 mptGw.authorize({.account = alice});
3577 auto const mpt = mptGw[
"MPT"];
3578 env(
pay(gw, alice, mpt(10'000)));
3582 auto const seq1 = env.
seq(alice);
3583 auto const preAliceMPT = env.
balance(alice, mpt);
3584 auto const preOutstanding = env.
balance(gw, mpt);
3586 BEAST_EXPECT(preOutstanding == mpt(-10'000));
3587 BEAST_EXPECT(preEscrowed == 0);
3592 Fee(baseFee * 150));
3595 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT - mpt(1'000));
3596 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == 1'000);
3597 BEAST_EXPECT(env.
balance(gw, mpt) == preOutstanding);
3604 Fee(baseFee * 150));
3607 BEAST_EXPECT(env.
balance(alice, mpt) == preAliceMPT - mpt(1'000));
3609 BEAST_EXPECT(env.
balance(gw, mpt) == preOutstanding + mpt(1'000));
3621 auto const alice =
Account(
"alice");
3622 auto const bob =
Account(
"bob");
3623 auto const carol =
Account(
"carol");
3624 auto const gw =
Account{
"gateway"};
3625 auto const usd = gw[
"USD"];
3629 Env env{*
this, features};
3630 auto const baseFee = env.
current()->fees().base;
3631 auto const alice =
Account(
"alice");
3632 auto const bob =
Account(
"bob");
3633 auto const gw =
Account(
"gw");
3635 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
3637 {.transferFee = 25000,
3640 .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3641 mptGw.authorize({.account = alice});
3642 mptGw.authorize({.account = bob});
3643 auto const mpt = mptGw[
"MPT"];
3644 env(
pay(gw, alice, mpt(10'000)));
3645 env(
pay(gw, bob, mpt(10'000)));
3649 auto const preAlice = env.
balance(alice, mpt);
3650 auto const seq1 = env.
seq(alice);
3651 auto const delta = mpt(125);
3655 Fee(baseFee * 150));
3660 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == 125);
3662 BEAST_EXPECT(env.
balance(gw, mpt) == mpt(-20'000));
3668 Fee(baseFee * 150));
3671 BEAST_EXPECT(env.
balance(alice, mpt) == preAlice - delta);
3672 BEAST_EXPECT(env.
balance(bob, mpt) == mpt(10'100));
3674 auto const escrowedWithFix = env.
current()->rules().enabled(fixTokenEscrowV1) ? 0 : 25;
3675 auto const outstandingWithFix =
3676 env.
current()->rules().enabled(fixTokenEscrowV1) ? mpt(19'975) : mpt(20'000);
3677 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == escrowedWithFix);
3679 BEAST_EXPECT(env.
balance(gw, mpt) == -outstandingWithFix);
3684 Env env{*
this, features};
3685 auto const baseFee = env.
current()->fees().base;
3686 auto const alice =
Account(
"alice");
3687 auto const bob =
Account(
"bob");
3688 auto const gw =
Account(
"gw");
3690 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
3692 {.transferFee = 25000,
3695 .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3696 mptGw.authorize({.account = alice});
3697 mptGw.authorize({.account = bob});
3698 auto const mpt = mptGw[
"MPT"];
3699 env(
pay(gw, alice, mpt(10'000)));
3700 env(
pay(gw, bob, mpt(10'000)));
3704 auto const preAlice = env.
balance(alice, mpt);
3705 auto const preBob = env.
balance(bob, mpt);
3706 auto const seq1 = env.
seq(alice);
3707 auto const delta = mpt(125);
3712 Fee(baseFee * 150));
3721 BEAST_EXPECT(env.
balance(alice, mpt) == preAlice);
3722 BEAST_EXPECT(env.
balance(bob, mpt) == preBob);
3723 BEAST_EXPECT(env.
balance(gw, mpt) == mpt(-20'000));
3730 Env env{*
this, features};
3731 auto const baseFee = env.
current()->fees().base;
3732 auto const alice =
Account(
"alice");
3733 auto const bob =
Account(
"bob");
3734 auto const gw =
Account(
"gw");
3736 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
3738 {.transferFee = 25000,
3741 .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3742 mptGw.authorize({.account = alice});
3743 mptGw.authorize({.account = bob});
3744 auto const mpt = mptGw[
"MPT"];
3745 env(
pay(gw, alice, mpt(10'000)));
3746 env(
pay(gw, bob, mpt(10'000)));
3750 auto const preAlice = env.
balance(alice, mpt);
3751 auto const seq1 = env.
seq(alice);
3752 auto const delta = mpt(125);
3756 Fee(baseFee * 150));
3761 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == 125);
3763 BEAST_EXPECT(env.
balance(gw, mpt) == mpt(-20'000));
3769 Fee(baseFee * 150));
3772 BEAST_EXPECT(env.
balance(alice, mpt) == preAlice - delta);
3775 BEAST_EXPECT(env.
balance(gw, mpt) == mpt(-19'875));
3785 bool const withCleanup340 = features[fixCleanup3_4_0];
3788 (withCleanup340 ?
"with Cleanup340" :
"without Cleanup340"));
3790 Env env{*
this, features};
3791 auto const baseFee = env.
current()->fees().base;
3792 auto const alice =
Account(
"alice");
3793 auto const bob =
Account(
"bob");
3794 auto const gw =
Account(
"gw");
3795 env.
fund(
XRP(1'000), alice, bob, gw);
3801 .holders = {alice, bob},
3802 .transferFee = 1'000,
3803 .flags = tfMPTCanEscrow | tfMPTCanTransfer,
3805 env(
pay(gw, alice, mpt(10'000)));
3808 static constexpr int escrowCount = 10;
3809 static constexpr int splitAmount = 10;
3810 static constexpr int totalLocked = escrowCount * splitAmount;
3812 for (
auto& seq : seqs)
3814 seq = env.
seq(alice);
3818 Fee(baseFee * 150));
3822 BEAST_EXPECT(env.
balance(alice, mpt) == mpt(10'000 - totalLocked));
3823 BEAST_EXPECT(env.
balance(bob, mpt) == mpt(0));
3824 BEAST_EXPECT(env.
balance(gw, mpt) == mpt(-10'000));
3825 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == totalLocked);
3828 for (
auto const seq : seqs)
3833 Fee(baseFee * 150));
3837 auto const feeBurned = withCleanup340 ? escrowCount : 0;
3838 BEAST_EXPECT(env.
balance(alice, mpt) == mpt(10'000 - totalLocked));
3839 BEAST_EXPECT(env.
balance(bob, mpt) == mpt(totalLocked - feeBurned));
3840 BEAST_EXPECT(env.
balance(gw, mpt) == mpt(-10'000 + feeBurned));
3852 auto constexpr escrowAmount = 200'000'000'000'000'000LL;
3853 auto constexpr noOverflowEscrowAmount = 186'000'000'000'000'000LL;
3854 auto const alice =
Account(
"alice");
3855 auto const bob =
Account(
"bob");
3856 auto const gw =
Account(
"gw");
3858 for (
auto const testFeatures :
3859 {features - featureMPTokensV2 - fixCleanup3_4_0,
3860 features - featureMPTokensV2,
3861 (features | featureMPTokensV2) - fixCleanup3_4_0,
3862 features | featureMPTokensV2})
3864 bool const mptV2 = testFeatures[featureMPTokensV2];
3865 bool const tokenEscrowV1 = testFeatures[fixTokenEscrowV1];
3872 bool const cleanup340 = testFeatures[fixCleanup3_4_0];
3873 bool const noOverflow = cleanup340 || mptV2;
3881 Env env{*
this, testFeatures};
3882 env.
fund(
XRP(1'000), alice, bob, gw);
3883 auto const baseFee = env.
current()->fees().base;
3888 .holders = {alice, bob},
3889 .transferFee = 1'000,
3890 .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3891 env(
pay(gw, alice, mpt(escrowAmount)));
3894 auto const preAlice = env.
balance(alice, mpt);
3895 auto const preBob = env.
balance(bob, mpt);
3896 auto const seq = env.
seq(alice);
3901 Fee(baseFee * 150));
3904 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == escrowAmount);
3917 BEAST_EXPECT(env.
balance(alice, mpt) == preAlice - mpt(escrowAmount));
3918 auto const postBob = env.
balance(bob, mpt);
3919 BEAST_EXPECT(postBob.value() > preBob.value());
3920 BEAST_EXPECT(postBob.value() < (preBob + mpt(escrowAmount)).value());
3921 auto const xferFee = escrowAmount - (postBob.value() - preBob.value());
3922 auto const expectedEscrow = tokenEscrowV1 ? 0 : xferFee;
3923 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == expectedEscrow);
3929 BEAST_EXPECT(env.
balance(alice, mpt) == preAlice - mpt(escrowAmount));
3930 BEAST_EXPECT(env.
balance(bob, mpt) == preBob);
3931 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == escrowAmount);
3939 Env env{*
this, testFeatures};
3940 env.
fund(
XRP(1'000), alice, bob, gw);
3941 auto const baseFee = env.
current()->fees().base;
3946 .holders = {alice, bob},
3947 .transferFee = 1'000,
3948 .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3949 env(
pay(gw, alice, mpt(noOverflowEscrowAmount)));
3952 auto const preAlice = env.
balance(alice, mpt);
3953 auto const preBob = env.
balance(bob, mpt);
3954 auto const seq = env.
seq(alice);
3959 Fee(baseFee * 150));
3962 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == noOverflowEscrowAmount);
3973 BEAST_EXPECT(env.
balance(alice, mpt) == preAlice - mpt(noOverflowEscrowAmount));
3974 auto const postBob = env.
balance(bob, mpt);
3975 BEAST_EXPECT(postBob.value() > preBob.value());
3976 BEAST_EXPECT(postBob.value() < (preBob + mpt(noOverflowEscrowAmount)).value());
3977 auto const xferFee = noOverflowEscrowAmount - (postBob.value() - preBob.value());
3978 auto const expectedEscrow = tokenEscrowV1 ? 0 : xferFee;
3979 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == expectedEscrow);
3986 Env env{*
this, testFeatures};
3987 env.
fund(
XRP(1'000), alice, bob, gw);
3988 auto const baseFee = env.
current()->fees().base;
3993 .holders = {alice, bob},
3994 .transferFee = 1'000,
3995 .flags = tfMPTCanEscrow | tfMPTCanTransfer});
3996 env(
pay(gw, alice, mpt(escrowAmount)));
3999 auto const preAlice = env.
balance(alice, mpt);
4000 auto const preBob = env.
balance(bob, mpt);
4001 auto const seq = env.
seq(alice);
4006 Fee(baseFee * 150));
4009 BEAST_EXPECT(
mptEscrowed(env, alice, mpt) == escrowAmount);
4016 BEAST_EXPECT(env.
balance(alice, mpt) == preAlice);
4017 BEAST_EXPECT(env.
balance(bob, mpt) == preBob);
4018 BEAST_EXPECT(env.
balance(gw, mpt) == -mpt(escrowAmount));
4032 Env env{*
this, features};
4033 auto const baseFee = env.
current()->fees().base;
4034 auto const alice =
Account(
"alice");
4035 auto const bob =
Account(
"bob");
4036 auto const gw =
Account(
"gw");
4038 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
4042 .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth});
4043 mptGw.authorize({.account = alice});
4044 mptGw.authorize({.account = gw, .holder = alice});
4045 mptGw.authorize({.account = bob});
4046 mptGw.authorize({.account = gw, .holder = bob});
4047 auto const mpt = mptGw[
"MPT"];
4048 env(
pay(gw, alice, mpt(10'000)));
4051 auto seq = env.
seq(alice);
4052 auto const delta = mpt(125);
4057 Fee(baseFee * 150));
4064 Fee(baseFee * 150));
4075 Env env{*
this, features};
4076 auto const baseFee = env.
current()->fees().base;
4077 auto const alice =
Account(
"alice");
4078 auto const bob =
Account(
"bob");
4079 auto const gw =
Account(
"gw");
4081 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
4085 .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTCanLock});
4086 mptGw.authorize({.account = alice});
4087 mptGw.authorize({.account = bob});
4088 auto const mpt = mptGw[
"MPT"];
4089 env(
pay(gw, alice, mpt(10'000)));
4090 env(
pay(gw, bob, mpt(10'000)));
4094 auto seq1 = env.
seq(alice);
4099 Fee(baseFee * 150));
4103 mptGw.set({.account = gw, .holder = alice, .flags = tfMPTLock});
4104 mptGw.set({.account = gw, .holder = bob, .flags = tfMPTLock});
4126 Env env{*
this, features};
4127 auto const baseFee = env.
current()->fees().base;
4128 auto const alice =
Account(
"alice");
4129 auto const bob =
Account(
"bob");
4130 auto const gw =
Account(
"gw");
4132 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
4133 mptGw.
create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow});
4134 mptGw.authorize({.account = alice});
4135 mptGw.authorize({.account = bob});
4136 auto const mpt = mptGw[
"MPT"];
4137 env(
pay(gw, alice, mpt(10'000)));
4138 env(
pay(gw, bob, mpt(10'000)));
4153 auto seq = env.
seq(alice);
4157 Fee(baseFee * 150));
4164 Fee(baseFee * 150));
4171 auto seq = env.
seq(alice);
4176 Fee(baseFee * 150));
4194 Env env{*
this, features};
4195 auto const baseFee = env.
current()->fees().base;
4196 auto const alice =
Account(
"alice");
4197 auto const bob =
Account(
"bob");
4198 auto const gw =
Account(
"gw");
4200 MPTTester mptGw(env, gw, {.holders = {alice, bob}});
4202 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
4203 mptGw.authorize({.account = alice});
4204 mptGw.authorize({.account = bob});
4205 auto const mpt = mptGw[
"MPT"];
4206 env(
pay(gw, alice, mpt(10'000)));
4207 env(
pay(gw, bob, mpt(10'000)));
4210 auto const seq1 = env.
seq(alice);
4214 Fee(baseFee * 150));
4218 env(
pay(alice, gw, mpt(9'990)));
4219 env(
pay(bob, gw, mpt(10'000)));
4220 BEAST_EXPECT(env.
balance(alice, mpt) == mpt(0));
4222 BEAST_EXPECT(env.
balance(bob, mpt) == mpt(0));
4224 BEAST_EXPECT(env.
balance(gw, mpt) == mpt(-10));
4225 mptGw.authorize({.account = bob, .flags = tfMPTUnauthorize});
4226 mptGw.destroy({.id = mptGw.issuanceID(), .ownerCount = 1, .err =
tecHAS_OBLIGATIONS});
4235 env(
pay(bob, gw, mpt(10)));
4236 mptGw.destroy({.id = mptGw.issuanceID(), .ownerCount = 0});
4241 Env env{*
this, features};
4242 auto const baseFee = env.
current()->fees().base;
4243 auto const alice =
Account(
"alice");
4244 auto const bob =
Account(
"bob");
4245 auto const gw =
Account(
"gw");
4249 MPTTester mptGw(env, gw, {.holders = {alice}});
4251 {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer});
4252 mptGw.authorize({.account = alice});
4253 auto const mpt = mptGw[
"MPT"];
4254 env(
pay(gw, alice, mpt(10'000)));
4257 auto const seq1 = env.
seq(alice);
4265 env(
pay(alice, gw, mpt(9'990)));
4268 BEAST_EXPECT(env.
balance(alice, mpt) == mpt(0));
4280 BEAST_EXPECT(env.
balance(alice, mpt) == mpt(0));
4282 mptGw.authorize({.account = alice, .flags = tfMPTUnauthorize});
4337 {all - featureSingleAssetVault - featureLendingProtocol - featureMPTokensV2, 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(ModifyType 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
constexpr value_type drops() const
Returns the number of drops.
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.
std::uint32_t ownerCount(Account const &account) const
Return the number of objects owned by an account.
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{}, std::source_location const &loc=std::source_location::current())
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.
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
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 testIOUCancelReserveRecycle(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...
STAmount const & value() const