73 auto testCase = [&,
this](
80 Env env{*
this, testableAmendments() - featureLendingProtocolV1_1};
83 Account const depositor{
"depositor"};
85 env.fund(XRP(1000), issuer, owner, depositor);
86 env(fset(issuer, asfAllowTrustLineClawback));
90 env.trust(asset(1000), owner);
91 env.trust(asset(1000), depositor);
92 env(pay(issuer, owner, asset(200)));
93 env(pay(issuer, depositor, asset(200)));
96 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
100 auto const [vaultAccount, issuanceId] =
102 auto const vault = env.le(
keylet);
103 return {
Account(
"vault", vault->at(sfAccount)), vault->at(sfShareMPTID)};
106 env.memoize(vaultAccount);
109 return env.app().getOpenLedger().modify(
113 if (!BEAST_EXPECT(vault))
116 if (!BEAST_EXPECT(shares))
118 if (fn(*vault, *shares))
133 .depositor = depositor,
134 .vaultAccount = vaultAccount,
144 testCase(18, [&,
this](Env& env, Data d) {
145 testcase(
"Scale deposit overflow on first deposit");
146 auto tx = d.vault.deposit(
147 {.depositor = d.depositor, .id = d.keylet.key, .amount = d.asset(10)});
152 testCase(18, [&,
this](Env& env, Data d) {
153 testcase(
"Scale deposit overflow on second deposit");
156 auto tx = d.vault.deposit(
157 {.depositor = d.depositor, .id = d.keylet.key, .amount = d.asset(5)});
163 auto tx = d.vault.deposit(
164 {.depositor = d.depositor, .id = d.keylet.key, .amount = d.asset(10)});
170 testCase(18, [&,
this](Env& env, Data d) {
171 testcase(
"Scale deposit overflow on total shares");
174 auto tx = d.vault.deposit(
175 {.depositor = d.depositor, .id = d.keylet.key, .amount = d.asset(5)});
181 auto tx = d.vault.deposit(
182 {.depositor = d.depositor, .id = d.keylet.key, .amount = d.asset(5)});
188 testCase(1, [&,
this](Env& env, Data d) {
191 auto const start = env.balance(d.depositor, d.assets).number();
192 auto tx = d.vault.deposit(
193 {.depositor = d.depositor, .id = d.keylet.key, .amount = d.asset(1)});
196 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(10));
197 BEAST_EXPECT(env.balance(d.depositor, d.assets) ==
STAmount(d.asset, start - 1));
200 testCase(1, [&,
this](Env& env, Data d) {
201 testcase(
"Scale deposit insignificant amount");
203 auto tx = d.vault.deposit(
204 {.depositor = d.depositor,
210 testCase(1, [&,
this](Env& env, Data d) {
211 testcase(
"Scale deposit exact, using full precision");
213 auto const start = env.balance(d.depositor, d.assets).number();
214 auto tx = d.vault.deposit(
215 {.depositor = d.depositor,
220 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(15));
222 env.balance(d.depositor, d.assets) ==
STAmount(d.asset, start -
Number(15, -1)));
225 testCase(1, [&,
this](Env& env, Data d) {
226 testcase(
"Scale deposit exact, truncating from .5");
228 auto const start = env.balance(d.depositor, d.assets).number();
232 auto tx = d.vault.deposit(
233 {.depositor = d.depositor,
238 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(12));
240 env.balance(d.depositor, d.assets) ==
245 auto tx = d.vault.deposit(
246 {.depositor = d.depositor,
251 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(24));
253 env.balance(d.depositor, d.assets) ==
258 auto tx = d.vault.deposit(
259 {.depositor = d.depositor,
264 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(36));
266 env.balance(d.depositor, d.assets) ==
271 testCase(1, [&,
this](Env& env, Data d) {
272 testcase(
"Scale deposit exact, truncating from .01");
274 auto const start = env.balance(d.depositor, d.assets).number();
276 auto tx = d.vault.deposit(
277 {.depositor = d.depositor,
282 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(12));
284 env.balance(d.depositor, d.assets) ==
STAmount(d.asset, start -
Number(12, -1)));
288 auto tx = d.vault.deposit(
289 {.depositor = d.depositor,
294 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(18));
296 env.balance(d.depositor, d.assets) ==
301 testCase(1, [&,
this](Env& env, Data d) {
302 testcase(
"Scale deposit exact, truncating from .99");
304 auto const start = env.balance(d.depositor, d.assets).number();
306 auto tx = d.vault.deposit(
307 {.depositor = d.depositor,
312 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(12));
314 env.balance(d.depositor, d.assets) ==
STAmount(d.asset, start -
Number(12, -1)));
318 auto tx = d.vault.deposit(
319 {.depositor = d.depositor,
324 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(18));
326 env.balance(d.depositor, d.assets) ==
331 testCase(1, [&,
this](Env& env, Data d) {
333 auto const start = env.balance(d.depositor, d.assets).number();
334 auto tx = d.vault.deposit(
335 {.depositor = d.depositor,
340 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(1000));
342 env.balance(d.depositor, d.assets) ==
STAmount(d.asset, start -
Number(100, 0)));
344 env.balance(d.vaultAccount, d.assets) ==
STAmount(d.asset,
Number(100, 0)));
346 env.balance(d.vaultAccount, d.shares) ==
STAmount(d.share,
Number(-1000, 0)));
354 auto const start = env.balance(d.depositor, d.assets).number();
355 auto tx = d.vault.withdraw(
356 {.depositor = d.depositor,
361 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(900));
363 env.balance(d.depositor, d.assets) ==
STAmount(d.asset, start +
Number(10, 0)));
365 env.balance(d.vaultAccount, d.assets) ==
STAmount(d.asset,
Number(90, 0)));
367 env.balance(d.vaultAccount, d.shares) ==
STAmount(d.share,
Number(-900, 0)));
371 testcase(
"Scale redeem with rounding");
376 auto const start = env.balance(d.depositor, d.assets).number();
377 d.peek([](
SLE& vault,
auto&) ->
bool {
378 vault[sfAssetsAvailable] =
Number(1);
386 auto tx = d.vault.withdraw(
387 {.depositor = d.depositor,
392 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(900 - 25));
394 env.balance(d.depositor, d.assets) ==
397 env.balance(d.vaultAccount, d.assets) ==
400 env.balance(d.vaultAccount, d.shares) ==
410 auto const start = env.balance(d.depositor, d.assets).number();
412 tx = d.vault.withdraw(
413 {.depositor = d.depositor,
418 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(875 - 21));
420 env.balance(d.depositor, d.assets) ==
423 env.balance(d.vaultAccount, d.assets) ==
426 env.balance(d.vaultAccount, d.shares) ==
432 auto const rest = env.balance(d.depositor, d.shares).number();
434 tx = d.vault.withdraw(
435 {.depositor = d.depositor,
437 .amount =
STAmount(d.share, rest)});
440 BEAST_EXPECT(env.balance(d.depositor, d.shares).number() == 0);
441 BEAST_EXPECT(env.balance(d.vaultAccount, d.assets).number() == 0);
442 BEAST_EXPECT(env.balance(d.vaultAccount, d.shares).number() == 0);
446 testCase(18, [&,
this](Env& env, Data d) {
447 testcase(
"Scale withdraw overflow");
450 auto tx = d.vault.deposit(
451 {.depositor = d.depositor, .id = d.keylet.key, .amount = d.asset(5)});
457 auto tx = d.vault.withdraw(
458 {.depositor = d.depositor,
466 testCase(1, [&,
this](Env& env, Data d) {
468 auto const start = env.balance(d.depositor, d.assets).number();
469 auto tx = d.vault.deposit(
470 {.depositor = d.depositor,
475 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(1000));
477 env.balance(d.depositor, d.assets) ==
STAmount(d.asset, start -
Number(100, 0)));
479 env.balance(d.vaultAccount, d.assets) ==
STAmount(d.asset,
Number(100, 0)));
481 env.balance(d.vaultAccount, d.shares) ==
STAmount(d.share,
Number(-1000, 0)));
492 auto const start = env.balance(d.depositor, d.assets).number();
493 auto tx = d.vault.withdraw(
494 {.depositor = d.depositor,
499 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(900));
501 env.balance(d.depositor, d.assets) ==
STAmount(d.asset, start +
Number(10, 0)));
503 env.balance(d.vaultAccount, d.assets) ==
STAmount(d.asset,
Number(90, 0)));
505 env.balance(d.vaultAccount, d.shares) ==
STAmount(d.share,
Number(-900, 0)));
509 testcase(
"Scale withdraw insignificant amount");
510 auto tx = d.vault.withdraw(
511 {.depositor = d.depositor,
518 testcase(
"Scale withdraw with rounding assets");
526 auto const start = env.balance(d.depositor, d.assets).number();
527 d.peek([](
SLE& vault,
auto&) ->
bool {
528 vault[sfAssetsAvailable] =
Number(1);
536 auto tx = d.vault.withdraw(
537 {.depositor = d.depositor,
542 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(900 - 25));
544 env.balance(d.depositor, d.assets) ==
547 env.balance(d.vaultAccount, d.assets) ==
550 env.balance(d.vaultAccount, d.shares) ==
555 testcase(
"Scale withdraw with rounding shares up (truncated post-fixCleanup3_4_0)");
563 auto const start = env.balance(d.depositor, d.assets).number();
564 auto tx = d.vault.withdraw(
565 {.depositor = d.depositor,
570 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(875 - 37));
572 env.balance(d.depositor, d.assets) ==
575 env.balance(d.vaultAccount, d.assets) ==
578 env.balance(d.vaultAccount, d.shares) ==
583 testcase(
"Scale withdraw with rounding shares down");
588 auto const start = env.balance(d.depositor, d.assets).number();
589 auto tx = d.vault.withdraw(
590 {.depositor = d.depositor,
595 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(838 - 37));
597 env.balance(d.depositor, d.assets) ==
600 env.balance(d.vaultAccount, d.assets) ==
603 env.balance(d.vaultAccount, d.shares) ==
608 testcase(
"Scale withdraw tiny amount rejected post-fixCleanup3_4_0");
613 auto const start = env.balance(d.depositor, d.assets).number();
614 auto tx = d.vault.withdraw(
615 {.depositor = d.depositor,
620 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(801));
621 BEAST_EXPECT(env.balance(d.depositor, d.assets) ==
STAmount(d.asset, start));
623 env.balance(d.vaultAccount, d.assets) ==
STAmount(d.asset,
Number(801, -1)));
625 env.balance(d.vaultAccount, d.shares) ==
STAmount(d.share, -
Number(801, 0)));
630 auto const rest = env.balance(d.vaultAccount, d.assets).number();
632 tx = d.vault.withdraw(
633 {.depositor = d.depositor,
635 .amount =
STAmount(d.asset, rest)});
638 BEAST_EXPECT(env.balance(d.depositor, d.shares).number() == 0);
639 BEAST_EXPECT(env.balance(d.vaultAccount, d.assets).number() == 0);
640 BEAST_EXPECT(env.balance(d.vaultAccount, d.shares).number() == 0);
644 testCase(18, [&,
this](Env& env, Data d) {
645 testcase(
"Scale clawback overflow");
648 auto tx = d.vault.deposit(
649 {.depositor = d.depositor, .id = d.keylet.key, .amount = d.asset(5)});
655 auto tx = d.vault.clawback(
658 .holder = d.depositor,
665 testCase(1, [&,
this](Env& env, Data d) {
667 auto const start = env.balance(d.depositor, d.assets).number();
668 auto tx = d.vault.deposit(
669 {.depositor = d.depositor,
674 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(1000));
676 env.balance(d.depositor, d.assets) ==
STAmount(d.asset, start -
Number(100, 0)));
678 env.balance(d.vaultAccount, d.assets) ==
STAmount(d.asset,
Number(100, 0)));
680 env.balance(d.vaultAccount, d.shares) ==
STAmount(d.share, -
Number(1000, 0)));
690 auto const start = env.balance(d.depositor, d.assets).number();
691 auto tx = d.vault.clawback(
694 .holder = d.depositor,
698 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(900));
699 BEAST_EXPECT(env.balance(d.depositor, d.assets) ==
STAmount(d.asset, start));
701 env.balance(d.vaultAccount, d.assets) ==
STAmount(d.asset,
Number(90, 0)));
703 env.balance(d.vaultAccount, d.shares) ==
STAmount(d.share, -
Number(900, 0)));
707 testcase(
"Scale clawback insignificant amount");
708 auto tx = d.vault.clawback(
711 .holder = d.depositor,
717 testcase(
"Scale clawback with rounding assets");
725 auto const start = env.balance(d.depositor, d.assets).number();
726 auto tx = d.vault.clawback(
729 .holder = d.depositor,
733 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(900 - 25));
734 BEAST_EXPECT(env.balance(d.depositor, d.assets) ==
STAmount(d.asset, start));
736 env.balance(d.vaultAccount, d.assets) ==
739 env.balance(d.vaultAccount, d.shares) ==
744 testcase(
"Scale clawback with rounding shares up (truncated post-fixCleanup3_4_0)");
752 auto const start = env.balance(d.depositor, d.assets).number();
753 auto tx = d.vault.clawback(
756 .holder = d.depositor,
760 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(875 - 37));
761 BEAST_EXPECT(env.balance(d.depositor, d.assets) ==
STAmount(d.asset, start));
763 env.balance(d.vaultAccount, d.assets) ==
766 env.balance(d.vaultAccount, d.shares) ==
771 testcase(
"Scale clawback with rounding shares down");
776 auto const start = env.balance(d.depositor, d.assets).number();
777 auto tx = d.vault.clawback(
780 .holder = d.depositor,
784 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(838 - 37));
785 BEAST_EXPECT(env.balance(d.depositor, d.assets) ==
STAmount(d.asset, start));
787 env.balance(d.vaultAccount, d.assets) ==
790 env.balance(d.vaultAccount, d.shares) ==
795 testcase(
"Scale clawback tiny amount rejected post-fixCleanup3_4_0");
800 auto const start = env.balance(d.depositor, d.assets).number();
801 auto tx = d.vault.clawback(
804 .holder = d.depositor,
808 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(801));
809 BEAST_EXPECT(env.balance(d.depositor, d.assets) ==
STAmount(d.asset, start));
811 env.balance(d.vaultAccount, d.assets) ==
STAmount(d.asset,
Number(801, -1)));
813 env.balance(d.vaultAccount, d.shares) ==
STAmount(d.share, -
Number(801, 0)));
818 auto const rest = env.balance(d.vaultAccount, d.assets).number();
819 d.peek([](
SLE& vault,
auto&) ->
bool {
820 vault[sfAssetsAvailable] =
Number(5);
828 tx = d.vault.clawback(
831 .holder = d.depositor,
832 .amount =
STAmount(d.asset, rest)});
835 BEAST_EXPECT(env.balance(d.depositor, d.shares).number() == 0);
836 BEAST_EXPECT(env.balance(d.vaultAccount, d.assets).number() == 0);
837 BEAST_EXPECT(env.balance(d.vaultAccount, d.shares).number() == 0);
844 testCase(1, [&,
this](Env& env, Data d) {
845 using namespace loan_broker;
846 using namespace loan;
848 testcase(
"Scale clawback clamped with outstanding loan");
850 auto tx = d.vault.deposit(
851 {.depositor = d.depositor,
856 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(1000));
859 auto const brokerKeylet =
861 env(
set(d.owner, d.keylet.key));
868 kPaymentInterval(120),
870 Sig(sfCounterpartySignature, d.owner),
871 Fee(env.current()->fees().base * 2),
876 auto const sle = env.le(d.keylet);
877 BEAST_EXPECT(sle->at(sfAssetsAvailable) ==
STAmount(d.asset,
Number(60, 0)));
878 BEAST_EXPECT(sle->at(sfAssetsTotal) ==
STAmount(d.asset,
Number(100, 0)));
883 tx = d.vault.clawback(
886 .holder = d.depositor,
892 auto const sle = env.le(d.keylet);
893 BEAST_EXPECT(sle !=
nullptr);
894 BEAST_EXPECT(sle->at(sfAssetsAvailable) ==
STAmount(d.asset,
Number(0, 0)));
895 BEAST_EXPECT(sle->at(sfAssetsTotal) ==
STAmount(d.asset,
Number(40, 0)));
898 BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(400));
903 auto seedLargeTotal = [](Env& env,
908 auto tx = d.vault.deposit(
909 {.depositor = d.depositor,
914 d.peek([&](
SLE& vault,
SLE& shares) ->
bool {
915 vault[sfAssetsTotal] = total;
916 vault[sfAssetsAvailable] = available;
917 shares[sfOutstandingAmount] = outstanding;
922 auto expectVault = [
this](
928 auto const sle = env.le(d.keylet);
929 BEAST_EXPECT(sle !=
nullptr);
930 BEAST_EXPECT(sle->at(sfAssetsTotal) == total);
931 BEAST_EXPECT(sle->at(sfAssetsAvailable) == available);
932 BEAST_EXPECT(env.balance(d.depositor, d.shares) == shareBalance);
936 testCase(0, [&,
this](Env& env, Data d) {
937 testcase(
"Scale clawback uses posterior scale across decade boundary");
939 Number const midGridTotal{10000000000000005ll};
940 Number const available{6};
941 seedLargeTotal(env, d, midGridTotal, available, 10000000000000005ull);
944 d.vault.clawback({.issuer = d.issuer, .id = d.keylet.key, .holder = d.depositor});
946 expectVault(env, d, midGridTotal - available,
Number(0), d.share(94));
950 testCase(0, [&,
this](Env& env, Data d) {
951 testcase(
"Scale clawback rejects amount below posterior scale");
953 Number const midGridTotal{12345678901234567ll};
954 Number const available{6};
955 seedLargeTotal(env, d, midGridTotal, available, 12345678901234567ull);
958 d.vault.clawback({.issuer = d.issuer, .id = d.keylet.key, .holder = d.depositor});
960 expectVault(env, d, midGridTotal, available, d.share(100));
964 testCase(0, [&,
this](Env& env, Data d) {
965 testcase(
"Scale clawback preserves exact posterior amount");
967 Number const midGridTotal{10000000000000005ll};
968 Number const available{15};
969 seedLargeTotal(env, d, midGridTotal, available, 10000000000000005ull);
972 d.vault.clawback({.issuer = d.issuer, .id = d.keylet.key, .holder = d.depositor});
974 expectVault(env, d, midGridTotal - available,
Number(0), d.share(85));
977 testCase(0, [&,
this](Env& env, Data d) {
978 testcase(
"Scale deposit rejects amount below posterior scale");
980 Number const midGridTotal{10000000000000005ll};
981 Number const available{100};
982 seedLargeTotal(env, d, midGridTotal, available, 10000000000000005ull);
984 auto const assetsBefore = env.balance(d.depositor, d.assets);
985 auto tx = d.vault.deposit(
986 {.depositor = d.depositor,
990 expectVault(env, d, midGridTotal, available, d.share(100));
991 BEAST_EXPECT(env.balance(d.depositor, d.assets) == assetsBefore);
994 testCase(0, [&,
this](Env& env, Data d) {
995 testcase(
"Scale withdraw uses posterior scale across decade boundary");
997 Number const midGridTotal{10000000000000005ll};
998 Number const available{100};
999 seedLargeTotal(env, d, midGridTotal, available, 10000000000000005ull);
1001 auto const assetsBefore = env.balance(d.depositor, d.assets);
1002 auto tx = d.vault.withdraw(
1003 {.depositor = d.depositor,
1007 expectVault(env, d, midGridTotal -
Number(15),
Number(85), d.share(85));
1009 env.balance(d.depositor, d.assets) ==
1021 Env env{*
this, testableAmendments()};
1023 Account const issuer{
"issuer"};
1025 Vault const vault{env};
1026 env.fund(XRP(1'000'000), issuer, owner);
1030 BEAST_EXPECT(maxInt64 ==
"9223372036854775807");
1034 BEAST_EXPECT(maxInt64Plus1 ==
"9223372036854775808");
1039 BEAST_EXPECT(maxInt64Plus2 ==
"9223372036854775809");
1042 BEAST_EXPECT(initialXRP ==
"100000000000000000");
1045 BEAST_EXPECT(initialXRPPlus1 ==
"100000000000000001");
1052 auto [tx,
keylet] = vault.create({.owner = owner, .asset = xrpAsset});
1053 tx[sfData] =
"4D65746144617461";
1055 tx[sfAssetsMaximum] = maxInt64;
1059 tx[sfAssetsMaximum] = initialXRPPlus1;
1063 tx[sfAssetsMaximum] = initialXRP;
1068 env.setParseFailureExpected(
true);
1071 tx[sfAssetsMaximum] = maxInt64Plus1;
1081 "invalidParamsField 'tx_json.AssetsMaximum' has invalid data.");
1086 tx[sfAssetsMaximum] = maxInt64Plus2;
1095 "invalidParamsField 'tx_json.AssetsMaximum' has invalid data.");
1101 auto const insertAt = maxInt64Plus2.size() - 3;
1102 auto const decimalTest = maxInt64Plus2.substr(0, insertAt) +
"." +
1103 maxInt64Plus2.substr(insertAt);
1104 BEAST_EXPECT(decimalTest ==
"9223372036854775.809");
1105 tx[sfAssetsMaximum] = decimalTest;
1114 "invalidParamsField 'tx_json.AssetsMaximum' has invalid data.");
1117 auto const vaultSle = env.le(newKeylet);
1118 BEAST_EXPECT(!vaultSle);
1125 MPTTester mptt{env, issuer, kMptInitNoFund};
1126 mptt.create({.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock});
1129 mptt.authorize({.account = owner});
1134 env(pay(issuer, owner, mptAsset(100'000)));
1137 auto [tx,
keylet] = vault.create({.owner = owner, .asset = mptAsset});
1138 tx[sfData] =
"4D65746144617461";
1140 tx[sfAssetsMaximum] = maxInt64;
1144 tx[sfAssetsMaximum] = initialXRPPlus1;
1148 tx[sfAssetsMaximum] = initialXRP;
1154 tx[sfAssetsMaximum] = maxInt64Plus2;
1163 "invalidParamsField 'tx_json.AssetsMaximum' has invalid data.");
1169 auto const insertAt = maxInt64Plus2.size() - 1;
1170 auto const decimalTest = maxInt64Plus2.substr(0, insertAt) +
"." +
1171 maxInt64Plus2.substr(insertAt);
1172 BEAST_EXPECT(decimalTest ==
"922337203685477580.9");
1173 tx[sfAssetsMaximum] = decimalTest;
1182 "invalidParamsField 'tx_json.AssetsMaximum' has invalid data.");
1185 auto const vaultSle = env.le(newKeylet);
1186 BEAST_EXPECT(!vaultSle);
1194 env.trust(iouAsset(1000), owner);
1195 env(pay(issuer, owner, iouAsset(200)));
1198 auto [tx,
keylet] = vault.create({.owner = owner, .asset = iouAsset});
1199 tx[sfData] =
"4D65746144617461";
1201 tx[sfAssetsMaximum] = maxInt64;
1205 tx[sfAssetsMaximum] = initialXRPPlus1;
1209 tx[sfAssetsMaximum] = initialXRP;
1215 env.setParseFailureExpected(
true);
1218 tx[sfAssetsMaximum] = maxInt64Plus2;
1227 "invalidParamsField 'tx_json.AssetsMaximum' has invalid data.");
1230 tx[sfAssetsMaximum] =
"1000000000000000e80";
1233 tx[sfAssetsMaximum] =
"1000000000000000e-96";
1238 auto const newKeylet =
1242 auto const insertAt = maxInt64Plus2.size() - 1;
1243 auto const decimalTest = maxInt64Plus2.substr(0, insertAt) +
"." +
1244 maxInt64Plus2.substr(insertAt);
1245 BEAST_EXPECT(decimalTest ==
"922337203685477580.9");
1246 tx[sfAssetsMaximum] = decimalTest;
1255 "invalidParamsField 'tx_json.AssetsMaximum' has invalid data.");
1258 auto const vaultSle = env.le(newKeylet);
1259 BEAST_EXPECT(!vaultSle);
1262 tx[sfAssetsMaximum] =
"9223372036854775807e40";
1263 auto const newKeylet =
1268 auto const vaultSle = env.le(newKeylet);
1269 if (!BEAST_EXPECT(vaultSle))
1273 (vaultSle->at(sfAssetsMaximum) ==
1274 Number{9223372036854776, 43, Number::Normalized{}}));
1277 tx[sfAssetsMaximum] =
"9223372036854775807e-40";
1278 auto const newKeylet =
1283 auto const vaultSle = env.le(newKeylet);
1284 if (!BEAST_EXPECT(vaultSle))
1288 (vaultSle->at(sfAssetsMaximum) ==
1289 Number{9223372036854776, -37, Number::Normalized{}}));
1292 tx[sfAssetsMaximum] =
"9223372036854775807e-100";
1293 auto const newKeylet =
1299 auto const vaultSle = env.le(newKeylet);
1300 if (!BEAST_EXPECT(vaultSle))
1303 BEAST_EXPECT(vaultSle->at(sfAssetsMaximum) ==
kNumZero);
1308 tx[sfAssetsMaximum] =
"1000000000000000e81";
1315 auto const g = env.getParseFailureGuard(
true);
1316 tx[sfAssetsMaximum] =
"18446744073709551617e5";
1318 BEAST_EXPECTS(
false,
"Expected parse_error for mantissa larger than uint64 max");
1320 catch (ParseError
const& e)
1322 using namespace std::string_literals;
1324 e.what() ==
"invalidParamsField 'tx_json.AssetsMaximum' has invalid data."s);