58 auto testCase = [&,
this](
66 Env env{*
this, args.features};
70 env.fund(XRP(1000), issuer, owner);
73 env(fset(issuer, asfAllowTrustLineClawback));
74 env(fset(issuer, asfRequireAuth));
78 env(trust(owner, asset(1000)));
79 env(trust(issuer, asset(0), owner, tfSetfAuth));
80 env(pay(issuer, owner, asset(1000)));
83 test(env, issuer, owner, asset, vault);
87 return [&, resultAfterCreate](
93 testcase(
"disabled single asset vault");
95 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
99 auto tx = vault.set({.owner = owner, .id =
keylet.key});
100 env(tx, kData(
"test"), Ter{resultAfterCreate});
105 vault.deposit({.depositor = owner, .id =
keylet.key, .amount = asset(10)});
106 env(tx, Ter{resultAfterCreate});
111 vault.withdraw({.depositor = owner, .id =
keylet.key, .amount = asset(10)});
112 env(tx, Ter{resultAfterCreate});
116 auto tx = vault.clawback(
117 {.issuer = issuer, .id =
keylet.key, .holder = owner, .amount = asset(10)});
118 env(tx, Ter{resultAfterCreate});
122 auto tx = vault.del({.owner = owner, .id =
keylet.key});
123 env(tx, Ter{resultAfterCreate});
128 testCase(testDisabled(), {.features = testableAmendments() - featureSingleAssetVault});
130 testCase(testDisabled(
tecNO_ENTRY), {.features = testableAmendments() - featureMPTokensV1});
138 testcase(
"disabled permissioned domains");
140 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
143 tx[sfFlags] = tx[sfFlags].asUInt() | tfVaultPrivate;
148 auto tx = vault.set({.owner = owner, .id =
keylet.key});
149 env(tx, kData(
"Test"));
155 {.features = testableAmendments() - featurePermissionedDomains});
157 testCase([&](Env& env,
164 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
165 tx[sfFlags] = tfClearDeepFreeze;
169 auto tx = vault.set({.owner = owner, .id =
keylet.key});
170 tx[sfFlags] = tfClearDeepFreeze;
176 vault.deposit({.depositor = owner, .id =
keylet.key, .amount = asset(10)});
177 tx[sfFlags] = tfClearDeepFreeze;
183 vault.withdraw({.depositor = owner, .id =
keylet.key, .amount = asset(10)});
184 tx[sfFlags] = tfClearDeepFreeze;
189 auto tx = vault.clawback(
190 {.issuer = issuer, .id =
keylet.key, .holder = owner, .amount = asset(10)});
191 tx[sfFlags] = tfClearDeepFreeze;
196 auto tx = vault.del({.owner = owner, .id =
keylet.key});
197 tx[sfFlags] = tfClearDeepFreeze;
202 testCase([&](Env& env,
209 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
214 auto tx = vault.set({.owner = owner, .id =
keylet.key});
221 vault.deposit({.depositor = owner, .id =
keylet.key, .amount = asset(10)});
228 vault.withdraw({.depositor = owner, .id =
keylet.key, .amount = asset(10)});
234 auto tx = vault.clawback(
235 {.issuer = issuer, .id =
keylet.key, .holder = owner, .amount = asset(10)});
241 auto tx = vault.del({.owner = owner, .id =
keylet.key});
249 testcase(
"disabled permissioned domain");
251 auto [tx,
keylet] = vault.create({.owner = owner, .asset =
xrpIssue()});
256 auto tx = vault.set({.owner = owner, .id =
keylet.key});
262 auto tx = vault.set({.owner = owner, .id =
keylet.key});
263 tx[sfDomainID] =
"0";
267 {.features = (testableAmendments()) - featurePermissionedDomains});
269 testCase([&](Env& env,
276 auto [tx,
keylet] = vault.create({.owner = owner, .asset =
xrpIssue()});
279 auto tx = vault.set({
288 vault.deposit({.depositor = owner, .id =
beast::kZero, .amount = asset(10)});
294 vault.withdraw({.depositor = owner, .id =
beast::kZero, .amount = asset(10)});
299 auto tx = vault.clawback(
300 {.issuer = issuer, .id =
beast::kZero, .holder = owner, .amount = asset(10)});
305 auto tx = vault.del({
315 testcase(
"withdraw to bad destination");
317 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
321 vault.withdraw({.depositor = owner, .id =
keylet.key, .amount = asset(10)});
322 tx[jss::Destination] =
"0";
332 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
338 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
345 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
349 auto const sleVault = env.le(
keylet);
350 BEAST_EXPECT(sleVault);
351 BEAST_EXPECT((*sleVault)[sfScale] == 18);
355 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
359 auto const sleVault = env.le(
keylet);
360 BEAST_EXPECT(sleVault);
361 BEAST_EXPECT((*sleVault)[sfScale] == 0);
365 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
368 auto const sleVault = env.le(
keylet);
369 BEAST_EXPECT(sleVault);
370 BEAST_EXPECT((*sleVault)[sfScale] == 6);
376 testcase(
"create or set invalid data");
378 auto [tx1,
keylet] = vault.create({.owner = owner, .asset = asset});
394 auto tx = vault.set({.owner = owner, .id =
keylet.key});
400 auto tx = vault.set({.owner = owner, .id =
keylet.key});
411 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
414 auto tx = vault.set({.owner = owner, .id =
keylet.key});
421 testcase(
"create with invalid metadata");
423 auto [tx1,
keylet] = vault.create({.owner = owner, .asset = asset});
427 tx[sfMPTokenMetadata] =
"";
444 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
447 auto tx = vault.set({.owner = owner, .id =
keylet.key});
457 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
460 auto tx = vault.deposit(
467 vault.deposit({.depositor = owner, .id =
keylet.key, .amount = asset(0)});
474 testcase(
"invalid set immutable flag");
476 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
479 auto tx = vault.set({.owner = owner, .id =
keylet.key});
480 tx[sfFlags] = tfVaultPrivate;
487 testcase(
"invalid withdraw amount");
489 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
492 auto tx = vault.withdraw(
499 vault.withdraw({.depositor = owner, .id =
keylet.key, .amount = asset(0)});
504 testCase([&](Env& env,
511 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
516 auto tx = vault.clawback(
517 {.issuer = issuer, .id =
keylet.key, .holder = owner, .amount = asset(50)});
522 auto tx = vault.clawback(
535 auto [tx1,
keylet] = vault.create({.owner = owner, .asset = asset});
539 tx[sfWithdrawalPolicy] = 0;
557 tx[sfFlags] = tfVaultPrivate;
558 tx[sfDomainID] =
"0";
570 auto testCase = [
this](
578 Env env{*
this, testableAmendments()};
579 Account const issuer{
"issuer"};
581 Account const depositor{
"depositor"};
583 env.fund(XRP(1000), issuer, owner, depositor);
588 test(env, issuer, owner, depositor, asset, vault);
600 tx[sfAssetsMaximum] = asset(0).number();
612 auto tx = vault.deposit(
613 {.depositor = depositor, .id =
keylet::skip().
key, .amount = asset(10)});
624 testcase(
"nothing to withdraw from");
625 auto tx = vault.withdraw(
626 {.depositor = depositor, .id =
keylet::skip().
key, .amount = asset(10)});
649 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
661 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
662 tx[sfWithdrawalPolicy] = 1;
663 testcase(
"explicitly select withdrawal policy");
674 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
676 env(tx, Fee(env.current()->fees().base - 1), Ter(
telINSUF_FEE_P));
686 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
690 env(pay(owner, issuer, XRP(775)));
702 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
703 tx[sfFlags] = tfVaultPrivate;
717 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
730 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
742 testcase(
"IOU fail because MPT is disabled");
743 Env env{*
this, (testableAmendments() - featureMPTokensV1)};
744 Account const issuer{
"issuer"};
746 env.fund(XRP(1000), issuer, owner);
749 Vault const vault{env};
750 Asset const asset = issuer[
"IOU"].asset();
751 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
759 Env env{*
this, testableAmendments()};
760 Account const issuer{
"issuer"};
762 env.fund(XRP(1000), issuer, owner);
764 env(fset(issuer, asfGlobalFreeze));
767 Vault const vault{env};
768 Asset const asset = issuer[
"IOU"].asset();
769 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
776 testcase(
"IOU fail create no ripling");
777 Env env{*
this, testableAmendments()};
778 Account const issuer{
"issuer"};
780 env.fund(XRP(1000), issuer, owner);
782 env(fclear(issuer, asfDefaultRipple));
785 Vault const vault{env};
786 Asset const asset = issuer[
"IOU"].asset();
787 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
794 Env env{*
this, testableAmendments()};
795 Account const issuer{
"issuer"};
797 env.fund(XRP(1000), owner);
800 Vault const vault{env};
801 Asset const asset = issuer[
"IOU"].asset();
803 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
811 testcase(
"IOU fail create vault for AMM LPToken");
812 Env env{*
this, testableAmendments()};
816 IOU
const usd = gw[
"USD"];
822 auto const defXRP = XRP(30000);
825 return a + XRP(1000);
827 auto defIOU =
STAmount{a.asset(), 30000};
830 return a +
STAmount{a.asset(), 1000};
832 auto const toFund1 = toFund(asset1);
833 auto const toFund2 = toFund(asset2);
834 BEAST_EXPECT(asset1 <= toFund1 && asset2 <= toFund2);
836 if (!asset1.native() && !asset2.native())
838 fund(env, gw, {alice, carol}, {toFund1, toFund2}, Fund::All);
840 else if (asset1.native())
842 fund(env, gw, {alice, carol}, toFund1, {toFund2}, Fund::All);
844 else if (asset2.native())
846 fund(env, gw, {alice, carol}, toFund2, {toFund1}, Fund::All);
849 AMM
const ammAlice(env, alice, asset1, asset2, CreateArg{.log =
false, .tfee = 0});
852 env.fund(XRP(1000000), owner);
854 Vault const vault{env};
855 auto [tx, k] = vault.create({.owner = owner, .asset = ammAlice.lptIssue()});
1084 bool const withFix = features[fixCleanup3_4_0];
1086 std::string{
"VaultWithdraw pseudo-account destination"} +
1087 (withFix ?
" (fixCleanup3_4_0)" :
" (pre-fix)"));
1089 Account const issuer{
"issuer"};
1091 Account const depositor{
"depositor"};
1092 Account const pdOwner{
"pdOwner"};
1093 Account const credIssuer{
"credIssuer"};
1096 Env env{*
this, features};
1097 Vault const vault{env};
1099 env.fund(XRP(100'000), issuer, owner, depositor, pdOwner, credIssuer);
1102 env(fset(issuer, asfDefaultRipple));
1106 for (
auto const& account : {owner, depositor})
1108 env.trust(asset(1'000'000), account);
1109 env(pay(issuer, account, asset(10'000)));
1116 auto const pseudoDestination = [&]() {
1117 auto [tx,
keylet] = vault.create({.owner = owner, .asset = asset});
1120 return Account(
"otherVault", env.le(
keylet)->at(sfAccount));
1125 auto const withdrawToPseudo = [&](
UInt256 const& vaultId) {
1126 auto tx = vault.withdraw({.depositor = depositor, .id = vaultId, .amount = asset(1)});
1127 tx[sfDestination] = pseudoDestination.human();
1132 auto [createTx,
keylet] = vault.create({.owner = owner, .asset = asset});
1136 env(vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(1'000)}));
1139 env(withdrawToPseudo(
keylet.key), Ter(expected));
1143 env(vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(1)}));
1148 auto const domainId = [&]() {
1150 {.issuer = credIssuer, .credType = credType}};
1153 return pdomain::getNewDomain(env.meta());
1156 env(credentials::create(depositor, credIssuer, credType));
1157 env(credentials::accept(depositor, credIssuer, credType));
1160 auto [createTx,
keylet] =
1161 vault.create({.owner = owner, .asset = asset, .flags = tfVaultPrivate});
1165 auto setTx = vault.set({.owner = owner, .id =
keylet.key});
1166 setTx[sfDomainID] =
to_string(domainId);
1170 env(vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(1'000)}));
1175 env(withdrawToPseudo(
keylet.key), Ter(expected));