21#include <test/jtx/AMMTest.h>
23#include <xrpld/ledger/View.h>
25#include <xrpl/basics/base_uint.h>
26#include <xrpl/beast/unit_test/suite.h>
27#include <xrpl/json/json_forwards.h>
28#include <xrpl/json/json_value.h>
29#include <xrpl/protocol/AccountID.h>
30#include <xrpl/protocol/Asset.h>
31#include <xrpl/protocol/Feature.h>
32#include <xrpl/protocol/Indexes.h>
33#include <xrpl/protocol/Issue.h>
34#include <xrpl/protocol/MPTIssue.h>
35#include <xrpl/protocol/Protocol.h>
36#include <xrpl/protocol/SField.h>
37#include <xrpl/protocol/STAmount.h>
38#include <xrpl/protocol/STNumber.h>
39#include <xrpl/protocol/TER.h>
40#include <xrpl/protocol/TxFlags.h>
41#include <xrpl/protocol/XRPAmount.h>
42#include <xrpl/protocol/jss.h>
59 using namespace test::jtx;
61 auto const testSequence = [
this](
64 Account
const& issuer,
66 Account
const& depositor,
67 Account
const& charlie,
70 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
71 tx[sfData] =
"AFEED00E";
72 tx[sfAssetsMaximum] = asset(100).number();
75 BEAST_EXPECT(env.le(keylet));
77 auto const share = [&env, keylet = keylet,
this]() ->
PrettyAsset {
78 auto const vault = env.le(keylet);
79 BEAST_EXPECT(vault !=
nullptr);
80 return MPTIssue(vault->at(sfShareMPTID));
84 Account alice{
"alice"};
87 env.fund(XRP(1000), alice, dave, erin);
93 testcase(prefix +
" fail to deposit more than assets held");
94 auto tx = vault.deposit(
95 {.depositor = depositor,
97 .amount = asset(10000)});
102 testcase(prefix +
" deposit non-zero amount");
103 auto tx = vault.deposit(
104 {.depositor = depositor,
106 .amount = asset(50)});
111 testcase(prefix +
" deposit non-zero amount again");
112 auto tx = vault.deposit(
113 {.depositor = depositor,
115 .amount = asset(50)});
120 testcase(prefix +
" fail to delete non-empty vault");
121 auto tx = vault.del({.owner = owner, .id = keylet.
key});
126 testcase(prefix +
" fail to update because wrong owner");
127 auto tx = vault.set({.owner = issuer, .id = keylet.
key});
128 tx[sfAssetsMaximum] = asset(50).number();
134 prefix +
" fail to set maximum lower than current amount");
135 auto tx = vault.set({.owner = owner, .id = keylet.
key});
136 tx[sfAssetsMaximum] = asset(50).number();
141 testcase(prefix +
" set maximum higher than current amount");
142 auto tx = vault.set({.owner = owner, .id = keylet.
key});
143 tx[sfAssetsMaximum] = asset(150).number();
149 auto tx = vault.set({.owner = owner, .id = keylet.
key});
155 testcase(prefix +
" fail to set domain on public vault");
156 auto tx = vault.set({.owner = owner, .id = keylet.
key});
162 testcase(prefix +
" fail to deposit more than maximum");
163 auto tx = vault.deposit(
164 {.depositor = depositor,
166 .amount = asset(100)});
171 testcase(prefix +
" reset maximum to zero i.e. not enforced");
172 auto tx = vault.set({.owner = owner, .id = keylet.
key});
173 tx[sfAssetsMaximum] = asset(0).number();
178 testcase(prefix +
" fail to withdraw more than assets held");
179 auto tx = vault.withdraw(
180 {.depositor = depositor,
182 .amount = asset(1000)});
187 testcase(prefix +
" deposit some more");
188 auto tx = vault.deposit(
189 {.depositor = depositor,
191 .amount = asset(100)});
196 testcase(prefix +
" clawback some");
199 auto tx = vault.clawback(
203 .amount = asset(10)});
211 auto tx = vault.clawback(
212 {.issuer = issuer, .id = keylet.
key, .holder = depositor});
216 if (!asset.raw().native())
218 testcase(prefix +
" deposit again");
219 auto tx = vault.deposit(
220 {.depositor = depositor,
222 .amount = asset(200)});
228 prefix +
" fail to withdraw to 3rd party lsfDepositAuth");
229 auto tx = vault.withdraw(
230 {.depositor = depositor,
232 .amount = asset(100)});
233 tx[sfDestination] = alice.human();
237 if (!asset.raw().native())
240 prefix +
" fail to withdraw to 3rd party no authorization");
241 auto tx = vault.withdraw(
242 {.depositor = depositor,
244 .amount = asset(100)});
245 tx[sfDestination] = erin.human();
250 if (!asset.raw().native() && asset.raw().holds<
Issue>())
252 testcase(prefix +
" temporary authorization for 3rd party");
253 env(trust(erin, asset(1000)));
254 env(trust(issuer, asset(0), erin,
tfSetfAuth));
255 env(pay(issuer, erin, asset(10)));
258 auto tx = vault.deposit(
259 {.depositor = erin, .id = keylet.
key, .amount = asset(10)});
261 env(pay(erin, depositor, share(10)));
263 testcase(prefix +
" withdraw to authorized 3rd party");
266 {.depositor = depositor,
268 .amount = asset(10)});
269 tx[sfDestination] = erin.human();
272 env(pay(erin, issuer, asset(10)));
274 testcase(prefix +
" fail to pay to unauthorized 3rd party");
275 env(trust(erin, asset(0)));
277 env(pay(depositor, erin, share(1)), ter{
tecNO_LINE});
283 " fail to withdraw to 3rd party lsfRequireDestTag");
284 auto tx = vault.withdraw(
285 {.depositor = depositor,
287 .amount = asset(100)});
288 tx[sfDestination] = dave.human();
293 testcase(prefix +
" withdraw to authorized 3rd party");
294 auto tx = vault.withdraw(
295 {.depositor = depositor,
297 .amount = asset(100)});
298 tx[sfDestination] = charlie.human();
303 testcase(prefix +
" withdraw to issuer");
304 auto tx = vault.withdraw(
305 {.depositor = depositor,
307 .amount = asset(50)});
308 tx[sfDestination] = issuer.human();
313 testcase(prefix +
" withdraw remaining assets");
314 auto tx = vault.withdraw(
315 {.depositor = depositor,
317 .amount = asset(50)});
322 testcase(prefix +
" fail to delete because wrong owner");
323 auto tx = vault.del({.owner = issuer, .id = keylet.
key});
328 testcase(prefix +
" delete empty vault");
329 auto tx = vault.del({.owner = owner, .id = keylet.
key});
331 BEAST_EXPECT(!env.le(keylet));
335 auto testCases = [
this, &testSequence](
339 Account
const& issuer,
340 Account
const& owner,
341 Account
const& depositor,
342 Account
const& charlie)> setup) {
343 Env env{*
this, supported_amendments() | featureSingleAssetVault};
344 Account issuer{
"issuer"};
345 Account owner{
"owner"};
346 Account depositor{
"depositor"};
347 Account charlie{
"charlie"};
349 env.fund(XRP(1000), issuer, owner, depositor, charlie);
357 PrettyAsset asset = setup(env, issuer, owner, depositor, charlie);
359 prefix, env, issuer, owner, depositor, charlie, vault, asset);
365 Account
const& issuer,
366 Account
const& owner,
367 Account
const& depositor,
375 Account
const& issuer,
376 Account
const& owner,
377 Account
const& depositor,
378 Account
const& charlie) ->
Asset {
380 env(trust(owner, asset(1000)));
381 env(trust(depositor, asset(1000)));
382 env(trust(charlie, asset(1000)));
383 env(trust(issuer, asset(0), owner,
tfSetfAuth));
384 env(trust(issuer, asset(0), depositor,
tfSetfAuth));
385 env(trust(issuer, asset(0), charlie,
tfSetfAuth));
386 env(pay(issuer, depositor, asset(1000)));
394 Account
const& issuer,
395 Account
const& owner,
396 Account
const& depositor,
397 Account
const& charlie) ->
Asset {
398 MPTTester mptt{env, issuer, mptInitNoFund};
403 mptt.authorize({.account = depositor});
404 mptt.authorize({.account = charlie});
405 env(pay(issuer, depositor, asset(1000)));
414 using namespace test::jtx;
419 supported_amendments() | featureSingleAssetVault;
422 auto testCase = [&,
this](
425 Account
const& issuer,
426 Account
const& owner,
429 CaseArgs args = {}) {
430 Env env{*
this, args.features};
431 Account issuer{
"issuer"};
432 Account owner{
"owner"};
434 env.fund(XRP(1000), issuer, owner);
442 env(trust(owner, asset(1000)));
443 env(trust(issuer, asset(0), owner,
tfSetfAuth));
444 env(pay(issuer, owner, asset(1000)));
447 test(env, issuer, owner, asset, vault);
452 Account
const& issuer,
453 Account
const& owner,
456 testcase(
"disabled single asset vault");
459 vault.create({.owner = owner, .asset = asset});
463 auto tx = vault.set({.owner = owner, .id = keylet.
key});
468 auto tx = vault.deposit(
471 .amount = asset(10)});
476 auto tx = vault.withdraw(
479 .amount = asset(10)});
484 auto tx = vault.clawback(
488 .amount = asset(10)});
493 auto tx = vault.del({.owner = owner, .id = keylet.
key});
497 {.features = supported_amendments() - featureSingleAssetVault});
499 testCase([&](Env& env,
500 Account
const& issuer,
501 Account
const& owner,
506 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
511 auto tx = vault.set({.owner = owner, .id = keylet.
key});
517 auto tx = vault.deposit(
520 .amount = asset(10)});
526 auto tx = vault.withdraw(
529 .amount = asset(10)});
535 auto tx = vault.clawback(
539 .amount = asset(10)});
545 auto tx = vault.del({.owner = owner, .id = keylet.
key});
551 testCase([&](Env& env,
552 Account
const& issuer,
553 Account
const& owner,
558 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
563 auto tx = vault.set({.owner = owner, .id = keylet.
key});
569 auto tx = vault.deposit(
572 .amount = asset(10)});
578 auto tx = vault.withdraw(
581 .amount = asset(10)});
587 auto tx = vault.clawback(
591 .amount = asset(10)});
597 auto tx = vault.del({.owner = owner, .id = keylet.
key});
606 Account
const& owner,
609 testcase(
"disabled permissioned domain");
612 vault.create({.owner = owner, .asset =
xrpIssue()});
617 auto tx = vault.set({.owner = owner, .id = keylet.
key});
623 auto tx = vault.set({.owner = owner, .id = keylet.
key});
624 tx[sfDomainID] =
"0";
628 {.features = (supported_amendments() | featureSingleAssetVault) -
629 featurePermissionedDomains});
631 testCase([&](Env& env,
632 Account
const& issuer,
633 Account
const& owner,
639 vault.create({.owner = owner, .asset =
xrpIssue()});
642 auto tx = vault.set({
650 auto tx = vault.deposit(
653 .amount = asset(10)});
658 auto tx = vault.withdraw(
661 .amount = asset(10)});
666 auto tx = vault.clawback(
670 .amount = asset(10)});
675 auto tx = vault.del({
683 testCase([&](Env& env,
684 Account
const& issuer,
685 Account
const& owner,
690 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
693 auto tx = vault.clawback(
697 .amount = asset(10)});
702 testCase([&](Env& env,
704 Account
const& owner,
707 testcase(
"withdraw to bad destination");
709 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
712 auto tx = vault.withdraw(
715 .amount = asset(10)});
716 tx[jss::Destination] =
"0";
721 testCase([&](Env& env,
723 Account
const& owner,
726 testcase(
"create or set invalid data");
728 auto [tx1, keylet] = vault.create({.owner = owner, .asset = asset});
744 auto tx = vault.set({.owner = owner, .id = keylet.
key});
750 auto tx = vault.set({.owner = owner, .id = keylet.
key});
757 testCase([&](Env& env,
759 Account
const& owner,
764 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
767 auto tx = vault.set({.owner = owner, .id = keylet.
key});
772 testCase([&](Env& env,
774 Account
const& owner,
777 testcase(
"create with invalid metadata");
779 auto [tx1, keylet] = vault.create({.owner = owner, .asset = asset});
783 tx[sfMPTokenMetadata] =
"";
796 testCase([&](Env& env,
798 Account
const& owner,
803 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
806 auto tx = vault.set({.owner = owner, .id = keylet.
key});
812 testCase([&](Env& env,
814 Account
const& owner,
819 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
822 auto tx = vault.deposit(
830 auto tx = vault.deposit(
831 {.depositor = owner, .id = keylet.
key, .amount = asset(0)});
836 testCase([&](Env& env,
838 Account
const& owner,
841 testcase(
"invalid set immutable flag");
843 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
846 auto tx = vault.set({.owner = owner, .id = keylet.
key});
852 testCase([&](Env& env,
854 Account
const& owner,
857 testcase(
"invalid withdraw amount");
859 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
862 auto tx = vault.withdraw(
870 auto tx = vault.withdraw(
871 {.depositor = owner, .id = keylet.
key, .amount = asset(0)});
876 testCase([&](Env& env,
877 Account
const& issuer,
878 Account
const& owner,
883 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
886 auto tx = vault.clawback(
890 .amount = asset(50)});
895 auto tx = vault.clawback(
904 testCase([&](Env& env,
906 Account
const& owner,
911 auto [tx1, keylet] = vault.create({.owner = owner, .asset = asset});
915 tx[sfWithdrawalPolicy] = 0;
934 tx[sfDomainID] =
"0";
944 using namespace test::jtx;
948 Account
const& issuer,
949 Account
const& owner,
950 Account
const& depositor,
952 Vault& vault)> test) {
953 Env env{*
this, supported_amendments() | featureSingleAssetVault};
954 Account issuer{
"issuer"};
955 Account owner{
"owner"};
956 Account depositor{
"depositor"};
957 env.fund(XRP(1000), issuer, owner, depositor);
962 test(env, issuer, owner, depositor, asset, vault);
967 Account
const& issuer,
968 Account
const& owner,
969 Account
const& depositor,
974 tx[sfAssetsMaximum] = asset(0).number();
980 Account
const& issuer,
981 Account
const& owner,
982 Account
const& depositor,
986 auto tx = vault.deposit(
987 {.depositor = depositor,
989 .amount = asset(10)});
995 Account
const& issuer,
996 Account
const& owner,
997 Account
const& depositor,
1000 testcase(
"nothing to withdraw from");
1001 auto tx = vault.withdraw(
1002 {.depositor = depositor,
1004 .amount = asset(10)});
1010 Account
const& issuer,
1011 Account
const& owner,
1012 Account
const& depositor,
1022 Account
const& issuer,
1023 Account
const& owner,
1024 Account
const& depositor,
1027 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1034 Account
const& issuer,
1035 Account
const& owner,
1036 Account
const& depositor,
1039 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1040 tx[sfWithdrawalPolicy] = 1;
1041 testcase(
"explicitly select withdrawal policy");
1047 Account
const& issuer,
1048 Account
const& owner,
1049 Account
const& depositor,
1052 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1059 Account
const& issuer,
1060 Account
const& owner,
1061 Account
const& depositor,
1064 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1068 env(pay(owner, issuer, XRP(775)));
1075 Account
const& issuer,
1076 Account
const& owner,
1077 Account
const& depositor,
1080 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1091 using namespace test::jtx;
1094 testcase(
"IOU fail create frozen");
1096 *
this, supported_amendments() | featureSingleAssetVault};
1097 Account issuer{
"issuer"};
1098 Account owner{
"owner"};
1099 env.fund(XRP(1000), issuer, owner);
1105 Asset asset = issuer[
"IOU"];
1107 vault.create({.owner = owner, .asset = asset});
1114 testcase(
"IOU fail create no ripling");
1116 *
this, supported_amendments() | featureSingleAssetVault};
1117 Account issuer{
"issuer"};
1118 Account owner{
"owner"};
1119 env.fund(XRP(1000), issuer, owner);
1125 Asset asset = issuer[
"IOU"];
1127 vault.create({.owner = owner, .asset = asset});
1135 *
this, supported_amendments() | featureSingleAssetVault};
1136 Account issuer{
"issuer"};
1137 Account owner{
"owner"};
1138 env.fund(XRP(1000), owner);
1142 Asset asset = issuer[
"IOU"];
1145 vault.create({.owner = owner, .asset = asset});
1153 testcase(
"IOU fail create vault for AMM LPToken");
1154 Env env{*
this, supported_amendments() | featureSingleAssetVault};
1155 Account
const gw(
"gateway");
1156 Account
const alice(
"alice");
1157 Account
const carol(
"carol");
1158 IOU
const USD = gw[
"USD"];
1160 auto const [asset1, asset2] =
1165 auto const defXRP = XRP(30000);
1168 return a + XRP(1000);
1175 auto const toFund1 = tofund(asset1);
1176 auto const toFund2 = tofund(asset2);
1177 BEAST_EXPECT(asset1 <= toFund1 && asset2 <= toFund2);
1179 if (!asset1.native() && !asset2.native())
1180 fund(env, gw, {alice, carol}, {toFund1, toFund2}, Fund::All);
1181 else if (asset1.native())
1182 fund(env, gw, {alice, carol}, toFund1, {toFund2}, Fund::All);
1183 else if (asset2.native())
1184 fund(env, gw, {alice, carol}, toFund2, {toFund1}, Fund::All);
1187 env, alice, asset1, asset2, CreateArg{.log =
false, .tfee = 0});
1189 Account
const owner{
"owner"};
1190 env.fund(XRP(1000000), owner);
1194 vault.create({.owner = owner, .asset = ammAlice.lptIssue()});
1203 using namespace test::jtx;
1205 Env env{*
this, supported_amendments() | featureSingleAssetVault};
1206 Account issuer{
"issuer"};
1207 Account owner{
"owner"};
1208 Account depositor{
"depositor"};
1209 env.fund(XRP(1000), issuer, owner, depositor);
1213 MPTTester mptt{env, issuer, mptInitNoFund};
1217 Asset asset = mptt.issuanceID();
1218 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1225 using namespace test::jtx;
1227 Env env{*
this, supported_amendments() | featureSingleAssetVault};
1228 Account issuer{
"issuer"};
1229 Account owner{
"owner"};
1230 Account depositor{
"depositor"};
1231 env.fund(XRP(1000), issuer, owner, depositor);
1236 env.trust(asset(1000), owner);
1237 env(pay(issuer, owner, asset(100)));
1238 env.trust(asset(1000), depositor);
1239 env(pay(issuer, depositor, asset(100)));
1242 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1248 testcase(
"nontransferable deposits");
1249 auto tx1 = vault.deposit(
1250 {.depositor = depositor,
1252 .amount = asset(40)});
1255 auto tx2 = vault.deposit(
1256 {.depositor = owner, .id = keylet.
key, .amount = asset(60)});
1261 auto const vaultAccount =
1263 auto jvVault = env.rpc(
"vault_info",
strHex(key));
1266 jvVault[jss::result][jss::vault][sfAssetsTotal] ==
"100");
1268 jvVault[jss::result][jss::vault][jss::shares]
1269 [sfOutstandingAmount] ==
"100");
1272 return parseBase58<AccountID>(
1273 jvVault[jss::result][jss::vault][jss::Account]
1278 auto const MptID =
makeMptID(1, vaultAccount);
1279 Asset shares = MptID;
1282 testcase(
"nontransferable shares cannot be moved");
1283 env(pay(owner, depositor, shares(10)), ter{
tecNO_AUTH});
1284 env(pay(depositor, owner, shares(10)), ter{
tecNO_AUTH});
1288 testcase(
"nontransferable shares can be used to withdraw");
1289 auto tx1 = vault.withdraw(
1290 {.depositor = depositor,
1292 .amount = asset(20)});
1295 auto tx2 = vault.withdraw(
1296 {.depositor = owner, .id = keylet.
key, .amount = asset(30)});
1302 testcase(
"nontransferable shares balance check");
1303 auto jvVault = env.rpc(
"vault_info",
strHex(keylet.
key));
1305 jvVault[jss::result][jss::vault][sfAssetsTotal] ==
"50");
1307 jvVault[jss::result][jss::vault][jss::shares]
1308 [sfOutstandingAmount] ==
"50");
1312 testcase(
"nontransferable shares withdraw rest");
1313 auto tx1 = vault.withdraw(
1314 {.depositor = depositor,
1316 .amount = asset(20)});
1319 auto tx2 = vault.withdraw(
1320 {.depositor = owner, .id = keylet.
key, .amount = asset(30)});
1326 testcase(
"nontransferable shares delete empty vault");
1327 auto tx = vault.del({.owner = owner, .id = keylet.
key});
1329 BEAST_EXPECT(!env.le(keylet));
1336 using namespace test::jtx;
1340 bool enableClawback =
true;
1343 auto testCase = [
this](
1346 Account
const& issuer,
1347 Account
const& owner,
1348 Account
const& depositor,
1351 MPTTester& mptt)> test,
1352 CaseArgs args = {}) {
1353 Env env{*
this, supported_amendments() | featureSingleAssetVault};
1354 Account issuer{
"issuer"};
1355 Account owner{
"owner"};
1356 Account depositor{
"depositor"};
1357 env.fund(XRP(1000), issuer, owner, depositor);
1361 MPTTester mptt{env, issuer, mptInitNoFund};
1368 mptt.authorize({.account = owner});
1369 mptt.authorize({.account = issuer, .holder = owner});
1370 mptt.authorize({.account = depositor});
1371 mptt.authorize({.account = issuer, .holder = depositor});
1372 env(pay(issuer, depositor, asset(1000)));
1375 test(env, issuer, owner, depositor, asset, vault, mptt);
1380 Account
const& issuer,
1381 Account
const& owner,
1382 Account
const& depositor,
1386 testcase(
"MPT nothing to clawback from");
1387 auto tx = vault.clawback(
1390 .holder = depositor,
1391 .amount = asset(10)});
1397 Account
const& issuer,
1398 Account
const& owner,
1399 Account
const& depositor,
1403 testcase(
"MPT global lock blocks create");
1404 mptt.set({.account = issuer, .flags =
tfMPTLock});
1405 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1411 Account
const& issuer,
1412 Account
const& owner,
1413 Account
const& depositor,
1417 testcase(
"MPT global lock blocks deposit");
1418 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1422 mptt.set({.account = issuer, .flags =
tfMPTLock});
1426 {.depositor = depositor,
1428 .amount = asset(100)});
1433 tx = vault.del({.owner = owner, .id = keylet.
key});
1439 Account
const& issuer,
1440 Account
const& owner,
1441 Account
const& depositor,
1445 testcase(
"MPT global lock blocks withdrawal");
1446 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1450 {.depositor = depositor,
1452 .amount = asset(100)});
1458 auto v = env.le(keylet);
1460 MPTID share = (*v)[sfShareMPTID];
1462 BEAST_EXPECT(issuance);
1463 Number outstandingShares = issuance->at(sfOutstandingAmount);
1464 BEAST_EXPECT(outstandingShares == 100);
1466 mptt.set({.account = issuer, .flags =
tfMPTLock});
1469 tx = vault.withdraw(
1470 {.depositor = depositor,
1472 .amount = asset(100)});
1475 tx[sfDestination] = issuer.human();
1479 tx = vault.clawback(
1482 .holder = depositor,
1483 .amount = asset(0)});
1488 tx = vault.del({.owner = owner, .id = keylet.
key});
1494 Account
const& issuer,
1495 Account
const& owner,
1496 Account
const& depositor,
1500 testcase(
"MPT only issuer can clawback");
1502 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1507 {.depositor = depositor,
1509 .amount = asset(100)});
1514 auto tx = vault.clawback(
1515 {.issuer = owner, .id = keylet.
key, .holder = depositor});
1522 Account
const& issuer,
1523 Account
const& owner,
1524 Account
const& depositor,
1530 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1535 {.depositor = depositor,
1537 .amount = asset(1000)});
1542 auto tx = vault.clawback(
1545 .holder = depositor,
1546 .amount = asset(0)});
1550 mptt.destroy({.issuer = issuer, .id = mptt.issuanceID()});
1555 vault.create({.owner = depositor, .asset = asset});
1560 auto tx = vault.deposit(
1561 {.depositor = depositor,
1563 .amount = asset(10)});
1568 auto tx = vault.withdraw(
1569 {.depositor = depositor,
1571 .amount = asset(10)});
1576 auto tx = vault.clawback(
1579 .holder = depositor,
1580 .amount = asset(0)});
1584 env(vault.del({.owner = owner, .id = keylet.key}));
1590 Account
const& issuer,
1591 Account
const& owner,
1592 Account
const& depositor,
1599 vault.create({.owner = owner, .asset = asset});
1604 {.depositor = depositor,
1606 .amount = asset(1000)});
1611 auto tx = vault.clawback(
1614 .holder = depositor,
1615 .amount = asset(0)});
1619 {.enableClawback =
false});
1623 Account
const& issuer,
1624 Account
const& owner,
1625 Account
const& depositor,
1630 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1634 {.depositor = depositor,
1636 .amount = asset(1000)});
1642 .holder = depositor,
1647 auto tx = vault.withdraw(
1648 {.depositor = depositor,
1650 .amount = asset(100)});
1654 tx[sfDestination] = issuer.human();
1656 tx[sfDestination] = owner.human();
1663 auto tx = vault.deposit(
1664 {.depositor = depositor,
1666 .amount = asset(100)});
1671 tx = vault.clawback(
1674 .holder = depositor,
1675 .amount = asset(800)});
1678 env(vault.del({.owner = owner, .id = keylet.key}));
1683 Account
const& issuer,
1684 Account
const& owner,
1685 Account
const& depositor,
1689 testcase(
"MPT lock of vault pseudo-account");
1690 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1694 auto const vaultAccount =
1695 [&env, keylet = keylet,
this]() ->
AccountID {
1696 auto const vault = env.le(keylet);
1697 BEAST_EXPECT(vault !=
nullptr);
1698 return vault->at(sfAccount);
1702 {.depositor = depositor,
1704 .amount = asset(100)});
1710 jv[jss::Account] = issuer.human();
1711 jv[sfMPTokenIssuanceID] =
1713 jv[jss::Holder] =
toBase58(vaultAccount);
1714 jv[jss::TransactionType] = jss::MPTokenIssuanceSet;
1722 {.depositor = depositor,
1724 .amount = asset(100)});
1727 tx = vault.withdraw(
1728 {.depositor = depositor,
1730 .amount = asset(100)});
1734 tx = vault.clawback(
1737 .holder = depositor,
1738 .amount = asset(100)});
1742 tx = vault.del({.owner = owner, .id = keylet.
key});
1749 Env env{*
this, supported_amendments() | featureSingleAssetVault};
1750 Account owner{
"owner"};
1751 Account issuer{
"issuer"};
1752 env.fund(XRP(1000000), owner, issuer);
1756 MPTTester mptt{env, issuer, mptInitNoFund};
1760 mptt.authorize({.account = owner});
1761 mptt.authorize({.account = issuer, .holder = owner});
1763 env(pay(issuer, owner, asset(100)));
1764 auto [tx1, k1] = vault.create({.owner = owner, .asset = asset});
1768 auto const shares = [&env, keylet = k1,
this]() ->
Asset {
1769 auto const vault = env.le(keylet);
1770 BEAST_EXPECT(vault !=
nullptr);
1771 return MPTIssue(vault->at(sfShareMPTID));
1774 auto [tx2, k2] = vault.create({.owner = owner, .asset = shares});
1783 using namespace test::jtx;
1789 Account
const& owner,
1790 Account
const& issuer,
1791 Account
const& charlie,
1799 *
this, supported_amendments() | featureSingleAssetVault};
1800 Account
const owner{
"owner"};
1801 Account
const issuer{
"issuer"};
1802 Account
const charlie{
"charlie"};
1804 env.fund(XRP(1000), issuer, owner, charlie);
1809 env.trust(asset(1000), owner);
1810 env(pay(issuer, owner, asset(200)));
1811 env(rate(issuer, 1.25));
1814 auto const [tx, keylet] =
1815 vault.create({.owner = owner, .asset = asset});
1819 auto const vaultAccount =
1821 return env.le(keylet)->at(sfAccount);
1824 return env.le(keylet)->at(sfShareMPTID);
1826 auto const vaultBalance =
1827 [&env, &vaultAccount, issue = asset.
raw().
get<
Issue>()](
1829 auto const account = vaultAccount(keylet);
1834 env.lookup(issue.account).name()};
1835 auto amount = sle->getFieldAmount(sfBalance);
1837 if (account > issue.account)
1839 return {amount, env.lookup(issue.account).name()};
1856 Account
const& owner,
1857 Account
const& issuer,
1863 testcase(
"IOU cannot use different asset");
1866 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1872 auto tx = [&, account = vaultAccount(keylet)]() {
1874 jv[jss::Account] = issuer.human();
1876 auto& ja = jv[jss::LimitAmount] =
1878 ja[jss::issuer] =
toBase58(account);
1880 jv[jss::TransactionType] = jss::TrustSet;
1889 auto tx = vault.deposit(
1890 {.depositor = issuer, .id = keylet.
key, .amount = foo(20)});
1896 auto tx = vault.withdraw(
1897 {.depositor = issuer, .id = keylet.
key, .amount = foo(20)});
1902 env(vault.del({.owner = owner, .id = keylet.key}));
1908 Account
const& owner,
1909 Account
const& issuer,
1910 Account
const& charlie,
1916 testcase(
"IOU frozen trust line to vault account");
1918 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1923 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
1926 Asset const share =
Asset(issuanceId(keylet));
1929 auto trustSet = [&, account = vaultAccount(keylet)]() {
1931 jv[jss::Account] = issuer.human();
1933 auto& ja = jv[jss::LimitAmount] =
1935 ja[jss::issuer] =
toBase58(account);
1937 jv[jss::TransactionType] = jss::TrustSet;
1949 auto tx = vault.deposit(
1950 {.depositor = owner,
1952 .amount = asset(80)});
1957 auto tx = vault.withdraw(
1958 {.depositor = owner,
1960 .amount = asset(100)});
1964 tx[sfDestination] = charlie.human();
1971 auto tx = vault.clawback(
1975 .amount = asset(50)});
1986 {.depositor = owner, .id = keylet.key, .amount = share(50)}));
1988 env(vault.del({.owner = owner, .id = keylet.key}));
1994 Account
const& owner,
1995 Account
const& issuer,
1996 Account
const& charlie,
2001 auto vaultBalance) {
2002 testcase(
"IOU transfer fees not applied");
2004 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2009 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
2013 Asset const share =
Asset(issuanceId(keylet));
2016 BEAST_EXPECT(env.balance(owner, issue) == asset(100));
2017 BEAST_EXPECT(vaultBalance(keylet) == asset(100));
2020 auto tx = vault.clawback(
2024 .amount = asset(50)});
2030 BEAST_EXPECT(env.balance(owner, issue) == asset(100));
2031 BEAST_EXPECT(vaultBalance(keylet) == asset(50));
2034 {.depositor = owner, .id = keylet.key, .amount = share(20)}));
2037 BEAST_EXPECT(env.balance(owner, issue) == asset(120));
2038 BEAST_EXPECT(vaultBalance(keylet) == asset(30));
2041 auto tx = vault.withdraw(
2042 {.depositor = owner,
2044 .amount = share(30)});
2045 tx[sfDestination] = charlie.human();
2050 BEAST_EXPECT(env.balance(owner, issue) == asset(120));
2051 BEAST_EXPECT(env.balance(charlie, issue) == asset(30));
2052 BEAST_EXPECT(vaultBalance(keylet) == asset(0));
2054 env(vault.del({.owner = owner, .id = keylet.key}));
2060 Account
const& owner,
2061 Account
const& issuer,
2062 Account
const& charlie,
2067 testcase(
"IOU frozen trust line to depositor");
2069 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2074 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
2079 auto tx = vault.withdraw(
2080 {.depositor = owner,
2082 .amount = asset(10)});
2083 tx[sfDestination] = charlie.human();
2086 env(withdrawToCharlie);
2093 auto const withdraw = vault.withdraw(
2094 {.depositor = owner, .id = keylet.
key, .amount = asset(10)});
2103 auto tx = vault.deposit(
2104 {.depositor = owner,
2106 .amount = asset(10)});
2112 auto tx = vault.clawback(
2116 .amount = asset(0)});
2121 env(vault.del({.owner = owner, .id = keylet.key}));
2127 Account
const& owner,
2128 Account
const& issuer,
2129 Account
const& charlie,
2134 testcase(
"IOU frozen trust line to 3rd party");
2136 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2141 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
2146 auto tx = vault.withdraw(
2147 {.depositor = owner,
2149 .amount = asset(10)});
2150 tx[sfDestination] = charlie.human();
2153 env(withdrawToCharlie);
2156 env(trust(issuer, asset(0), charlie,
tfSetFreeze));
2160 auto const withdraw = vault.withdraw(
2161 {.depositor = owner, .id = keylet.
key, .amount = asset(10)});
2173 .amount = asset(0)}));
2176 env(vault.del({.owner = owner, .id = keylet.key}));
2182 Account
const& owner,
2183 Account
const& issuer,
2184 Account
const& charlie,
2191 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2196 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
2204 auto tx = vault.withdraw(
2205 {.depositor = owner,
2207 .amount = asset(10)});
2211 tx[sfDestination] = charlie.human();
2217 {.depositor = owner,
2219 .amount = asset(10)});
2229 .amount = asset(0)}));
2232 env(vault.del({.owner = owner, .id = keylet.key}));
2240 using namespace test::jtx;
2244 Env env{*
this, supported_amendments() | featureSingleAssetVault};
2245 Account issuer{
"issuer"};
2246 Account owner{
"owner"};
2247 Account depositor{
"depositor"};
2248 Account charlie{
"charlie"};
2249 Account pdOwner{
"pdOwner"};
2250 Account credIssuer1{
"credIssuer1"};
2251 Account credIssuer2{
"credIssuer2"};
2269 env.trust(asset(1000), owner);
2270 env(pay(issuer, owner, asset(500)));
2271 env.trust(asset(1000), depositor);
2272 env(pay(issuer, depositor, asset(500)));
2273 env.trust(asset(1000), charlie);
2274 env(pay(issuer, charlie, asset(5)));
2277 auto [tx, keylet] = vault.create(
2281 BEAST_EXPECT(env.le(keylet));
2284 testcase(
"private vault owner can deposit");
2285 auto tx = vault.deposit(
2286 {.depositor = owner, .id = keylet.
key, .amount = asset(50)});
2291 testcase(
"private vault depositor not authorized yet");
2292 auto tx = vault.deposit(
2293 {.depositor = depositor,
2295 .amount = asset(50)});
2300 testcase(
"private vault cannot set non-existing domain");
2301 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2307 testcase(
"private vault set domainId");
2310 pdomain::Credentials
const credentials1{
2311 {.issuer = credIssuer1, .credType = credType}};
2313 env(pdomain::setTx(pdOwner, credentials1));
2314 auto const domainId1 = [&]() {
2316 return pdomain::getNewDomain(env.meta());
2319 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2330 pdomain::Credentials
const credentials{
2331 {.issuer = credIssuer1, .credType = credType},
2332 {.issuer = credIssuer2, .credType = credType}};
2334 env(pdomain::setTx(pdOwner, credentials));
2335 auto const domainId = [&]() {
2337 return pdomain::getNewDomain(env.meta());
2340 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2348 testcase(
"private vault depositor still not authorized");
2349 auto tx = vault.deposit(
2350 {.depositor = depositor,
2352 .amount = asset(50)});
2357 auto const credKeylet =
2358 credentials::keylet(depositor, credIssuer1, credType);
2360 testcase(
"private vault depositor now authorized");
2361 env(credentials::create(depositor, credIssuer1, credType));
2362 env(credentials::accept(depositor, credIssuer1, credType));
2363 env(credentials::create(charlie, credIssuer1, credType));
2366 auto credSle = env.le(credKeylet);
2367 BEAST_EXPECT(credSle !=
nullptr);
2369 auto tx = vault.deposit(
2370 {.depositor = depositor,
2372 .amount = asset(50)});
2377 {.depositor = charlie, .id = keylet.
key, .amount = asset(50)});
2383 testcase(
"private vault depositor lost authorization");
2384 env(credentials::deleteCred(
2385 credIssuer1, depositor, credIssuer1, credType));
2386 env(credentials::deleteCred(
2387 credIssuer1, charlie, credIssuer1, credType));
2389 auto credSle = env.le(credKeylet);
2390 BEAST_EXPECT(credSle ==
nullptr);
2392 auto tx = vault.deposit(
2393 {.depositor = depositor,
2395 .amount = asset(50)});
2400 auto const shares = [&env, keylet = keylet,
this]() ->
Asset {
2401 auto const vault = env.le(keylet);
2402 BEAST_EXPECT(vault !=
nullptr);
2403 return MPTIssue(vault->at(sfShareMPTID));
2407 testcase(
"private vault expired authorization");
2408 uint32_t
const closeTime = env.current()
2410 .parentCloseTime.time_since_epoch()
2414 credentials::create(depositor, credIssuer2, credType);
2415 tx0[sfExpiration] = closeTime + 20;
2417 tx0 = credentials::create(charlie, credIssuer2, credType);
2418 tx0[sfExpiration] = closeTime + 20;
2422 env(credentials::accept(depositor, credIssuer2, credType));
2423 env(credentials::accept(charlie, credIssuer2, credType));
2428 auto tx1 = vault.deposit(
2429 {.depositor = depositor,
2431 .amount = asset(50)});
2437 BEAST_EXPECT(env.le(tokenKeylet) !=
nullptr);
2446 auto const credsKeylet =
2447 credentials::keylet(depositor, credIssuer2, credType);
2448 BEAST_EXPECT(env.le(credsKeylet) !=
nullptr);
2450 auto tx2 = vault.deposit(
2451 {.depositor = depositor,
2453 .amount = asset(1)});
2457 BEAST_EXPECT(env.le(credsKeylet) ==
nullptr);
2461 auto const credsKeylet =
2462 credentials::keylet(charlie, credIssuer2, credType);
2463 BEAST_EXPECT(env.le(credsKeylet) !=
nullptr);
2466 BEAST_EXPECT(env.le(tokenKeylet) ==
nullptr);
2468 auto tx3 = vault.deposit(
2469 {.depositor = charlie,
2471 .amount = asset(2)});
2475 BEAST_EXPECT(env.le(credsKeylet) ==
nullptr);
2476 BEAST_EXPECT(env.le(tokenKeylet) ==
nullptr);
2481 testcase(
"private vault reset domainId");
2482 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2483 tx[sfDomainID] =
"0";
2488 {.depositor = depositor,
2490 .amount = asset(50)});
2494 tx = vault.withdraw(
2495 {.depositor = depositor,
2497 .amount = asset(50)});
2500 tx = vault.clawback(
2503 .holder = depositor,
2504 .amount = asset(0)});
2507 tx = vault.clawback(
2511 .amount = asset(0)});
2525 using namespace test::jtx;
2529 Env env{*
this, supported_amendments() | featureSingleAssetVault};
2530 Account owner{
"owner"};
2531 Account depositor{
"depositor"};
2532 Account alice{
"charlie"};
2535 env.fund(XRP(100000), owner, depositor, alice);
2539 auto [tx, keylet] = vault.create(
2544 auto const [vaultAccount, issuanceId] =
2546 auto const vault = env.le(keylet);
2547 BEAST_EXPECT(vault !=
nullptr);
2548 return {vault->at(sfAccount), vault->at(sfShareMPTID)};
2555 testcase(
"private XRP vault owner can deposit");
2556 auto tx = vault.deposit(
2557 {.depositor = owner, .id = keylet.
key, .amount = asset(50)});
2562 testcase(
"private XRP vault cannot pay shares to depositor yet");
2563 env(pay(owner, depositor, shares(1)), ter{
tecNO_AUTH});
2567 testcase(
"private XRP vault depositor not authorized yet");
2568 auto tx = vault.deposit(
2569 {.depositor = depositor,
2571 .amount = asset(50)});
2576 testcase(
"private XRP vault set DomainID");
2577 pdomain::Credentials
const credentials{
2578 {.issuer = owner, .credType = credType}};
2580 env(pdomain::setTx(owner, credentials));
2581 auto const domainId = [&]() {
2583 return pdomain::getNewDomain(env.meta());
2586 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2592 auto const credKeylet = credentials::keylet(depositor, owner, credType);
2594 testcase(
"private XRP vault depositor now authorized");
2595 env(credentials::create(depositor, owner, credType));
2596 env(credentials::accept(depositor, owner, credType));
2599 BEAST_EXPECT(env.le(credKeylet));
2600 auto tx = vault.deposit(
2601 {.depositor = depositor,
2603 .amount = asset(50)});
2609 testcase(
"private XRP vault can pay shares to depositor");
2610 env(pay(owner, depositor, shares(1)));
2614 testcase(
"private XRP vault cannot pay shares to 3rd party");
2616 jv[sfAccount] = alice.human();
2617 jv[sfTransactionType] = jss::MPTokenAuthorize;
2618 jv[sfMPTokenIssuanceID] =
to_string(issuanceId);
2622 env(pay(owner, alice, shares(1)), ter{
tecNO_AUTH});
2629 using namespace test::jtx;
2631 testcase(
"failed pseudo-account allocation");
2632 Env env{*
this, supported_amendments() | featureSingleAssetVault};
2633 Account
const owner{
"owner"};
2635 env.fund(XRP(1000), owner);
2637 auto const keylet =
keylet::vault(owner.id(), env.seq(owner));
2638 for (
int i = 0; i < 256; ++i)
2643 env(pay(env.master.id(), accountId, XRP(1000)),
2649 auto [tx, keylet1] =
2650 vault.create({.owner = owner, .asset =
xrpIssue()});
2651 BEAST_EXPECT(keylet.
key == keylet1.key);
2658 using namespace test::jtx;
2661 Env env{*
this, supported_amendments() | featureSingleAssetVault};
2662 Account
const owner{
"owner"};
2663 Account
const issuer{
"issuer"};
2665 env.fund(XRP(1000), issuer, owner);
2669 env.trust(asset(1000), owner);
2670 env(pay(issuer, owner, asset(200)));
2673 auto const sequence = env.seq(owner);
2674 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2680 auto tx1 = vault.deposit(
2681 {.depositor = owner, .id = keylet.
key, .amount = asset(50)});
2684 auto tx2 = vault.set({.owner = owner, .id = keylet.
key});
2685 tx2[sfAssetsMaximum] = asset(1000).number();
2690 auto const sleVault = [&env, keylet = keylet,
this]() {
2691 auto const vault = env.le(keylet);
2692 BEAST_EXPECT(vault !=
nullptr);
2696 auto const check = [&, keylet = keylet, sle = sleVault,
this](
2699 BEAST_EXPECT(vault.isObject());
2701 constexpr auto checkString =
2703 return node.isMember(field.fieldName) &&
2704 node[field.fieldName].isString() &&
2705 node[field.fieldName] == v;
2707 constexpr auto checkObject =
2709 return node.isMember(field.fieldName) &&
2710 node[field.fieldName].isObject() &&
2711 node[field.fieldName] == v;
2713 constexpr auto checkInt =
2714 [](
auto& node,
SField const& field,
int v) ->
bool {
2715 return node.isMember(field.fieldName) &&
2716 ((node[field.fieldName].isInt() &&
2717 node[field.fieldName] ==
Json::Int(v)) ||
2718 (node[field.fieldName].isUInt() &&
2722 BEAST_EXPECT(vault[
"LedgerEntryType"].asString() ==
"Vault");
2723 BEAST_EXPECT(vault[jss::index].asString() ==
strHex(keylet.
key));
2724 BEAST_EXPECT(checkInt(vault, sfFlags, 0));
2728 checkString(vault, sfAccount,
toBase58(sle->at(sfAccount))));
2730 checkObject(vault, sfAsset,
to_json(sle->at(sfAsset))));
2731 BEAST_EXPECT(checkString(vault, sfAssetsAvailable,
"50"));
2732 BEAST_EXPECT(checkString(vault, sfAssetsMaximum,
"1000"));
2733 BEAST_EXPECT(checkString(vault, sfAssetsTotal,
"50"));
2734 BEAST_EXPECT(checkString(vault, sfLossUnrealized,
"0"));
2736 auto const strShareID =
strHex(sle->at(sfShareMPTID));
2737 BEAST_EXPECT(checkString(vault, sfShareMPTID, strShareID));
2738 BEAST_EXPECT(checkString(vault, sfOwner,
toBase58(owner.id())));
2739 BEAST_EXPECT(checkInt(vault, sfSequence, sequence));
2740 BEAST_EXPECT(checkInt(
2743 if (issuance.isObject())
2746 issuance[
"LedgerEntryType"].asString() ==
2749 issuance[jss::mpt_issuance_id].asString() == strShareID);
2750 BEAST_EXPECT(checkInt(issuance, sfSequence, 1));
2751 BEAST_EXPECT(checkInt(
2755 BEAST_EXPECT(checkString(issuance, sfOutstandingAmount,
"50"));
2760 testcase(
"RPC ledger_entry selected by key");
2762 jvParams[jss::ledger_index] = jss::validated;
2763 jvParams[jss::vault] =
strHex(keylet.
key);
2764 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2766 BEAST_EXPECT(!jvVault[jss::result].isMember(jss::error));
2767 BEAST_EXPECT(jvVault[jss::result].isMember(jss::node));
2768 check(jvVault[jss::result][jss::node]);
2772 testcase(
"RPC ledger_entry selected by owner and seq");
2774 jvParams[jss::ledger_index] = jss::validated;
2775 jvParams[jss::vault][jss::owner] = owner.human();
2776 jvParams[jss::vault][jss::seq] = sequence;
2777 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2779 BEAST_EXPECT(!jvVault[jss::result].isMember(jss::error));
2780 BEAST_EXPECT(jvVault[jss::result].isMember(jss::node));
2781 check(jvVault[jss::result][jss::node]);
2785 testcase(
"RPC ledger_entry cannot find vault by key");
2787 jvParams[jss::ledger_index] = jss::validated;
2789 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2791 jvVault[jss::result][jss::error].asString() ==
"entryNotFound");
2795 testcase(
"RPC ledger_entry cannot find vault by owner and seq");
2797 jvParams[jss::ledger_index] = jss::validated;
2798 jvParams[jss::vault][jss::owner] = issuer.human();
2799 jvParams[jss::vault][jss::seq] = 1'000'000;
2800 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2802 jvVault[jss::result][jss::error].asString() ==
"entryNotFound");
2806 testcase(
"RPC ledger_entry malformed key");
2808 jvParams[jss::ledger_index] = jss::validated;
2809 jvParams[jss::vault] = 42;
2810 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2812 jvVault[jss::result][jss::error].asString() ==
2813 "malformedRequest");
2817 testcase(
"RPC ledger_entry malformed owner");
2819 jvParams[jss::ledger_index] = jss::validated;
2820 jvParams[jss::vault][jss::owner] = 42;
2821 jvParams[jss::vault][jss::seq] = sequence;
2822 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2824 jvVault[jss::result][jss::error].asString() ==
2829 testcase(
"RPC ledger_entry malformed seq");
2831 jvParams[jss::ledger_index] = jss::validated;
2832 jvParams[jss::vault][jss::owner] = issuer.human();
2833 jvParams[jss::vault][jss::seq] =
"foo";
2834 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2836 jvVault[jss::result][jss::error].asString() ==
2837 "malformedRequest");
2841 testcase(
"RPC ledger_entry zero seq");
2843 jvParams[jss::ledger_index] = jss::validated;
2844 jvParams[jss::vault][jss::owner] = issuer.human();
2845 jvParams[jss::vault][jss::seq] = 0;
2846 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2848 jvVault[jss::result][jss::error].asString() ==
2849 "malformedRequest");
2853 testcase(
"RPC ledger_entry negative seq");
2855 jvParams[jss::ledger_index] = jss::validated;
2856 jvParams[jss::vault][jss::owner] = issuer.human();
2857 jvParams[jss::vault][jss::seq] = -1;
2858 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2860 jvVault[jss::result][jss::error].asString() ==
2861 "malformedRequest");
2865 testcase(
"RPC ledger_entry oversized seq");
2867 jvParams[jss::ledger_index] = jss::validated;
2868 jvParams[jss::vault][jss::owner] = issuer.human();
2869 jvParams[jss::vault][jss::seq] = 1e20;
2870 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2872 jvVault[jss::result][jss::error].asString() ==
2873 "malformedRequest");
2877 testcase(
"RPC ledger_entry bool seq");
2879 jvParams[jss::ledger_index] = jss::validated;
2880 jvParams[jss::vault][jss::owner] = issuer.human();
2881 jvParams[jss::vault][jss::seq] =
true;
2882 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2884 jvVault[jss::result][jss::error].asString() ==
2885 "malformedRequest");
2892 jvParams[jss::account] = owner.human();
2893 jvParams[jss::type] = jss::vault;
2895 "json",
"account_objects",
to_string(jvParams))[jss::result];
2897 BEAST_EXPECT(jv[jss::account_objects].size() == 1);
2898 check(jv[jss::account_objects][0u]);
2905 jvParams[jss::ledger_index] = jss::validated;
2906 jvParams[jss::binary] =
false;
2907 jvParams[jss::type] = jss::vault;
2909 env.rpc(
"json",
"ledger_data",
to_string(jvParams));
2910 BEAST_EXPECT(jv[jss::result][jss::state].size() == 1);
2911 check(jv[jss::result][jss::state][0u]);
2915 testcase(
"RPC vault_info command line");
2917 env.rpc(
"vault_info",
strHex(keylet.
key),
"validated");
2919 BEAST_EXPECT(!jv[jss::result].isMember(jss::error));
2920 BEAST_EXPECT(jv[jss::result].isMember(jss::vault));
2922 jv[jss::result][jss::vault],
2923 jv[jss::result][jss::vault][jss::shares]);
2929 jvParams[jss::ledger_index] = jss::validated;
2930 jvParams[jss::vault_id] =
strHex(keylet.
key);
2931 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2933 BEAST_EXPECT(!jv[jss::result].isMember(jss::error));
2934 BEAST_EXPECT(jv[jss::result].isMember(jss::vault));
2936 jv[jss::result][jss::vault],
2937 jv[jss::result][jss::vault][jss::shares]);
2941 testcase(
"RPC vault_info invalid vault_id");
2943 jvParams[jss::ledger_index] = jss::validated;
2944 jvParams[jss::vault_id] =
"foobar";
2945 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2947 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2951 testcase(
"RPC vault_info json invalid index");
2953 jvParams[jss::ledger_index] = jss::validated;
2954 jvParams[jss::vault_id] = 0;
2955 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2957 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2961 testcase(
"RPC vault_info json by owner and sequence");
2963 jvParams[jss::ledger_index] = jss::validated;
2964 jvParams[jss::owner] = owner.human();
2965 jvParams[jss::seq] = sequence;
2966 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2968 BEAST_EXPECT(!jv[jss::result].isMember(jss::error));
2969 BEAST_EXPECT(jv[jss::result].isMember(jss::vault));
2971 jv[jss::result][jss::vault],
2972 jv[jss::result][jss::vault][jss::shares]);
2976 testcase(
"RPC vault_info json malformed sequence");
2978 jvParams[jss::ledger_index] = jss::validated;
2979 jvParams[jss::owner] = owner.human();
2980 jvParams[jss::seq] =
"foobar";
2981 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2983 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2987 testcase(
"RPC vault_info json invalid sequence");
2989 jvParams[jss::ledger_index] = jss::validated;
2990 jvParams[jss::owner] = owner.human();
2991 jvParams[jss::seq] = 0;
2992 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2994 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2998 testcase(
"RPC vault_info json negative sequence");
3000 jvParams[jss::ledger_index] = jss::validated;
3001 jvParams[jss::owner] = owner.human();
3002 jvParams[jss::seq] = -1;
3003 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3005 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3009 testcase(
"RPC vault_info json oversized sequence");
3011 jvParams[jss::ledger_index] = jss::validated;
3012 jvParams[jss::owner] = owner.human();
3013 jvParams[jss::seq] = 1e20;
3014 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3016 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3020 testcase(
"RPC vault_info json bool sequence");
3022 jvParams[jss::ledger_index] = jss::validated;
3023 jvParams[jss::owner] = owner.human();
3024 jvParams[jss::seq] =
true;
3025 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3027 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3031 testcase(
"RPC vault_info json malformed owner");
3033 jvParams[jss::ledger_index] = jss::validated;
3034 jvParams[jss::owner] =
"foobar";
3035 jvParams[jss::seq] = sequence;
3036 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3038 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3042 testcase(
"RPC vault_info json invalid combination only owner");
3044 jvParams[jss::ledger_index] = jss::validated;
3045 jvParams[jss::owner] = owner.human();
3046 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3048 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3052 testcase(
"RPC vault_info json invalid combination only seq");
3054 jvParams[jss::ledger_index] = jss::validated;
3055 jvParams[jss::seq] = sequence;
3056 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3058 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3062 testcase(
"RPC vault_info json invalid combination seq vault_id");
3064 jvParams[jss::ledger_index] = jss::validated;
3065 jvParams[jss::vault_id] =
strHex(keylet.
key);
3066 jvParams[jss::seq] = sequence;
3067 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3069 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3073 testcase(
"RPC vault_info json invalid combination owner vault_id");
3075 jvParams[jss::ledger_index] = jss::validated;
3076 jvParams[jss::vault_id] =
strHex(keylet.
key);
3077 jvParams[jss::owner] = owner.human();
3078 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3080 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3085 "RPC vault_info json invalid combination owner seq "
3088 jvParams[jss::ledger_index] = jss::validated;
3089 jvParams[jss::vault_id] =
strHex(keylet.
key);
3090 jvParams[jss::seq] = sequence;
3091 jvParams[jss::owner] = owner.human();
3092 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3094 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3098 testcase(
"RPC vault_info json no input");
3100 jvParams[jss::ledger_index] = jss::validated;
3101 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3103 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3107 testcase(
"RPC vault_info command line invalid index");
3108 Json::Value jv = env.rpc(
"vault_info",
"foobar",
"validated");
3109 BEAST_EXPECT(jv[jss::error].asString() ==
"invalidParams");
3113 testcase(
"RPC vault_info command line invalid index");
3114 Json::Value jv = env.rpc(
"vault_info",
"0",
"validated");
3116 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3120 testcase(
"RPC vault_info command line invalid index");
3124 jv[jss::result][jss::error].asString() ==
"entryNotFound");
3128 testcase(
"RPC vault_info command line invalid ledger");
3131 jv[jss::result][jss::error].asString() ==
"lgrNotFound");
3154BEAST_DEFINE_TESTSUITE_PRIO(Vault, tx,
ripple, 1);
testcase_t testcase
Memberspace for declaring test cases.
constexpr TIss const & get() const
A currency issued by an account.
constexpr MPTID const & getMptID() const
void setIssuer(AccountID const &uIssuer)
Issue const & issue() const
void testFailedPseudoAccount()
ripple::test::jtx::PrettyAsset PrettyAsset
void testNonTransferableShares()
void testWithDomainCheck()
static auto constexpr negativeAmount
void run() override
Runs the suite.
void testWithDomainCheckXRP()
ripple::test::jtx::PrettyAmount PrettyAmount
Integers of any length that is a multiple of 32-bits.
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Keylet line(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet const & skip() noexcept
The index of the "short" skip list.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
constexpr std::uint32_t asfGlobalFreeze
constexpr std::uint32_t asfDepositAuth
constexpr std::uint32_t const tfMPTCanTransfer
constexpr std::uint32_t asfRequireDest
base_uint< 192 > MPTID
MPTID is a 192-bit value representing MPT Issuance ID, which is a concatenation of a 32-bit sequence ...
constexpr std::uint32_t const tfVaultPrivate
Json::Value to_json(Asset const &asset)
std::string strHex(FwdIt begin, FwdIt end)
constexpr std::uint32_t const tfMPTUnauthorize
constexpr std::uint32_t tfSetfAuth
constexpr std::uint32_t asfDefaultRipple
constexpr std::uint32_t tfClearFreeze
@ tecINSUFFICIENT_RESERVE
constexpr std::uint32_t const tfMPTLock
constexpr std::uint32_t const tfVaultShareNonTransferable
AccountID pseudoAccountAddress(ReadView const &view, uint256 const &pseudoOwnerKey)
constexpr std::uint32_t tfClearDeepFreeze
std::string to_string(base_uint< Bits, Tag > const &a)
std::uint8_t constexpr vaultStrategyFirstComeFirstServe
Vault withdrawal policies.
constexpr std::uint32_t asfAllowTrustLineClawback
constexpr std::uint32_t asfRequireAuth
MPTID makeMptID(std::uint32_t sequence, AccountID const &account)
constexpr std::uint32_t const tfMPTRequireAuth
constexpr std::uint32_t tfSetFreeze
constexpr std::uint32_t const tfMPTCanLock
constexpr std::uint32_t const tfMPTCanClawback
A pair of SHAMap key and LedgerEntryType.
Represents an XRP or IOU quantity This customizes the string conversion and supports XRP conversions ...
Asset const & raw() const