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, testable_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 testable_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 = testable_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 = (testable_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, testable_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");
1095 Env env{*
this, testable_amendments() | featureSingleAssetVault};
1096 Account issuer{
"issuer"};
1097 Account owner{
"owner"};
1098 env.fund(XRP(1000), issuer, owner);
1104 Asset asset = issuer[
"IOU"];
1106 vault.create({.owner = owner, .asset = asset});
1113 testcase(
"IOU fail create no ripling");
1114 Env env{*
this, testable_amendments() | featureSingleAssetVault};
1115 Account issuer{
"issuer"};
1116 Account owner{
"owner"};
1117 env.fund(XRP(1000), issuer, owner);
1123 Asset asset = issuer[
"IOU"];
1125 vault.create({.owner = owner, .asset = asset});
1132 Env env{*
this, testable_amendments() | featureSingleAssetVault};
1133 Account issuer{
"issuer"};
1134 Account owner{
"owner"};
1135 env.fund(XRP(1000), owner);
1139 Asset asset = issuer[
"IOU"];
1142 vault.create({.owner = owner, .asset = asset});
1150 testcase(
"IOU fail create vault for AMM LPToken");
1151 Env env{*
this, testable_amendments() | featureSingleAssetVault};
1152 Account
const gw(
"gateway");
1153 Account
const alice(
"alice");
1154 Account
const carol(
"carol");
1155 IOU
const USD = gw[
"USD"];
1157 auto const [asset1, asset2] =
1162 auto const defXRP = XRP(30000);
1165 return a + XRP(1000);
1172 auto const toFund1 = tofund(asset1);
1173 auto const toFund2 = tofund(asset2);
1174 BEAST_EXPECT(asset1 <= toFund1 && asset2 <= toFund2);
1176 if (!asset1.native() && !asset2.native())
1177 fund(env, gw, {alice, carol}, {toFund1, toFund2}, Fund::All);
1178 else if (asset1.native())
1179 fund(env, gw, {alice, carol}, toFund1, {toFund2}, Fund::All);
1180 else if (asset2.native())
1181 fund(env, gw, {alice, carol}, toFund2, {toFund1}, Fund::All);
1184 env, alice, asset1, asset2, CreateArg{.log =
false, .tfee = 0});
1186 Account
const owner{
"owner"};
1187 env.fund(XRP(1000000), owner);
1191 vault.create({.owner = owner, .asset = ammAlice.lptIssue()});
1200 using namespace test::jtx;
1202 Env env{*
this, testable_amendments() | featureSingleAssetVault};
1203 Account issuer{
"issuer"};
1204 Account owner{
"owner"};
1205 Account depositor{
"depositor"};
1206 env.fund(XRP(1000), issuer, owner, depositor);
1210 MPTTester mptt{env, issuer, mptInitNoFund};
1214 Asset asset = mptt.issuanceID();
1215 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1222 using namespace test::jtx;
1224 Env env{*
this, testable_amendments() | featureSingleAssetVault};
1225 Account issuer{
"issuer"};
1226 Account owner{
"owner"};
1227 Account depositor{
"depositor"};
1228 env.fund(XRP(1000), issuer, owner, depositor);
1233 env.trust(asset(1000), owner);
1234 env(pay(issuer, owner, asset(100)));
1235 env.trust(asset(1000), depositor);
1236 env(pay(issuer, depositor, asset(100)));
1239 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1245 testcase(
"nontransferable deposits");
1246 auto tx1 = vault.deposit(
1247 {.depositor = depositor,
1249 .amount = asset(40)});
1252 auto tx2 = vault.deposit(
1253 {.depositor = owner, .id = keylet.
key, .amount = asset(60)});
1258 auto const vaultAccount =
1260 auto jvVault = env.rpc(
"vault_info",
strHex(key));
1263 jvVault[jss::result][jss::vault][sfAssetsTotal] ==
"100");
1265 jvVault[jss::result][jss::vault][jss::shares]
1266 [sfOutstandingAmount] ==
"100");
1269 return parseBase58<AccountID>(
1270 jvVault[jss::result][jss::vault][jss::Account]
1275 auto const MptID =
makeMptID(1, vaultAccount);
1276 Asset shares = MptID;
1279 testcase(
"nontransferable shares cannot be moved");
1280 env(pay(owner, depositor, shares(10)), ter{
tecNO_AUTH});
1281 env(pay(depositor, owner, shares(10)), ter{
tecNO_AUTH});
1285 testcase(
"nontransferable shares can be used to withdraw");
1286 auto tx1 = vault.withdraw(
1287 {.depositor = depositor,
1289 .amount = asset(20)});
1292 auto tx2 = vault.withdraw(
1293 {.depositor = owner, .id = keylet.
key, .amount = asset(30)});
1299 testcase(
"nontransferable shares balance check");
1300 auto jvVault = env.rpc(
"vault_info",
strHex(keylet.
key));
1302 jvVault[jss::result][jss::vault][sfAssetsTotal] ==
"50");
1304 jvVault[jss::result][jss::vault][jss::shares]
1305 [sfOutstandingAmount] ==
"50");
1309 testcase(
"nontransferable shares withdraw rest");
1310 auto tx1 = vault.withdraw(
1311 {.depositor = depositor,
1313 .amount = asset(20)});
1316 auto tx2 = vault.withdraw(
1317 {.depositor = owner, .id = keylet.
key, .amount = asset(30)});
1323 testcase(
"nontransferable shares delete empty vault");
1324 auto tx = vault.del({.owner = owner, .id = keylet.
key});
1326 BEAST_EXPECT(!env.le(keylet));
1333 using namespace test::jtx;
1337 bool enableClawback =
true;
1340 auto testCase = [
this](
1343 Account
const& issuer,
1344 Account
const& owner,
1345 Account
const& depositor,
1348 MPTTester& mptt)> test,
1349 CaseArgs args = {}) {
1350 Env env{*
this, testable_amendments() | featureSingleAssetVault};
1351 Account issuer{
"issuer"};
1352 Account owner{
"owner"};
1353 Account depositor{
"depositor"};
1354 env.fund(XRP(1000), issuer, owner, depositor);
1358 MPTTester mptt{env, issuer, mptInitNoFund};
1365 mptt.authorize({.account = owner});
1366 mptt.authorize({.account = issuer, .holder = owner});
1367 mptt.authorize({.account = depositor});
1368 mptt.authorize({.account = issuer, .holder = depositor});
1369 env(pay(issuer, depositor, asset(1000)));
1372 test(env, issuer, owner, depositor, asset, vault, mptt);
1377 Account
const& issuer,
1378 Account
const& owner,
1379 Account
const& depositor,
1383 testcase(
"MPT nothing to clawback from");
1384 auto tx = vault.clawback(
1387 .holder = depositor,
1388 .amount = asset(10)});
1394 Account
const& issuer,
1395 Account
const& owner,
1396 Account
const& depositor,
1400 testcase(
"MPT global lock blocks create");
1401 mptt.set({.account = issuer, .flags =
tfMPTLock});
1402 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1408 Account
const& issuer,
1409 Account
const& owner,
1410 Account
const& depositor,
1414 testcase(
"MPT global lock blocks deposit");
1415 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1419 mptt.set({.account = issuer, .flags =
tfMPTLock});
1423 {.depositor = depositor,
1425 .amount = asset(100)});
1430 tx = vault.del({.owner = owner, .id = keylet.
key});
1436 Account
const& issuer,
1437 Account
const& owner,
1438 Account
const& depositor,
1442 testcase(
"MPT global lock blocks withdrawal");
1443 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1447 {.depositor = depositor,
1449 .amount = asset(100)});
1455 auto v = env.le(keylet);
1457 MPTID share = (*v)[sfShareMPTID];
1459 BEAST_EXPECT(issuance);
1460 Number outstandingShares = issuance->at(sfOutstandingAmount);
1461 BEAST_EXPECT(outstandingShares == 100);
1463 mptt.set({.account = issuer, .flags =
tfMPTLock});
1466 tx = vault.withdraw(
1467 {.depositor = depositor,
1469 .amount = asset(100)});
1472 tx[sfDestination] = issuer.human();
1476 tx = vault.clawback(
1479 .holder = depositor,
1480 .amount = asset(0)});
1485 tx = vault.del({.owner = owner, .id = keylet.
key});
1491 Account
const& issuer,
1492 Account
const& owner,
1493 Account
const& depositor,
1497 testcase(
"MPT only issuer can clawback");
1499 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1504 {.depositor = depositor,
1506 .amount = asset(100)});
1511 auto tx = vault.clawback(
1512 {.issuer = owner, .id = keylet.
key, .holder = depositor});
1519 Account
const& issuer,
1520 Account
const& owner,
1521 Account
const& depositor,
1527 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1532 {.depositor = depositor,
1534 .amount = asset(1000)});
1539 auto tx = vault.clawback(
1542 .holder = depositor,
1543 .amount = asset(0)});
1547 mptt.destroy({.issuer = issuer, .id = mptt.issuanceID()});
1552 vault.create({.owner = depositor, .asset = asset});
1557 auto tx = vault.deposit(
1558 {.depositor = depositor,
1560 .amount = asset(10)});
1565 auto tx = vault.withdraw(
1566 {.depositor = depositor,
1568 .amount = asset(10)});
1573 auto tx = vault.clawback(
1576 .holder = depositor,
1577 .amount = asset(0)});
1581 env(vault.del({.owner = owner, .id = keylet.key}));
1587 Account
const& issuer,
1588 Account
const& owner,
1589 Account
const& depositor,
1596 vault.create({.owner = owner, .asset = asset});
1601 {.depositor = depositor,
1603 .amount = asset(1000)});
1608 auto tx = vault.clawback(
1611 .holder = depositor,
1612 .amount = asset(0)});
1616 {.enableClawback =
false});
1620 Account
const& issuer,
1621 Account
const& owner,
1622 Account
const& depositor,
1627 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1631 {.depositor = depositor,
1633 .amount = asset(1000)});
1639 .holder = depositor,
1644 auto tx = vault.withdraw(
1645 {.depositor = depositor,
1647 .amount = asset(100)});
1651 tx[sfDestination] = issuer.human();
1653 tx[sfDestination] = owner.human();
1660 auto tx = vault.deposit(
1661 {.depositor = depositor,
1663 .amount = asset(100)});
1668 tx = vault.clawback(
1671 .holder = depositor,
1672 .amount = asset(800)});
1675 env(vault.del({.owner = owner, .id = keylet.key}));
1680 Account
const& issuer,
1681 Account
const& owner,
1682 Account
const& depositor,
1686 testcase(
"MPT lock of vault pseudo-account");
1687 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1691 auto const vaultAccount =
1692 [&env, keylet = keylet,
this]() ->
AccountID {
1693 auto const vault = env.le(keylet);
1694 BEAST_EXPECT(vault !=
nullptr);
1695 return vault->at(sfAccount);
1699 {.depositor = depositor,
1701 .amount = asset(100)});
1707 jv[jss::Account] = issuer.human();
1708 jv[sfMPTokenIssuanceID] =
1710 jv[jss::Holder] =
toBase58(vaultAccount);
1711 jv[jss::TransactionType] = jss::MPTokenIssuanceSet;
1719 {.depositor = depositor,
1721 .amount = asset(100)});
1724 tx = vault.withdraw(
1725 {.depositor = depositor,
1727 .amount = asset(100)});
1731 tx = vault.clawback(
1734 .holder = depositor,
1735 .amount = asset(100)});
1739 tx = vault.del({.owner = owner, .id = keylet.
key});
1746 Env env{*
this, testable_amendments() | featureSingleAssetVault};
1747 Account owner{
"owner"};
1748 Account issuer{
"issuer"};
1749 env.fund(XRP(1000000), owner, issuer);
1753 MPTTester mptt{env, issuer, mptInitNoFund};
1757 mptt.authorize({.account = owner});
1758 mptt.authorize({.account = issuer, .holder = owner});
1760 env(pay(issuer, owner, asset(100)));
1761 auto [tx1, k1] = vault.create({.owner = owner, .asset = asset});
1765 auto const shares = [&env, keylet = k1,
this]() ->
Asset {
1766 auto const vault = env.le(keylet);
1767 BEAST_EXPECT(vault !=
nullptr);
1768 return MPTIssue(vault->at(sfShareMPTID));
1771 auto [tx2, k2] = vault.create({.owner = owner, .asset = shares});
1780 using namespace test::jtx;
1786 Account
const& owner,
1787 Account
const& issuer,
1788 Account
const& charlie,
1795 Env env{*
this, testable_amendments() | featureSingleAssetVault};
1796 Account
const owner{
"owner"};
1797 Account
const issuer{
"issuer"};
1798 Account
const charlie{
"charlie"};
1800 env.fund(XRP(1000), issuer, owner, charlie);
1805 env.trust(asset(1000), owner);
1806 env(pay(issuer, owner, asset(200)));
1807 env(rate(issuer, 1.25));
1810 auto const [tx, keylet] =
1811 vault.create({.owner = owner, .asset = asset});
1815 auto const vaultAccount =
1817 return env.le(keylet)->at(sfAccount);
1820 return env.le(keylet)->at(sfShareMPTID);
1822 auto const vaultBalance =
1823 [&env, &vaultAccount, issue = asset.
raw().
get<
Issue>()](
1825 auto const account = vaultAccount(keylet);
1830 env.lookup(issue.account).name()};
1831 auto amount = sle->getFieldAmount(sfBalance);
1833 if (account > issue.account)
1835 return {amount, env.lookup(issue.account).name()};
1852 Account
const& owner,
1853 Account
const& issuer,
1859 testcase(
"IOU cannot use different asset");
1862 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1868 auto tx = [&, account = vaultAccount(keylet)]() {
1870 jv[jss::Account] = issuer.human();
1872 auto& ja = jv[jss::LimitAmount] =
1874 ja[jss::issuer] =
toBase58(account);
1876 jv[jss::TransactionType] = jss::TrustSet;
1885 auto tx = vault.deposit(
1886 {.depositor = issuer, .id = keylet.
key, .amount = foo(20)});
1892 auto tx = vault.withdraw(
1893 {.depositor = issuer, .id = keylet.
key, .amount = foo(20)});
1898 env(vault.del({.owner = owner, .id = keylet.key}));
1904 Account
const& owner,
1905 Account
const& issuer,
1906 Account
const& charlie,
1912 testcase(
"IOU frozen trust line to vault account");
1914 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1919 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
1922 Asset const share =
Asset(issuanceId(keylet));
1925 auto trustSet = [&, account = vaultAccount(keylet)]() {
1927 jv[jss::Account] = issuer.human();
1929 auto& ja = jv[jss::LimitAmount] =
1931 ja[jss::issuer] =
toBase58(account);
1933 jv[jss::TransactionType] = jss::TrustSet;
1945 auto tx = vault.deposit(
1946 {.depositor = owner,
1948 .amount = asset(80)});
1953 auto tx = vault.withdraw(
1954 {.depositor = owner,
1956 .amount = asset(100)});
1960 tx[sfDestination] = charlie.human();
1967 auto tx = vault.clawback(
1971 .amount = asset(50)});
1982 {.depositor = owner, .id = keylet.key, .amount = share(50)}));
1984 env(vault.del({.owner = owner, .id = keylet.key}));
1990 Account
const& owner,
1991 Account
const& issuer,
1992 Account
const& charlie,
1997 auto vaultBalance) {
1998 testcase(
"IOU transfer fees not applied");
2000 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2005 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
2009 Asset const share =
Asset(issuanceId(keylet));
2012 BEAST_EXPECT(env.balance(owner, issue) == asset(100));
2013 BEAST_EXPECT(vaultBalance(keylet) == asset(100));
2016 auto tx = vault.clawback(
2020 .amount = asset(50)});
2026 BEAST_EXPECT(env.balance(owner, issue) == asset(100));
2027 BEAST_EXPECT(vaultBalance(keylet) == asset(50));
2030 {.depositor = owner, .id = keylet.key, .amount = share(20)}));
2033 BEAST_EXPECT(env.balance(owner, issue) == asset(120));
2034 BEAST_EXPECT(vaultBalance(keylet) == asset(30));
2037 auto tx = vault.withdraw(
2038 {.depositor = owner,
2040 .amount = share(30)});
2041 tx[sfDestination] = charlie.human();
2046 BEAST_EXPECT(env.balance(owner, issue) == asset(120));
2047 BEAST_EXPECT(env.balance(charlie, issue) == asset(30));
2048 BEAST_EXPECT(vaultBalance(keylet) == asset(0));
2050 env(vault.del({.owner = owner, .id = keylet.key}));
2056 Account
const& owner,
2057 Account
const& issuer,
2058 Account
const& charlie,
2063 testcase(
"IOU frozen trust line to depositor");
2065 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2070 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
2075 auto tx = vault.withdraw(
2076 {.depositor = owner,
2078 .amount = asset(10)});
2079 tx[sfDestination] = charlie.human();
2082 env(withdrawToCharlie);
2089 auto const withdraw = vault.withdraw(
2090 {.depositor = owner, .id = keylet.
key, .amount = asset(10)});
2099 auto tx = vault.deposit(
2100 {.depositor = owner,
2102 .amount = asset(10)});
2108 auto tx = vault.clawback(
2112 .amount = asset(0)});
2117 env(vault.del({.owner = owner, .id = keylet.key}));
2123 Account
const& owner,
2124 Account
const& issuer,
2125 Account
const& charlie,
2130 testcase(
"IOU frozen trust line to 3rd party");
2132 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2137 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
2142 auto tx = vault.withdraw(
2143 {.depositor = owner,
2145 .amount = asset(10)});
2146 tx[sfDestination] = charlie.human();
2149 env(withdrawToCharlie);
2152 env(trust(issuer, asset(0), charlie,
tfSetFreeze));
2156 auto const withdraw = vault.withdraw(
2157 {.depositor = owner, .id = keylet.
key, .amount = asset(10)});
2169 .amount = asset(0)}));
2172 env(vault.del({.owner = owner, .id = keylet.key}));
2178 Account
const& owner,
2179 Account
const& issuer,
2180 Account
const& charlie,
2187 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2192 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
2200 auto tx = vault.withdraw(
2201 {.depositor = owner,
2203 .amount = asset(10)});
2207 tx[sfDestination] = charlie.human();
2213 {.depositor = owner,
2215 .amount = asset(10)});
2225 .amount = asset(0)}));
2228 env(vault.del({.owner = owner, .id = keylet.key}));
2236 using namespace test::jtx;
2240 Env env{*
this, testable_amendments() | featureSingleAssetVault};
2241 Account issuer{
"issuer"};
2242 Account owner{
"owner"};
2243 Account depositor{
"depositor"};
2244 Account charlie{
"charlie"};
2245 Account pdOwner{
"pdOwner"};
2246 Account credIssuer1{
"credIssuer1"};
2247 Account credIssuer2{
"credIssuer2"};
2265 env.trust(asset(1000), owner);
2266 env(pay(issuer, owner, asset(500)));
2267 env.trust(asset(1000), depositor);
2268 env(pay(issuer, depositor, asset(500)));
2269 env.trust(asset(1000), charlie);
2270 env(pay(issuer, charlie, asset(5)));
2273 auto [tx, keylet] = vault.create(
2277 BEAST_EXPECT(env.le(keylet));
2280 testcase(
"private vault owner can deposit");
2281 auto tx = vault.deposit(
2282 {.depositor = owner, .id = keylet.
key, .amount = asset(50)});
2287 testcase(
"private vault depositor not authorized yet");
2288 auto tx = vault.deposit(
2289 {.depositor = depositor,
2291 .amount = asset(50)});
2296 testcase(
"private vault cannot set non-existing domain");
2297 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2303 testcase(
"private vault set domainId");
2306 pdomain::Credentials
const credentials1{
2307 {.issuer = credIssuer1, .credType = credType}};
2309 env(pdomain::setTx(pdOwner, credentials1));
2310 auto const domainId1 = [&]() {
2312 return pdomain::getNewDomain(env.meta());
2315 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2326 pdomain::Credentials
const credentials{
2327 {.issuer = credIssuer1, .credType = credType},
2328 {.issuer = credIssuer2, .credType = credType}};
2330 env(pdomain::setTx(pdOwner, credentials));
2331 auto const domainId = [&]() {
2333 return pdomain::getNewDomain(env.meta());
2336 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2344 testcase(
"private vault depositor still not authorized");
2345 auto tx = vault.deposit(
2346 {.depositor = depositor,
2348 .amount = asset(50)});
2353 auto const credKeylet =
2354 credentials::keylet(depositor, credIssuer1, credType);
2356 testcase(
"private vault depositor now authorized");
2357 env(credentials::create(depositor, credIssuer1, credType));
2358 env(credentials::accept(depositor, credIssuer1, credType));
2359 env(credentials::create(charlie, credIssuer1, credType));
2362 auto credSle = env.le(credKeylet);
2363 BEAST_EXPECT(credSle !=
nullptr);
2365 auto tx = vault.deposit(
2366 {.depositor = depositor,
2368 .amount = asset(50)});
2373 {.depositor = charlie, .id = keylet.
key, .amount = asset(50)});
2379 testcase(
"private vault depositor lost authorization");
2380 env(credentials::deleteCred(
2381 credIssuer1, depositor, credIssuer1, credType));
2382 env(credentials::deleteCred(
2383 credIssuer1, charlie, credIssuer1, credType));
2385 auto credSle = env.le(credKeylet);
2386 BEAST_EXPECT(credSle ==
nullptr);
2388 auto tx = vault.deposit(
2389 {.depositor = depositor,
2391 .amount = asset(50)});
2396 auto const shares = [&env, keylet = keylet,
this]() ->
Asset {
2397 auto const vault = env.le(keylet);
2398 BEAST_EXPECT(vault !=
nullptr);
2399 return MPTIssue(vault->at(sfShareMPTID));
2403 testcase(
"private vault expired authorization");
2404 uint32_t
const closeTime = env.current()
2406 .parentCloseTime.time_since_epoch()
2410 credentials::create(depositor, credIssuer2, credType);
2411 tx0[sfExpiration] = closeTime + 20;
2413 tx0 = credentials::create(charlie, credIssuer2, credType);
2414 tx0[sfExpiration] = closeTime + 20;
2418 env(credentials::accept(depositor, credIssuer2, credType));
2419 env(credentials::accept(charlie, credIssuer2, credType));
2424 auto tx1 = vault.deposit(
2425 {.depositor = depositor,
2427 .amount = asset(50)});
2433 BEAST_EXPECT(env.le(tokenKeylet) !=
nullptr);
2442 auto const credsKeylet =
2443 credentials::keylet(depositor, credIssuer2, credType);
2444 BEAST_EXPECT(env.le(credsKeylet) !=
nullptr);
2446 auto tx2 = vault.deposit(
2447 {.depositor = depositor,
2449 .amount = asset(1)});
2453 BEAST_EXPECT(env.le(credsKeylet) ==
nullptr);
2457 auto const credsKeylet =
2458 credentials::keylet(charlie, credIssuer2, credType);
2459 BEAST_EXPECT(env.le(credsKeylet) !=
nullptr);
2462 BEAST_EXPECT(env.le(tokenKeylet) ==
nullptr);
2464 auto tx3 = vault.deposit(
2465 {.depositor = charlie,
2467 .amount = asset(2)});
2471 BEAST_EXPECT(env.le(credsKeylet) ==
nullptr);
2472 BEAST_EXPECT(env.le(tokenKeylet) ==
nullptr);
2477 testcase(
"private vault reset domainId");
2478 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2479 tx[sfDomainID] =
"0";
2484 {.depositor = depositor,
2486 .amount = asset(50)});
2490 tx = vault.withdraw(
2491 {.depositor = depositor,
2493 .amount = asset(50)});
2496 tx = vault.clawback(
2499 .holder = depositor,
2500 .amount = asset(0)});
2503 tx = vault.clawback(
2507 .amount = asset(0)});
2521 using namespace test::jtx;
2525 Env env{*
this, testable_amendments() | featureSingleAssetVault};
2526 Account owner{
"owner"};
2527 Account depositor{
"depositor"};
2528 Account alice{
"charlie"};
2531 env.fund(XRP(100000), owner, depositor, alice);
2535 auto [tx, keylet] = vault.create(
2540 auto const [vaultAccount, issuanceId] =
2542 auto const vault = env.le(keylet);
2543 BEAST_EXPECT(vault !=
nullptr);
2544 return {vault->at(sfAccount), vault->at(sfShareMPTID)};
2551 testcase(
"private XRP vault owner can deposit");
2552 auto tx = vault.deposit(
2553 {.depositor = owner, .id = keylet.
key, .amount = asset(50)});
2558 testcase(
"private XRP vault cannot pay shares to depositor yet");
2559 env(pay(owner, depositor, shares(1)), ter{
tecNO_AUTH});
2563 testcase(
"private XRP vault depositor not authorized yet");
2564 auto tx = vault.deposit(
2565 {.depositor = depositor,
2567 .amount = asset(50)});
2572 testcase(
"private XRP vault set DomainID");
2573 pdomain::Credentials
const credentials{
2574 {.issuer = owner, .credType = credType}};
2576 env(pdomain::setTx(owner, credentials));
2577 auto const domainId = [&]() {
2579 return pdomain::getNewDomain(env.meta());
2582 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2588 auto const credKeylet = credentials::keylet(depositor, owner, credType);
2590 testcase(
"private XRP vault depositor now authorized");
2591 env(credentials::create(depositor, owner, credType));
2592 env(credentials::accept(depositor, owner, credType));
2595 BEAST_EXPECT(env.le(credKeylet));
2596 auto tx = vault.deposit(
2597 {.depositor = depositor,
2599 .amount = asset(50)});
2605 testcase(
"private XRP vault can pay shares to depositor");
2606 env(pay(owner, depositor, shares(1)));
2610 testcase(
"private XRP vault cannot pay shares to 3rd party");
2612 jv[sfAccount] = alice.human();
2613 jv[sfTransactionType] = jss::MPTokenAuthorize;
2614 jv[sfMPTokenIssuanceID] =
to_string(issuanceId);
2618 env(pay(owner, alice, shares(1)), ter{
tecNO_AUTH});
2625 using namespace test::jtx;
2627 testcase(
"failed pseudo-account allocation");
2628 Env env{*
this, testable_amendments() | featureSingleAssetVault};
2629 Account
const owner{
"owner"};
2631 env.fund(XRP(1000), owner);
2633 auto const keylet =
keylet::vault(owner.id(), env.seq(owner));
2634 for (
int i = 0; i < 256; ++i)
2639 env(pay(env.master.id(), accountId, XRP(1000)),
2645 auto [tx, keylet1] =
2646 vault.create({.owner = owner, .asset =
xrpIssue()});
2647 BEAST_EXPECT(keylet.
key == keylet1.key);
2654 using namespace test::jtx;
2657 Env env{*
this, testable_amendments() | featureSingleAssetVault};
2658 Account
const owner{
"owner"};
2659 Account
const issuer{
"issuer"};
2661 env.fund(XRP(1000), issuer, owner);
2665 env.trust(asset(1000), owner);
2666 env(pay(issuer, owner, asset(200)));
2669 auto const sequence = env.seq(owner);
2670 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2676 auto tx1 = vault.deposit(
2677 {.depositor = owner, .id = keylet.
key, .amount = asset(50)});
2680 auto tx2 = vault.set({.owner = owner, .id = keylet.
key});
2681 tx2[sfAssetsMaximum] = asset(1000).number();
2686 auto const sleVault = [&env, keylet = keylet,
this]() {
2687 auto const vault = env.le(keylet);
2688 BEAST_EXPECT(vault !=
nullptr);
2692 auto const check = [&, keylet = keylet, sle = sleVault,
this](
2695 BEAST_EXPECT(vault.isObject());
2697 constexpr auto checkString =
2699 return node.isMember(field.fieldName) &&
2700 node[field.fieldName].isString() &&
2701 node[field.fieldName] == v;
2703 constexpr auto checkObject =
2705 return node.isMember(field.fieldName) &&
2706 node[field.fieldName].isObject() &&
2707 node[field.fieldName] == v;
2709 constexpr auto checkInt =
2710 [](
auto& node,
SField const& field,
int v) ->
bool {
2711 return node.isMember(field.fieldName) &&
2712 ((node[field.fieldName].isInt() &&
2713 node[field.fieldName] ==
Json::Int(v)) ||
2714 (node[field.fieldName].isUInt() &&
2718 BEAST_EXPECT(vault[
"LedgerEntryType"].asString() ==
"Vault");
2719 BEAST_EXPECT(vault[jss::index].asString() ==
strHex(keylet.
key));
2720 BEAST_EXPECT(checkInt(vault, sfFlags, 0));
2724 checkString(vault, sfAccount,
toBase58(sle->at(sfAccount))));
2726 checkObject(vault, sfAsset,
to_json(sle->at(sfAsset))));
2727 BEAST_EXPECT(checkString(vault, sfAssetsAvailable,
"50"));
2728 BEAST_EXPECT(checkString(vault, sfAssetsMaximum,
"1000"));
2729 BEAST_EXPECT(checkString(vault, sfAssetsTotal,
"50"));
2730 BEAST_EXPECT(checkString(vault, sfLossUnrealized,
"0"));
2732 auto const strShareID =
strHex(sle->at(sfShareMPTID));
2733 BEAST_EXPECT(checkString(vault, sfShareMPTID, strShareID));
2734 BEAST_EXPECT(checkString(vault, sfOwner,
toBase58(owner.id())));
2735 BEAST_EXPECT(checkInt(vault, sfSequence, sequence));
2736 BEAST_EXPECT(checkInt(
2739 if (issuance.isObject())
2742 issuance[
"LedgerEntryType"].asString() ==
2745 issuance[jss::mpt_issuance_id].asString() == strShareID);
2746 BEAST_EXPECT(checkInt(issuance, sfSequence, 1));
2747 BEAST_EXPECT(checkInt(
2751 BEAST_EXPECT(checkString(issuance, sfOutstandingAmount,
"50"));
2756 testcase(
"RPC ledger_entry selected by key");
2758 jvParams[jss::ledger_index] = jss::validated;
2759 jvParams[jss::vault] =
strHex(keylet.
key);
2760 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2762 BEAST_EXPECT(!jvVault[jss::result].isMember(jss::error));
2763 BEAST_EXPECT(jvVault[jss::result].isMember(jss::node));
2764 check(jvVault[jss::result][jss::node]);
2768 testcase(
"RPC ledger_entry selected by owner and seq");
2770 jvParams[jss::ledger_index] = jss::validated;
2771 jvParams[jss::vault][jss::owner] = owner.human();
2772 jvParams[jss::vault][jss::seq] = sequence;
2773 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2775 BEAST_EXPECT(!jvVault[jss::result].isMember(jss::error));
2776 BEAST_EXPECT(jvVault[jss::result].isMember(jss::node));
2777 check(jvVault[jss::result][jss::node]);
2781 testcase(
"RPC ledger_entry cannot find vault by key");
2783 jvParams[jss::ledger_index] = jss::validated;
2785 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2787 jvVault[jss::result][jss::error].asString() ==
"entryNotFound");
2791 testcase(
"RPC ledger_entry cannot find vault by owner and seq");
2793 jvParams[jss::ledger_index] = jss::validated;
2794 jvParams[jss::vault][jss::owner] = issuer.human();
2795 jvParams[jss::vault][jss::seq] = 1'000'000;
2796 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2798 jvVault[jss::result][jss::error].asString() ==
"entryNotFound");
2802 testcase(
"RPC ledger_entry malformed key");
2804 jvParams[jss::ledger_index] = jss::validated;
2805 jvParams[jss::vault] = 42;
2806 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2808 jvVault[jss::result][jss::error].asString() ==
2809 "malformedRequest");
2813 testcase(
"RPC ledger_entry malformed owner");
2815 jvParams[jss::ledger_index] = jss::validated;
2816 jvParams[jss::vault][jss::owner] = 42;
2817 jvParams[jss::vault][jss::seq] = sequence;
2818 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2820 jvVault[jss::result][jss::error].asString() ==
2825 testcase(
"RPC ledger_entry malformed seq");
2827 jvParams[jss::ledger_index] = jss::validated;
2828 jvParams[jss::vault][jss::owner] = issuer.human();
2829 jvParams[jss::vault][jss::seq] =
"foo";
2830 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2832 jvVault[jss::result][jss::error].asString() ==
2833 "malformedRequest");
2837 testcase(
"RPC ledger_entry zero seq");
2839 jvParams[jss::ledger_index] = jss::validated;
2840 jvParams[jss::vault][jss::owner] = issuer.human();
2841 jvParams[jss::vault][jss::seq] = 0;
2842 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2844 jvVault[jss::result][jss::error].asString() ==
2845 "malformedRequest");
2849 testcase(
"RPC ledger_entry negative seq");
2851 jvParams[jss::ledger_index] = jss::validated;
2852 jvParams[jss::vault][jss::owner] = issuer.human();
2853 jvParams[jss::vault][jss::seq] = -1;
2854 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2856 jvVault[jss::result][jss::error].asString() ==
2857 "malformedRequest");
2861 testcase(
"RPC ledger_entry oversized seq");
2863 jvParams[jss::ledger_index] = jss::validated;
2864 jvParams[jss::vault][jss::owner] = issuer.human();
2865 jvParams[jss::vault][jss::seq] = 1e20;
2866 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2868 jvVault[jss::result][jss::error].asString() ==
2869 "malformedRequest");
2873 testcase(
"RPC ledger_entry bool seq");
2875 jvParams[jss::ledger_index] = jss::validated;
2876 jvParams[jss::vault][jss::owner] = issuer.human();
2877 jvParams[jss::vault][jss::seq] =
true;
2878 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2880 jvVault[jss::result][jss::error].asString() ==
2881 "malformedRequest");
2888 jvParams[jss::account] = owner.human();
2889 jvParams[jss::type] = jss::vault;
2891 "json",
"account_objects",
to_string(jvParams))[jss::result];
2893 BEAST_EXPECT(jv[jss::account_objects].size() == 1);
2894 check(jv[jss::account_objects][0u]);
2901 jvParams[jss::ledger_index] = jss::validated;
2902 jvParams[jss::binary] =
false;
2903 jvParams[jss::type] = jss::vault;
2905 env.rpc(
"json",
"ledger_data",
to_string(jvParams));
2906 BEAST_EXPECT(jv[jss::result][jss::state].size() == 1);
2907 check(jv[jss::result][jss::state][0u]);
2911 testcase(
"RPC vault_info command line");
2913 env.rpc(
"vault_info",
strHex(keylet.
key),
"validated");
2915 BEAST_EXPECT(!jv[jss::result].isMember(jss::error));
2916 BEAST_EXPECT(jv[jss::result].isMember(jss::vault));
2918 jv[jss::result][jss::vault],
2919 jv[jss::result][jss::vault][jss::shares]);
2925 jvParams[jss::ledger_index] = jss::validated;
2926 jvParams[jss::vault_id] =
strHex(keylet.
key);
2927 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2929 BEAST_EXPECT(!jv[jss::result].isMember(jss::error));
2930 BEAST_EXPECT(jv[jss::result].isMember(jss::vault));
2932 jv[jss::result][jss::vault],
2933 jv[jss::result][jss::vault][jss::shares]);
2937 testcase(
"RPC vault_info invalid vault_id");
2939 jvParams[jss::ledger_index] = jss::validated;
2940 jvParams[jss::vault_id] =
"foobar";
2941 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2943 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2947 testcase(
"RPC vault_info json invalid index");
2949 jvParams[jss::ledger_index] = jss::validated;
2950 jvParams[jss::vault_id] = 0;
2951 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2953 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2957 testcase(
"RPC vault_info json by owner and sequence");
2959 jvParams[jss::ledger_index] = jss::validated;
2960 jvParams[jss::owner] = owner.human();
2961 jvParams[jss::seq] = sequence;
2962 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2964 BEAST_EXPECT(!jv[jss::result].isMember(jss::error));
2965 BEAST_EXPECT(jv[jss::result].isMember(jss::vault));
2967 jv[jss::result][jss::vault],
2968 jv[jss::result][jss::vault][jss::shares]);
2972 testcase(
"RPC vault_info json malformed sequence");
2974 jvParams[jss::ledger_index] = jss::validated;
2975 jvParams[jss::owner] = owner.human();
2976 jvParams[jss::seq] =
"foobar";
2977 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2979 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2983 testcase(
"RPC vault_info json invalid sequence");
2985 jvParams[jss::ledger_index] = jss::validated;
2986 jvParams[jss::owner] = owner.human();
2987 jvParams[jss::seq] = 0;
2988 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2990 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2994 testcase(
"RPC vault_info json negative sequence");
2996 jvParams[jss::ledger_index] = jss::validated;
2997 jvParams[jss::owner] = owner.human();
2998 jvParams[jss::seq] = -1;
2999 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3001 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3005 testcase(
"RPC vault_info json oversized sequence");
3007 jvParams[jss::ledger_index] = jss::validated;
3008 jvParams[jss::owner] = owner.human();
3009 jvParams[jss::seq] = 1e20;
3010 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3012 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3016 testcase(
"RPC vault_info json bool sequence");
3018 jvParams[jss::ledger_index] = jss::validated;
3019 jvParams[jss::owner] = owner.human();
3020 jvParams[jss::seq] =
true;
3021 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3023 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3027 testcase(
"RPC vault_info json malformed owner");
3029 jvParams[jss::ledger_index] = jss::validated;
3030 jvParams[jss::owner] =
"foobar";
3031 jvParams[jss::seq] = sequence;
3032 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3034 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3038 testcase(
"RPC vault_info json invalid combination only owner");
3040 jvParams[jss::ledger_index] = jss::validated;
3041 jvParams[jss::owner] = owner.human();
3042 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3044 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3048 testcase(
"RPC vault_info json invalid combination only seq");
3050 jvParams[jss::ledger_index] = jss::validated;
3051 jvParams[jss::seq] = sequence;
3052 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3054 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3058 testcase(
"RPC vault_info json invalid combination seq vault_id");
3060 jvParams[jss::ledger_index] = jss::validated;
3061 jvParams[jss::vault_id] =
strHex(keylet.
key);
3062 jvParams[jss::seq] = sequence;
3063 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3065 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3069 testcase(
"RPC vault_info json invalid combination owner vault_id");
3071 jvParams[jss::ledger_index] = jss::validated;
3072 jvParams[jss::vault_id] =
strHex(keylet.
key);
3073 jvParams[jss::owner] = owner.human();
3074 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3076 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3081 "RPC vault_info json invalid combination owner seq "
3084 jvParams[jss::ledger_index] = jss::validated;
3085 jvParams[jss::vault_id] =
strHex(keylet.
key);
3086 jvParams[jss::seq] = sequence;
3087 jvParams[jss::owner] = owner.human();
3088 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3090 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3094 testcase(
"RPC vault_info json no input");
3096 jvParams[jss::ledger_index] = jss::validated;
3097 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3099 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3103 testcase(
"RPC vault_info command line invalid index");
3104 Json::Value jv = env.rpc(
"vault_info",
"foobar",
"validated");
3105 BEAST_EXPECT(jv[jss::error].asString() ==
"invalidParams");
3109 testcase(
"RPC vault_info command line invalid index");
3110 Json::Value jv = env.rpc(
"vault_info",
"0",
"validated");
3112 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3116 testcase(
"RPC vault_info command line invalid index");
3120 jv[jss::result][jss::error].asString() ==
"entryNotFound");
3124 testcase(
"RPC vault_info command line invalid ledger");
3127 jv[jss::result][jss::error].asString() ==
"lgrNotFound");
3150BEAST_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