diff --git a/InvariantCheck_8cpp_source.html b/InvariantCheck_8cpp_source.html
index d33be013b6..3c8b2fdbbc 100644
--- a/InvariantCheck_8cpp_source.html
+++ b/InvariantCheck_8cpp_source.html
@@ -2436,900 +2436,895 @@ $(document).ready(function() { init_codefold(0); });
-
-
-
-
-
-
-
-
2312 bool const enforce = view.
rules().
enabled(featureSingleAssetVault);
-
-
-
-
-
-
-
-
-
-
2322 "Invariant failed: vault operation succeeded without modifying "
-
-
-
2325 enforce,
"ripple::ValidVault::finalize : vault noop invariant");
-
-
-
-
-
-
-
-
-
2334 "Invariant failed: vault updated by a wrong transaction type";
-
-
-
2337 "ripple::ValidVault::finalize : illegal vault transaction "
-
-
-
-
-
-
-
-
2345 "Invariant failed: vault operation updated more than single vault";
-
-
2347 enforce,
"ripple::ValidVault::finalize : single vault invariant");
-
-
-
-
-
-
-
-
-
-
2357 if (txnType != ttVAULT_DELETE)
-
-
-
2360 "Invariant failed: vault deleted by a wrong transaction type";
-
-
-
2363 "ripple::ValidVault::finalize : illegal vault deletion "
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
2316 bool const enforce = view.
rules().
enabled(featureSingleAssetVault);
+
+
+
+
+
+
+
+
+
+
2326 "Invariant failed: vault operation succeeded without modifying "
+
+
+
2329 enforce,
"ripple::ValidVault::finalize : vault noop invariant");
+
+
+
+
+
+
+
+
+
2338 "Invariant failed: vault updated by a wrong transaction type";
+
+
+
2341 "ripple::ValidVault::finalize : illegal vault transaction "
+
+
+
+
+
+
+
+
2349 "Invariant failed: vault operation updated more than single vault";
+
+
2351 enforce,
"ripple::ValidVault::finalize : single vault invariant");
+
+
+
+
+
+
+
+
+
+
2361 if (txnType != ttVAULT_DELETE)
+
+
+
2364 "Invariant failed: vault deleted by a wrong transaction type";
+
+
+
2367 "ripple::ValidVault::finalize : illegal vault deletion "
+
+
+
-
-
-
-
-
-
-
2378 if (e.share.getMptID() == beforeVault.shareMPTID)
-
2379 return std::move(e);
-
-
-
-
-
-
-
2386 JLOG(j.
fatal()) <<
"Invariant failed: deleted vault must also "
-
-
-
-
2390 "ripple::ValidVault::finalize : shares deletion invariant");
-
-
-
-
-
2395 if (deletedShares->sharesTotal != 0)
-
-
2397 JLOG(j.
fatal()) <<
"Invariant failed: deleted vault must have no "
-
2398 "shares outstanding";
-
-
-
2401 if (beforeVault.assetsTotal !=
zero)
-
-
2403 JLOG(j.
fatal()) <<
"Invariant failed: deleted vault must have no "
-
2404 "assets outstanding";
-
-
-
2407 if (beforeVault.assetsAvailable !=
zero)
-
-
2409 JLOG(j.
fatal()) <<
"Invariant failed: deleted vault must have no "
-
-
-
-
-
-
-
2416 else if (txnType == ttVAULT_DELETE)
-
-
2418 JLOG(j.
fatal()) <<
"Invariant failed: vault deletion succeeded without "
-
-
-
2421 enforce,
"ripple::ValidVault::finalize : vault deletion invariant");
-
-
-
-
-
-
-
-
2429 "ripple::ValidVault::finalize : single vault operation");
-
-
-
-
-
-
-
-
-
-
2439 if (e.share.getMptID() == afterVault.shareMPTID)
-
-
-
-
2443 auto const sleShares =
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
2382 if (e.share.getMptID() == beforeVault.shareMPTID)
+
2383 return std::move(e);
+
+
+
+
+
+
+
2390 JLOG(j.
fatal()) <<
"Invariant failed: deleted vault must also "
+
+
+
+
2394 "ripple::ValidVault::finalize : shares deletion invariant");
+
+
+
+
+
2399 if (deletedShares->sharesTotal != 0)
+
+
2401 JLOG(j.
fatal()) <<
"Invariant failed: deleted vault must have no "
+
2402 "shares outstanding";
+
+
+
2405 if (beforeVault.assetsTotal !=
zero)
+
+
2407 JLOG(j.
fatal()) <<
"Invariant failed: deleted vault must have no "
+
2408 "assets outstanding";
+
+
+
2411 if (beforeVault.assetsAvailable !=
zero)
+
+
2413 JLOG(j.
fatal()) <<
"Invariant failed: deleted vault must have no "
+
+
+
+
+
+
+
2420 else if (txnType == ttVAULT_DELETE)
+
+
2422 JLOG(j.
fatal()) <<
"Invariant failed: vault deletion succeeded without "
+
+
+
2425 enforce,
"ripple::ValidVault::finalize : vault deletion invariant");
+
+
+
+
+
+
+
+
2433 "ripple::ValidVault::finalize : single vault operation");
+
+
+
+
+
+
+
+
+
+
2443 if (e.share.getMptID() == afterVault.shareMPTID)
+
+
+
+
2447 auto const sleShares =
+
-
-
-
-
-
-
-
2456 if (afterVault.asset != beforeVault.asset ||
-
2457 afterVault.pseudoId != beforeVault.pseudoId ||
-
2458 afterVault.shareMPTID != beforeVault.shareMPTID)
-
-
-
2461 <<
"Invariant failed: violation of vault immutable data";
-
-
-
-
-
-
-
2468 JLOG(j.
fatal()) <<
"Invariant failed: updated vault must have shares";
-
-
-
2471 "ripple::ValidVault::finalize : vault has shares invariant");
-
-
-
-
2475 if (updatedShares->sharesTotal == 0)
-
-
2477 if (afterVault.assetsTotal !=
zero)
-
-
2479 JLOG(j.
fatal()) <<
"Invariant failed: updated zero sized "
-
2480 "vault must have no assets outstanding";
-
-
-
2483 if (afterVault.assetsAvailable !=
zero)
-
-
2485 JLOG(j.
fatal()) <<
"Invariant failed: updated zero sized "
-
2486 "vault must have no assets available";
-
-
-
-
2490 else if (updatedShares->sharesTotal > updatedShares->sharesMaximum)
-
-
-
2493 <<
"Invariant failed: updated shares must not exceed maximum "
-
2494 << updatedShares->sharesMaximum;
-
-
-
-
2498 if (afterVault.assetsAvailable <
zero)
-
-
-
2501 <<
"Invariant failed: assets available must be positive";
-
-
-
-
2505 if (afterVault.assetsAvailable > afterVault.assetsTotal)
-
-
2507 JLOG(j.
fatal()) <<
"Invariant failed: assets available must "
-
2508 "not be greater than assets outstanding";
-
-
-
-
2512 afterVault.lossUnrealized >
-
2513 afterVault.assetsTotal - afterVault.assetsAvailable)
-
-
-
2516 <<
"Invariant failed: loss unrealized must not exceed "
-
2517 "the difference between assets outstanding and available";
-
-
-
-
2521 if (afterVault.assetsTotal <
zero)
-
-
-
2524 <<
"Invariant failed: assets outstanding must be positive";
-
-
-
-
2528 if (afterVault.assetsMaximum <
zero)
-
-
2530 JLOG(j.
fatal()) <<
"Invariant failed: assets maximum must be positive";
-
-
-
-
-
-
-
-
-
2539 "Invariant failed: vault created by a wrong transaction type";
-
-
2541 enforce,
"ripple::ValidVault::finalize : vault creation invariant");
-
-
-
-
-
2546 afterVault.lossUnrealized !=
beforeVault_[0].lossUnrealized)
-
-
-
2549 "Invariant failed: vault transaction must not change loss "
-
-
-
-
-
-
-
-
-
-
-
-
2561 if (e.share.getMptID() == beforeVault.shareMPTID)
-
2562 return std::move(e);
-
-
-
-
-
2567 if (!beforeShares &&
-
-
-
-
-
2572 JLOG(j.
fatal()) <<
"Invariant failed: vault operation succeeded "
-
2573 "without updating shares";
-
-
2575 enforce,
"ripple::ValidVault::finalize : shares noop invariant");
-
-
-
-
2579 auto const& vaultAsset = afterVault.asset;
-
-
-
-
-
-
-
2586 return it->second *
sign;
-
-
-
-
2590 [&]<
typename TIss>(TIss
const& issue) {
-
-
-
-
-
-
-
2597 id > issue.getIssuer() ? -1 : 1);
-
-
-
-
-
-
-
-
2605 vaultAsset.value());
-
-
-
2608 auto const it = [&]() {
-
2609 if (
id == afterVault.pseudoId)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
2626 case ttVAULT_CREATE: {
-
-
-
-
-
-
2632 <<
"Invariant failed: create operation must not have "
-
-
-
-
-
2637 if (afterVault.assetsAvailable !=
zero ||
-
2638 afterVault.assetsTotal !=
zero ||
-
2639 afterVault.lossUnrealized !=
zero ||
-
2640 updatedShares->sharesTotal != 0)
-
-
-
2643 <<
"Invariant failed: created vault must be empty";
-
-
-
-
2647 if (afterVault.pseudoId != updatedShares->share.getIssuer())
-
-
-
2650 <<
"Invariant failed: shares issuer and vault "
-
2651 "pseudo-account must be the same";
-
-
-
-
2655 auto const sleSharesIssuer = view.
read(
-
-
2657 if (!sleSharesIssuer)
-
-
-
2660 <<
"Invariant failed: shares issuer must exist";
-
-
-
-
-
-
-
2667 <<
"Invariant failed: shares issuer must be a "
-
-
-
-
-
2672 if (
auto const vaultId = (*sleSharesIssuer)[~sfVaultID];
-
2673 !vaultId || *vaultId != afterVault.key)
-
-
-
2676 <<
"Invariant failed: shares issuer pseudo-account "
-
2677 "must point back to the vault";
-
-
-
-
-
-
-
-
-
-
-
2688 "ripple::ValidVault::finalize : set updated a vault");
-
-
-
2691 auto const vaultDeltaAssets = deltaAssets(afterVault.pseudoId);
-
2692 if (vaultDeltaAssets)
-
-
-
2695 "Invariant failed: set must not change vault balance";
-
-
-
-
2699 if (beforeVault.assetsTotal != afterVault.assetsTotal)
-
-
-
2702 "Invariant failed: set must not change assets "
-
-
-
+
+
+
+
+
+
+
+
+
+
+
2460 if (afterVault.asset != beforeVault.asset ||
+
2461 afterVault.pseudoId != beforeVault.pseudoId ||
+
2462 afterVault.shareMPTID != beforeVault.shareMPTID)
+
+
+
2465 <<
"Invariant failed: violation of vault immutable data";
+
+
+
+
+
+
+
2472 JLOG(j.
fatal()) <<
"Invariant failed: updated vault must have shares";
+
+
+
2475 "ripple::ValidVault::finalize : vault has shares invariant");
+
+
+
+
2479 if (updatedShares->sharesTotal == 0)
+
+
2481 if (afterVault.assetsTotal !=
zero)
+
+
2483 JLOG(j.
fatal()) <<
"Invariant failed: updated zero sized "
+
2484 "vault must have no assets outstanding";
+
+
+
2487 if (afterVault.assetsAvailable !=
zero)
+
+
2489 JLOG(j.
fatal()) <<
"Invariant failed: updated zero sized "
+
2490 "vault must have no assets available";
+
+
+
+
2494 else if (updatedShares->sharesTotal > updatedShares->sharesMaximum)
+
+
+
2497 <<
"Invariant failed: updated shares must not exceed maximum "
+
2498 << updatedShares->sharesMaximum;
+
+
+
+
2502 if (afterVault.assetsAvailable <
zero)
+
+
+
2505 <<
"Invariant failed: assets available must be positive";
+
+
+
+
2509 if (afterVault.assetsAvailable > afterVault.assetsTotal)
+
+
2511 JLOG(j.
fatal()) <<
"Invariant failed: assets available must "
+
2512 "not be greater than assets outstanding";
+
+
+
+
2516 afterVault.lossUnrealized >
+
2517 afterVault.assetsTotal - afterVault.assetsAvailable)
+
+
+
2520 <<
"Invariant failed: loss unrealized must not exceed "
+
2521 "the difference between assets outstanding and available";
+
+
+
+
2525 if (afterVault.assetsTotal <
zero)
+
+
+
2528 <<
"Invariant failed: assets outstanding must be positive";
+
+
+
+
2532 if (afterVault.assetsMaximum <
zero)
+
+
2534 JLOG(j.
fatal()) <<
"Invariant failed: assets maximum must be positive";
+
+
+
+
+
+
+
+
+
2543 "Invariant failed: vault created by a wrong transaction type";
+
+
2545 enforce,
"ripple::ValidVault::finalize : vault creation invariant");
+
+
+
+
+
2550 afterVault.lossUnrealized !=
beforeVault_[0].lossUnrealized)
+
+
+
2553 "Invariant failed: vault transaction must not change loss "
+
+
+
+
+
+
+
+
+
+
+
+
2565 if (e.share.getMptID() == beforeVault.shareMPTID)
+
2566 return std::move(e);
+
+
+
+
+
2571 if (!beforeShares &&
+
+
+
+
+
2576 JLOG(j.
fatal()) <<
"Invariant failed: vault operation succeeded "
+
2577 "without updating shares";
+
+
2579 enforce,
"ripple::ValidVault::finalize : shares noop invariant");
+
+
+
+
2583 auto const& vaultAsset = afterVault.asset;
+
+
+
+
+
+
+
2590 return it->second *
sign;
+
+
+
+
2594 [&]<
typename TIss>(TIss
const& issue) {
+
+
+
+
+
+
+
2601 id > issue.getIssuer() ? -1 : 1);
+
+
+
+
+
+
+
+
2609 vaultAsset.value());
+
+
+
2612 auto ret = deltaAssets(tx[sfAccount]);
+
+
2614 if (!ret.has_value() || !vaultAsset.native())
+
+
+
+
2618 if (
auto const delegate = tx[~sfDelegate];
+
2619 delegate.has_value() && *delegate != tx[sfAccount])
+
+
+
2622 *ret += fee.
drops();
+
+
+
+
+
+
+
2629 auto const it = [&]() {
+
2630 if (
id == afterVault.pseudoId)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2647 case ttVAULT_CREATE: {
+
+
+
+
+
+
2653 <<
"Invariant failed: create operation must not have "
+
+
+
+
+
2658 if (afterVault.assetsAvailable !=
zero ||
+
2659 afterVault.assetsTotal !=
zero ||
+
2660 afterVault.lossUnrealized !=
zero ||
+
2661 updatedShares->sharesTotal != 0)
+
+
+
2664 <<
"Invariant failed: created vault must be empty";
+
+
+
+
2668 if (afterVault.pseudoId != updatedShares->share.getIssuer())
+
+
+
2671 <<
"Invariant failed: shares issuer and vault "
+
2672 "pseudo-account must be the same";
+
+
+
+
2676 auto const sleSharesIssuer = view.
read(
+
+
2678 if (!sleSharesIssuer)
+
+
+
2681 <<
"Invariant failed: shares issuer must exist";
+
+
+
+
+
+
+
2688 <<
"Invariant failed: shares issuer must be a "
+
+
+
+
+
2693 if (
auto const vaultId = (*sleSharesIssuer)[~sfVaultID];
+
2694 !vaultId || *vaultId != afterVault.key)
+
+
+
2697 <<
"Invariant failed: shares issuer pseudo-account "
+
2698 "must point back to the vault";
+
+
+
+
+
+
+
-
2707 if (afterVault.assetsMaximum >
zero &&
-
2708 afterVault.assetsTotal > afterVault.assetsMaximum)
-
-
-
2711 "Invariant failed: set assets outstanding must not "
-
2712 "exceed assets maximum";
-
-
-
-
2716 if (beforeVault.assetsAvailable != afterVault.assetsAvailable)
-
-
-
2719 "Invariant failed: set must not change assets "
-
-
-
-
-
2724 if (beforeShares && updatedShares &&
-
2725 beforeShares->sharesTotal != updatedShares->sharesTotal)
-
-
-
2728 "Invariant failed: set must not change shares "
-
-
-
-
-
-
-
2735 case ttVAULT_DEPOSIT: {
-
-
-
-
-
2740 "ripple::ValidVault::finalize : deposit updated a vault");
-
-
-
2743 auto const vaultDeltaAssets = deltaAssets(afterVault.pseudoId);
+
+
+
2709 "ripple::ValidVault::finalize : set updated a vault");
+
+
+
2712 auto const vaultDeltaAssets = deltaAssets(afterVault.pseudoId);
+
2713 if (vaultDeltaAssets)
+
+
+
2716 "Invariant failed: set must not change vault balance";
+
+
+
+
2720 if (beforeVault.assetsTotal != afterVault.assetsTotal)
+
+
+
2723 "Invariant failed: set must not change assets "
+
+
+
+
+
2728 if (afterVault.assetsMaximum >
zero &&
+
2729 afterVault.assetsTotal > afterVault.assetsMaximum)
+
+
+
2732 "Invariant failed: set assets outstanding must not "
+
2733 "exceed assets maximum";
+
+
+
+
2737 if (beforeVault.assetsAvailable != afterVault.assetsAvailable)
+
+
+
2740 "Invariant failed: set must not change assets "
+
+
+
-
2745 if (!vaultDeltaAssets)
-
-
-
2748 "Invariant failed: deposit must change vault balance";
-
-
-
-
2752 if (*vaultDeltaAssets > tx[sfAmount])
-
-
-
2755 "Invariant failed: deposit must not change vault "
-
2756 "balance by more than deposited amount";
-
-
-
-
2760 if (*vaultDeltaAssets <=
zero)
-
-
-
2763 "Invariant failed: deposit must increase vault balance";
-
-
-
-
-
-
2769 bool const issuerDeposit = [&]() ->
bool {
-
2770 if (vaultAsset.native())
-
-
2772 return tx[sfAccount] == vaultAsset.getIssuer();
-
-
-
-
-
2777 auto const accountDeltaAssets =
-
-
2779 if (
auto ret = deltaAssets(tx[sfAccount]); ret)
-
-
-
-
2783 if (vaultAsset.native())
-
2784 *ret += fee.
drops();
-
-
-
-
-
-
-
2791 if (!accountDeltaAssets)
-
-
-
2794 "Invariant failed: deposit must change depositor "
-
-
-
-
-
2799 if (*accountDeltaAssets >=
zero)
+
2745 if (beforeShares && updatedShares &&
+
2746 beforeShares->sharesTotal != updatedShares->sharesTotal)
+
+
+
2749 "Invariant failed: set must not change shares "
+
+
+
+
+
+
+
2756 case ttVAULT_DEPOSIT: {
+
+
+
+
+
2761 "ripple::ValidVault::finalize : deposit updated a vault");
+
+
+
2764 auto const vaultDeltaAssets = deltaAssets(afterVault.pseudoId);
+
+
2766 if (!vaultDeltaAssets)
+
+
+
2769 "Invariant failed: deposit must change vault balance";
+
+
+
+
2773 if (*vaultDeltaAssets > tx[sfAmount])
+
+
+
2776 "Invariant failed: deposit must not change vault "
+
2777 "balance by more than deposited amount";
+
+
+
+
2781 if (*vaultDeltaAssets <=
zero)
+
+
+
2784 "Invariant failed: deposit must increase vault balance";
+
+
+
+
+
+
2790 bool const issuerDeposit = [&]() ->
bool {
+
2791 if (vaultAsset.native())
+
+
2793 return tx[sfAccount] == vaultAsset.getIssuer();
+
+
+
+
+
2798 auto const accountDeltaAssets = deltaAssetsTxAccount();
+
2799 if (!accountDeltaAssets)
-
2802 "Invariant failed: deposit must decrease depositor "
+
2802 "Invariant failed: deposit must change depositor "
-
+
-
2807 if (*accountDeltaAssets * -1 != *vaultDeltaAssets)
+
2807 if (*accountDeltaAssets >=
zero)
-
2810 "Invariant failed: deposit must change vault and "
-
2811 "depositor balance by equal amount";
+
2810 "Invariant failed: deposit must decrease depositor "
+
-
-
-
2816 if (afterVault.assetsMaximum >
zero &&
-
2817 afterVault.assetsTotal > afterVault.assetsMaximum)
-
-
-
2820 "Invariant failed: deposit assets outstanding must not "
-
2821 "exceed assets maximum";
-
-
-
-
2825 auto const accountDeltaShares = deltaShares(tx[sfAccount]);
-
2826 if (!accountDeltaShares)
-
-
-
2829 "Invariant failed: deposit must change depositor "
-
-
-
-
-
2834 if (*accountDeltaShares <=
zero)
+
+
2815 if (*accountDeltaAssets * -1 != *vaultDeltaAssets)
+
+
+
2818 "Invariant failed: deposit must change vault and "
+
2819 "depositor balance by equal amount";
+
+
+
+
+
2824 if (afterVault.assetsMaximum >
zero &&
+
2825 afterVault.assetsTotal > afterVault.assetsMaximum)
+
+
+
2828 "Invariant failed: deposit assets outstanding must not "
+
2829 "exceed assets maximum";
+
+
+
+
2833 auto const accountDeltaShares = deltaShares(tx[sfAccount]);
+
2834 if (!accountDeltaShares)
-
2837 "Invariant failed: deposit must increase depositor "
+
2837 "Invariant failed: deposit must change depositor "
-
+
-
2842 auto const vaultDeltaShares = deltaShares(afterVault.pseudoId);
-
2843 if (!vaultDeltaShares)
-
-
-
2846 "Invariant failed: deposit must change vault shares";
-
+
2842 if (*accountDeltaShares <=
zero)
+
+
+
2845 "Invariant failed: deposit must increase depositor "
+
+
-
2850 if (*vaultDeltaShares * -1 != *accountDeltaShares)
-
-
-
2853 "Invariant failed: deposit must change depositor and "
-
2854 "vault shares by equal amount";
-
+
2850 auto const vaultDeltaShares = deltaShares(afterVault.pseudoId);
+
2851 if (!vaultDeltaShares || *vaultDeltaShares ==
zero)
+
+
+
2854 "Invariant failed: deposit must change vault shares";
+
-
2858 if (beforeVault.assetsTotal + *vaultDeltaAssets !=
-
2859 afterVault.assetsTotal)
-
-
2861 JLOG(j.
fatal()) <<
"Invariant failed: deposit and assets "
-
2862 "outstanding must add up";
+
2858 if (*vaultDeltaShares * -1 != *accountDeltaShares)
+
+
+
2861 "Invariant failed: deposit must change depositor and "
+
2862 "vault shares by equal amount";
-
2865 if (beforeVault.assetsAvailable + *vaultDeltaAssets !=
-
2866 afterVault.assetsAvailable)
-
-
2868 JLOG(j.
fatal()) <<
"Invariant failed: deposit and assets "
-
2869 "available must add up";
-
-
-
-
-
-
2875 case ttVAULT_WITHDRAW: {
-
-
-
-
-
2880 "ripple::ValidVault::finalize : withdrawal updated a "
-
-
-
-
2884 auto const vaultDeltaAssets = deltaAssets(afterVault.pseudoId);
+
+
2866 if (beforeVault.assetsTotal + *vaultDeltaAssets !=
+
2867 afterVault.assetsTotal)
+
+
2869 JLOG(j.
fatal()) <<
"Invariant failed: deposit and assets "
+
2870 "outstanding must add up";
+
+
+
2873 if (beforeVault.assetsAvailable + *vaultDeltaAssets !=
+
2874 afterVault.assetsAvailable)
+
+
2876 JLOG(j.
fatal()) <<
"Invariant failed: deposit and assets "
+
2877 "available must add up";
+
+
+
+
+
+
2883 case ttVAULT_WITHDRAW: {
+
-
2886 if (!vaultDeltaAssets)
-
-
2888 JLOG(j.
fatal()) <<
"Invariant failed: withdrawal must "
-
2889 "change vault balance";
-
-
-
-
2893 if (*vaultDeltaAssets >=
zero)
-
-
2895 JLOG(j.
fatal()) <<
"Invariant failed: withdrawal must "
-
2896 "decrease vault balance";
-
-
-
-
-
-
2902 bool const issuerWithdrawal = [&]() ->
bool {
-
2903 if (vaultAsset.native())
-
-
2905 auto const destination =
-
2906 tx[~sfDestination].value_or(tx[sfAccount]);
-
2907 return destination == vaultAsset.getIssuer();
-
-
-
2910 if (!issuerWithdrawal)
-
-
2912 auto const accountDeltaAssets =
-
-
2914 if (
auto ret = deltaAssets(tx[sfAccount]); ret)
-
-
-
-
2918 if (vaultAsset.native())
-
2919 *ret += fee.
drops();
-
-
-
-
-
-
-
2926 auto const otherAccountDelta =
-
-
2928 if (
auto const destination = tx[~sfDestination];
-
2929 destination && *destination != tx[sfAccount])
-
2930 return deltaAssets(*destination);
-
-
-
-
2934 if (accountDeltaAssets.has_value() ==
-
2935 otherAccountDelta.has_value())
-
-
-
2938 "Invariant failed: withdrawal must change one "
-
2939 "destination balance";
-
-
-
-
2943 auto const destinationDelta =
-
2944 accountDeltaAssets ? *accountDeltaAssets
-
2945 : *otherAccountDelta;
-
-
2947 if (destinationDelta <=
zero)
-
-
-
2950 "Invariant failed: withdrawal must increase "
-
2951 "destination balance";
-
-
-
-
2955 if (*vaultDeltaAssets * -1 != destinationDelta)
-
-
-
2958 "Invariant failed: withdrawal must change vault "
-
2959 "and destination balance by equal amount";
-
-
-
-
-
2964 auto const accountDeltaShares = deltaShares(tx[sfAccount]);
-
2965 if (!accountDeltaShares)
-
-
-
2968 "Invariant failed: withdrawal must change depositor "
-
-
-
-
-
2973 if (*accountDeltaShares >=
zero)
-
-
-
2976 "Invariant failed: withdrawal must decrease depositor "
-
-
-
-
-
2981 auto const vaultDeltaShares = deltaShares(afterVault.pseudoId);
-
2982 if (!vaultDeltaShares)
-
-
-
2985 "Invariant failed: withdrawal must change vault shares";
-
-
-
-
2989 if (*vaultDeltaShares * -1 != *accountDeltaShares)
-
-
-
2992 "Invariant failed: withdrawal must change depositor "
-
2993 "and vault shares by equal amount";
-
-
-
-
-
2998 if (beforeVault.assetsTotal + *vaultDeltaAssets !=
-
2999 afterVault.assetsTotal)
-
-
3001 JLOG(j.
fatal()) <<
"Invariant failed: withdrawal and "
-
3002 "assets outstanding must add up";
-
-
-
-
3006 if (beforeVault.assetsAvailable + *vaultDeltaAssets !=
-
3007 afterVault.assetsAvailable)
-
-
3009 JLOG(j.
fatal()) <<
"Invariant failed: withdrawal and "
-
3010 "assets available must add up";
-
-
+
+
+
2888 "ripple::ValidVault::finalize : withdrawal updated a "
+
+
+
+
2892 auto const vaultDeltaAssets = deltaAssets(afterVault.pseudoId);
+
+
2894 if (!vaultDeltaAssets)
+
+
2896 JLOG(j.
fatal()) <<
"Invariant failed: withdrawal must "
+
2897 "change vault balance";
+
+
+
+
2901 if (*vaultDeltaAssets >=
zero)
+
+
2903 JLOG(j.
fatal()) <<
"Invariant failed: withdrawal must "
+
2904 "decrease vault balance";
+
+
+
+
+
+
2910 bool const issuerWithdrawal = [&]() ->
bool {
+
2911 if (vaultAsset.native())
+
+
2913 auto const destination =
+
2914 tx[~sfDestination].value_or(tx[sfAccount]);
+
2915 return destination == vaultAsset.getIssuer();
+
+
+
2918 if (!issuerWithdrawal)
+
+
2920 auto const accountDeltaAssets = deltaAssetsTxAccount();
+
2921 auto const otherAccountDelta =
+
+
2923 if (
auto const destination = tx[~sfDestination];
+
2924 destination && *destination != tx[sfAccount])
+
2925 return deltaAssets(*destination);
+
+
+
+
2929 if (accountDeltaAssets.has_value() ==
+
2930 otherAccountDelta.has_value())
+
+
+
2933 "Invariant failed: withdrawal must change one "
+
2934 "destination balance";
+
+
+
+
2938 auto const destinationDelta =
+
2939 accountDeltaAssets ? *accountDeltaAssets
+
2940 : *otherAccountDelta;
+
+
2942 if (destinationDelta <=
zero)
+
+
+
2945 "Invariant failed: withdrawal must increase "
+
2946 "destination balance";
+
+
+
+
2950 if (*vaultDeltaAssets * -1 != destinationDelta)
+
+
+
2953 "Invariant failed: withdrawal must change vault "
+
2954 "and destination balance by equal amount";
+
+
+
+
+
2959 auto const accountDeltaShares = deltaShares(tx[sfAccount]);
+
2960 if (!accountDeltaShares)
+
+
+
2963 "Invariant failed: withdrawal must change depositor "
+
+
+
+
+
2968 if (*accountDeltaShares >=
zero)
+
+
+
2971 "Invariant failed: withdrawal must decrease depositor "
+
+
+
+
+
2976 auto const vaultDeltaShares = deltaShares(afterVault.pseudoId);
+
2977 if (!vaultDeltaShares || *vaultDeltaShares ==
zero)
+
+
+
2980 "Invariant failed: withdrawal must change vault shares";
+
+
+
+
2984 if (*vaultDeltaShares * -1 != *accountDeltaShares)
+
+
+
2987 "Invariant failed: withdrawal must change depositor "
+
2988 "and vault shares by equal amount";
+
+
+
+
+
2993 if (beforeVault.assetsTotal + *vaultDeltaAssets !=
+
2994 afterVault.assetsTotal)
+
+
2996 JLOG(j.
fatal()) <<
"Invariant failed: withdrawal and "
+
2997 "assets outstanding must add up";
+
+
+
+
3001 if (beforeVault.assetsAvailable + *vaultDeltaAssets !=
+
3002 afterVault.assetsAvailable)
+
+
3004 JLOG(j.
fatal()) <<
"Invariant failed: withdrawal and "
+
3005 "assets available must add up";
+
+
+
+
+
+
3011 case ttVAULT_CLAWBACK: {
+
-
-
-
3016 case ttVAULT_CLAWBACK: {
-
+
+
+
3016 "ripple::ValidVault::finalize : clawback updated a vault");
+
-
-
-
3021 "ripple::ValidVault::finalize : clawback updated a vault");
-
-
-
3024 if (vaultAsset.native() ||
-
3025 vaultAsset.getIssuer() != tx[sfAccount])
-
-
-
3028 "Invariant failed: clawback may only be performed by "
-
-
-
-
-
3033 auto const vaultDeltaAssets = deltaAssets(afterVault.pseudoId);
-
-
3035 if (!vaultDeltaAssets)
-
-
-
3038 "Invariant failed: clawback must change vault balance";
-
-
-
-
3042 if (*vaultDeltaAssets >=
zero)
-
-
-
3045 "Invariant failed: clawback must decrease vault "
-
-
-
-
-
3050 auto const accountDeltaShares = deltaShares(tx[sfHolder]);
-
3051 if (!accountDeltaShares)
-
-
-
3054 "Invariant failed: clawback must change holder shares";
-
-
-
-
3058 if (*accountDeltaShares >=
zero)
-
-
-
3061 "Invariant failed: clawback must decrease holder "
-
-
-
-
-
3066 auto const vaultDeltaShares = deltaShares(afterVault.pseudoId);
-
3067 if (!vaultDeltaShares)
-
-
-
3070 "Invariant failed: clawback must change vault shares";
-
-
-
-
3074 if (*vaultDeltaShares * -1 != *accountDeltaShares)
-
-
-
3077 "Invariant failed: clawback must change holder and "
-
3078 "vault shares by equal amount";
-
-
-
-
3082 if (beforeVault.assetsTotal + *vaultDeltaAssets !=
-
3083 afterVault.assetsTotal)
-
-
-
3086 "Invariant failed: clawback and assets outstanding "
-
-
-
-
-
3091 if (beforeVault.assetsAvailable + *vaultDeltaAssets !=
-
3092 afterVault.assetsAvailable)
-
-
-
3095 "Invariant failed: clawback and assets available must "
-
-
-
-
-
-
-
-
-
-
-
3106 "ripple::ValidVault::finalize : unknown transaction type");
-
-
-
-
-
-
-
-
-
-
3116 XRPL_ASSERT(enforce,
"ripple::ValidVault::finalize : vault invariants");
-
-
-
-
-
+
3019 if (vaultAsset.native() ||
+
3020 vaultAsset.getIssuer() != tx[sfAccount])
+
+
+
3023 "Invariant failed: clawback may only be performed by "
+
+
+
+
+
3028 auto const vaultDeltaAssets = deltaAssets(afterVault.pseudoId);
+
+
3030 if (!vaultDeltaAssets)
+
+
+
3033 "Invariant failed: clawback must change vault balance";
+
+
+
+
3037 if (*vaultDeltaAssets >=
zero)
+
+
+
3040 "Invariant failed: clawback must decrease vault "
+
+
+
+
+
3045 auto const accountDeltaShares = deltaShares(tx[sfHolder]);
+
3046 if (!accountDeltaShares)
+
+
+
3049 "Invariant failed: clawback must change holder shares";
+
+
+
+
3053 if (*accountDeltaShares >=
zero)
+
+
+
3056 "Invariant failed: clawback must decrease holder "
+
+
+
+
+
3061 auto const vaultDeltaShares = deltaShares(afterVault.pseudoId);
+
3062 if (!vaultDeltaShares || *vaultDeltaShares ==
zero)
+
+
+
3065 "Invariant failed: clawback must change vault shares";
+
+
+
+
3069 if (*vaultDeltaShares * -1 != *accountDeltaShares)
+
+
+
3072 "Invariant failed: clawback must change holder and "
+
3073 "vault shares by equal amount";
+
+
+
+
3077 if (beforeVault.assetsTotal + *vaultDeltaAssets !=
+
3078 afterVault.assetsTotal)
+
+
+
3081 "Invariant failed: clawback and assets outstanding "
+
+
+
+
+
3086 if (beforeVault.assetsAvailable + *vaultDeltaAssets !=
+
3087 afterVault.assetsAvailable)
+
+
+
3090 "Invariant failed: clawback and assets available must "
+
+
+
+
+
+
+
+
+
+
+
3101 "ripple::ValidVault::finalize : unknown transaction type");
+
+
+
+
+
+
+
+
+
+
3111 XRPL_ASSERT(enforce,
"ripple::ValidVault::finalize : vault invariants");
+
+
+
+
+
-
-
+
+
@@ -3467,7 +3462,7 @@ $(document).ready(function() { init_codefold(0); });
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
std::vector< std::string > errors_
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
-
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
+
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
std::vector< Shares > beforeMPTs_
std::vector< Vault > beforeVault_
std::unordered_map< uint256, Number > deltas_
diff --git a/InvariantCheck_8h_source.html b/InvariantCheck_8h_source.html
index a83085b89c..04de8236a5 100644
--- a/InvariantCheck_8h_source.html
+++ b/InvariantCheck_8h_source.html
@@ -931,7 +931,7 @@ $(document).ready(function() { init_codefold(0); });
std::vector< std::string > errors_
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
Invariants: Vault object and MPTokenIssuance for vault shares.
-
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
+
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
std::vector< Shares > beforeMPTs_
std::vector< Vault > beforeVault_
std::unordered_map< uint256, Number > deltas_
diff --git a/Invariants__test_8cpp_source.html b/Invariants__test_8cpp_source.html
index 21f5e9ddc2..f4e96d5685 100644
--- a/Invariants__test_8cpp_source.html
+++ b/Invariants__test_8cpp_source.html
@@ -1856,7 +1856,7 @@ $(document).ready(function() { init_codefold(0); });
-
+
@@ -1869,7 +1869,7 @@ $(document).ready(function() { init_codefold(0); });
1765 auto constexpr adjust = [&](
ApplyView& ac,
-
1767 Adjustements args) {
+
1768 auto sleVault = ac.
peek(keylet);
@@ -1895,1673 +1895,1734 @@ $(document).ready(function() { init_codefold(0); });
1792 if (args.sharesTotal)
-
1793 (*sleShares)[sfOutstandingAmount] =
-
1794 *(*sleShares)[sfOutstandingAmount] + *args.sharesTotal;
-
-
-
1797 auto const assets = *(*sleVault)[sfAsset];
-
1798 auto const pseudoId = *(*sleVault)[sfAccount];
-
1799 if (args.vaultAssets)
-
-
1801 if (assets.native())
-
-
-
1804 if (!slePseudoAccount)
-
-
1806 (*slePseudoAccount)[sfBalance] =
-
1807 *(*slePseudoAccount)[sfBalance] + *args.vaultAssets;
-
1808 ac.
update(slePseudoAccount);
-
-
-
-
1812 auto const mptId = assets.get<
MPTIssue>().getMptID();
-
-
-
-
1816 (*sleMPToken)[sfMPTAmount] =
-
1817 *(*sleMPToken)[sfMPTAmount] + *args.vaultAssets;
-
-
-
-
-
-
-
1824 if (args.accountAssets)
-
-
1826 auto const& pair = *args.accountAssets;
-
1827 if (assets.native())
-
-
-
-
-
1832 (*sleAccount)[sfBalance] =
-
1833 *(*sleAccount)[sfBalance] + pair.amount;
-
-
-
-
-
1838 auto const mptID = assets.get<
MPTIssue>().getMptID();
-
-
-
-
-
1843 (*sleMPToken)[sfMPTAmount] =
-
1844 *(*sleMPToken)[sfMPTAmount] + pair.amount;
-
-
-
-
-
-
-
1851 if (args.accountShares)
-
-
1853 auto const& pair = *args.accountShares;
-
-
-
-
-
1858 (*sleMPToken)[sfMPTAmount] =
-
1859 *(*sleMPToken)[sfMPTAmount] + pair.amount;
-
-
-
-
-
-
1865 constexpr auto args =
-
1866 [](
AccountID id,
int adjustement,
auto fn) -> Adjustements {
-
1867 Adjustements sample = {
-
1868 .assetsTotal = adjustement,
-
1869 .assetsAvailable = adjustement,
-
1870 .lossUnrealized = 0,
-
1871 .sharesTotal = adjustement,
-
1872 .vaultAssets = adjustement,
-
-
1874 AccountAmount{id, -adjustement},
-
-
1876 AccountAmount{id, adjustement}};
-
-
-
-
-
-
-
1883 auto const precloseXrp =
-
-
1885 env.fund(
XRP(1000), A3, A4);
-
-
-
1888 vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
1891 {.depositor = A1, .id = keylet.key, .amount = XRP(10)}));
+
+
1794 (*sleShares)[sfOutstandingAmount] =
+
1795 *(*sleShares)[sfOutstandingAmount] + *args.sharesTotal;
+
+
+
+
1799 auto const assets = *(*sleVault)[sfAsset];
+
1800 auto const pseudoId = *(*sleVault)[sfAccount];
+
1801 if (args.vaultAssets)
+
+
1803 if (assets.native())
+
+
+
1806 if (!slePseudoAccount)
+
+
1808 (*slePseudoAccount)[sfBalance] =
+
1809 *(*slePseudoAccount)[sfBalance] + *args.vaultAssets;
+
1810 ac.
update(slePseudoAccount);
+
+
+
+
1814 auto const mptId = assets.get<
MPTIssue>().getMptID();
+
+
+
+
1818 (*sleMPToken)[sfMPTAmount] =
+
1819 *(*sleMPToken)[sfMPTAmount] + *args.vaultAssets;
+
+
+
+
+
+
+
1826 if (args.accountAssets)
+
+
1828 auto const& pair = *args.accountAssets;
+
1829 if (assets.native())
+
+
+
+
+
1834 (*sleAccount)[sfBalance] =
+
1835 *(*sleAccount)[sfBalance] + pair.amount;
+
+
+
+
+
1840 auto const mptID = assets.get<
MPTIssue>().getMptID();
+
+
+
+
+
1845 (*sleMPToken)[sfMPTAmount] =
+
1846 *(*sleMPToken)[sfMPTAmount] + pair.amount;
+
+
+
+
+
+
+
1853 if (args.accountShares)
+
+
1855 auto const& pair = *args.accountShares;
+
+
+
+
+
1860 (*sleMPToken)[sfMPTAmount] =
+
1861 *(*sleMPToken)[sfMPTAmount] + pair.amount;
+
+
+
+
+
+
1867 constexpr auto args =
+
1868 [](
AccountID id,
int adjustment,
auto fn) -> Adjustments {
+
1869 Adjustments sample = {
+
1870 .assetsTotal = adjustment,
+
1871 .assetsAvailable = adjustment,
+
1872 .lossUnrealized = 0,
+
1873 .sharesTotal = adjustment,
+
1874 .vaultAssets = adjustment,
+
+
1876 AccountAmount{id, -adjustment},
+
+
1878 AccountAmount{id, adjustment}};
+
+
+
+
+
+
+
1885 auto const precloseXrp =
+
+
1887 env.fund(
XRP(1000), A3, A4);
+
+
+
1890 vault.create({.owner =
A1, .asset =
xrpIssue()});
+
-
1893 {.depositor = A2, .id = keylet.key, .amount = XRP(10)}));
+
1893 {.depositor = A1, .id = keylet.key, .amount = XRP(10)}));
-
1895 {.depositor = A3, .id = keylet.key, .amount = XRP(10)}));
-
-
-
-
1899 testcase <<
"Vault general checks";
-
-
1901 {
"vault deletion succeeded without deleting a vault"},
-
-
-
1904 auto sleVault = ac.view().
peek(keylet);
-
-
-
1907 ac.view().
update(sleVault);
-
-
-
-
-
-
-
-
1915 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
-
-
-
1921 {
"vault updated by a wrong transaction type"},
-
-
-
1924 auto sleVault = ac.view().
peek(keylet);
-
-
-
1927 ac.view().
erase(sleVault);
-
-
-
-
-
-
-
-
1935 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
-
-
-
1941 {
"vault updated by a wrong transaction type"},
-
-
-
1944 auto sleVault = ac.view().
peek(keylet);
-
-
-
1947 ac.view().
update(sleVault);
-
-
-
-
-
-
-
-
1955 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
-
-
-
1961 {
"vault updated by a wrong transaction type"},
-
-
1963 auto const sequence = ac.view().
seq();
-
-
-
1966 auto const vaultPage = ac.view().
dirInsert(
-
-
-
-
1970 sleVault->setFieldU64(sfOwnerNode, *vaultPage);
-
1971 ac.view().
insert(sleVault);
-
-
-
-
-
-
-
-
1979 {
"vault deleted by a wrong transaction type"},
-
-
-
1982 auto sleVault = ac.view().
peek(keylet);
-
-
-
1985 ac.view().
erase(sleVault);
-
-
-
-
-
-
-
-
1993 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
-
-
-
1999 {
"vault operation updated more than single vault"},
-
-
-
-
2003 auto sleVault = ac.view().
peek(keylet);
-
-
-
2006 ac.view().
erase(sleVault);
-
-
-
-
2010 auto sleVault = ac.view().
peek(keylet);
-
-
-
2013 ac.view().
erase(sleVault);
-
-
-
-
-
-
-
-
-
-
-
2024 vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
-
-
2029 vault.create({.owner =
A2, .asset =
xrpIssue()});
-
-
-
-
-
-
-
2036 {
"vault operation updated more than single vault"},
-
-
2038 auto const sequence = ac.view().
seq();
-
2039 auto const insertVault = [&](
Account const A) {
-
-
-
2042 auto const vaultPage = ac.view().
dirInsert(
-
-
-
-
2046 sleVault->setFieldU64(sfOwnerNode, *vaultPage);
-
2047 ac.view().
insert(sleVault);
-
-
-
-
-
-
-
-
-
-
-
2058 {
"deleted vault must also delete shares"},
-
-
-
2061 auto sleVault = ac.view().
peek(keylet);
-
-
-
2064 ac.view().
erase(sleVault);
-
-
-
-
-
-
-
-
2072 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
-
-
-
2078 {
"deleted vault must have no shares outstanding",
-
2079 "deleted vault must have no assets outstanding",
-
2080 "deleted vault must have no assets available"},
-
-
-
2083 auto sleVault = ac.view().
peek(keylet);
-
-
-
2086 auto sleShares = ac.view().
peek(
-
-
-
-
2090 ac.view().
erase(sleVault);
-
2091 ac.view().
erase(sleShares);
-
-
-
-
-
-
-
-
-
2100 vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
2103 {.depositor = A1, .id = keylet.key, .amount = XRP(10)}));
-
-
-
-
-
2108 {
"vault operation succeeded without modifying a vault"},
-
-
-
2111 auto sleVault = ac.view().
peek(keylet);
-
-
-
2114 auto sleShares = ac.view().
peek(
-
-
-
-
-
-
2120 sleShares->setFieldH256(sfDomainID,
uint256(13));
-
2121 ac.view().
update(sleShares);
-
-
-
-
-
-
-
-
-
-
2131 {
"vault operation succeeded without modifying a vault"},
-
-
-
-
-
-
-
-
-
2140 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
-
-
-
2146 {
"vault operation succeeded without modifying a vault"},
-
-
-
-
-
-
-
-
-
2155 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
-
-
-
2161 {
"vault operation succeeded without modifying a vault"},
-
-
-
-
-
-
-
-
-
2170 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
-
-
-
2176 {
"vault operation succeeded without modifying a vault"},
-
-
-
-
-
-
-
-
-
2185 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
-
-
-
2191 {
"vault operation succeeded without modifying a vault"},
-
-
-
-
-
-
-
-
-
2200 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
-
-
-
2206 {
"updated vault must have shares"},
-
-
-
2209 auto sleVault = ac.view().
peek(keylet);
-
-
-
2212 (*sleVault)[sfAssetsMaximum] = 200;
-
2213 ac.view().
update(sleVault);
-
-
2215 auto sleShares = ac.view().
peek(
-
-
-
-
2219 ac.view().
erase(sleShares);
-
-
-
-
-
-
-
-
2227 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
-
-
-
2233 {
"vault operation succeeded without updating shares",
-
2234 "assets available must not be greater than assets outstanding"},
-
-
-
2237 auto sleVault = ac.view().
peek(keylet);
-
-
-
2240 (*sleVault)[sfAssetsTotal] = 9;
-
2241 ac.view().
update(sleVault);
-
-
-
-
-
-
-
-
-
2250 vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
2253 {.depositor = A1, .id = keylet.key, .amount = XRP(10)}));
-
-
-
-
-
2258 {
"set must not change assets outstanding",
-
2259 "set must not change assets available",
-
2260 "set must not change shares outstanding",
-
2261 "set must not change vault balance",
-
2262 "assets available must be positive",
-
2263 "assets available must not be greater than assets outstanding",
-
2264 "assets outstanding must be positive"},
-
-
-
2267 auto sleVault = ac.view().
peek(keylet);
-
-
-
2270 auto slePseudoAccount =
-
-
2272 if (!slePseudoAccount)
-
-
2274 (*slePseudoAccount)[sfBalance] =
-
2275 *(*slePseudoAccount)[sfBalance] - 10;
-
2276 ac.view().
update(slePseudoAccount);
-
-
-
-
-
-
2282 (*sleA4)[sfBalance] = *(*sleA4)[sfBalance] + 10;
-
-
-
-
-
-
2288 args(
A2.id(), 0, [&](Adjustements& sample) {
-
2289 sample.assetsAvailable = (DROPS_PER_XRP * -100).value();
-
2290 sample.assetsTotal = (DROPS_PER_XRP * -200).value();
-
2291 sample.sharesTotal = -1;
-
-
-
-
-
-
-
-
-
-
2301 {
"violation of vault immutable data"},
-
-
-
2304 auto sleVault = ac.view().
peek(keylet);
-
-
-
2307 sleVault->setFieldIssue(
-
-
2309 ac.view().
update(sleVault);
-
-
-
-
-
-
-
-
-
2318 {
"violation of vault immutable data"},
-
-
-
2321 auto sleVault = ac.view().
peek(keylet);
-
-
-
2324 sleVault->setAccountID(sfAccount,
A2.id());
-
2325 ac.view().
update(sleVault);
-
-
-
-
-
-
-
-
-
2334 {
"violation of vault immutable data"},
-
-
-
2337 auto sleVault = ac.view().
peek(keylet);
-
-
-
2340 (*sleVault)[sfShareMPTID] =
MPTID(42);
-
2341 ac.view().
update(sleVault);
-
-
-
-
-
-
-
-
-
2350 {
"vault transaction must not change loss unrealized",
-
2351 "set must not change assets outstanding"},
-
-
-
-
-
-
2357 args(
A2.id(), 0, [&](Adjustements& sample) {
-
2358 sample.lossUnrealized = 13;
-
2359 sample.assetsTotal = 20;
-
-
-
-
-
-
-
-
-
-
2369 {
"loss unrealized must not exceed the difference "
-
2370 "between assets outstanding and available",
-
2371 "vault transaction must not change loss unrealized"},
-
-
-
-
-
-
2377 args(
A2.id(), 100, [&](Adjustements& sample) {
-
2378 sample.lossUnrealized = 13;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
2392 {
"set assets outstanding must not exceed assets maximum"},
-
-
-
-
-
-
2398 args(
A2.id(), 0, [&](Adjustements& sample) {
-
2399 sample.assetsMaximum = 1;
-
-
-
-
-
-
-
-
-
-
2409 {
"assets maximum must be positive"},
-
-
-
-
-
-
2415 args(
A2.id(), 0, [&](Adjustements& sample) {
-
2416 sample.assetsMaximum = -1;
-
-
-
-
-
-
-
-
-
-
2426 {
"set must not change shares outstanding",
-
2427 "updated zero sized vault must have no assets outstanding",
-
2428 "updated zero sized vault must have no assets available"},
-
-
-
2431 auto sleVault = ac.view().
peek(keylet);
-
-
-
2434 ac.view().
update(sleVault);
-
2435 auto sleShares = ac.view().
peek(
-
-
-
-
2439 (*sleShares)[sfOutstandingAmount] = 0;
-
2440 ac.view().
update(sleShares);
-
-
-
-
-
-
-
-
-
-
2450 {
"updated shares must not exceed maximum"},
-
-
-
2453 auto sleVault = ac.view().
peek(keylet);
-
-
-
2456 auto sleShares = ac.view().
peek(
-
-
-
-
2460 (*sleShares)[sfMaximumAmount] = 10;
-
2461 ac.view().
update(sleShares);
-
-
-
2464 ac.view(), keylet, args(
A2.id(), 10, [](Adjustements&) {}));
-
-
-
-
-
-
-
-
-
2473 {
"updated shares must not exceed maximum"},
-
-
-
-
2477 ac.view(), keylet, args(
A2.id(), 10, [](Adjustements&) {}));
-
-
2479 auto sleVault = ac.view().
peek(keylet);
-
-
-
2482 auto sleShares = ac.view().
peek(
-
-
-
-
-
2487 ac.view().
update(sleShares);
-
-
-
-
-
-
-
-
-
-
-
-
2499 "created vault must be empty",
-
2500 "updated zero sized vault must have no assets outstanding",
-
2501 "create operation must not have updated a vault",
-
-
-
-
2505 auto sleVault = ac.view().
peek(keylet);
-
-
-
2508 (*sleVault)[sfAssetsTotal] = 9;
-
2509 ac.view().
update(sleVault);
-
-
-
-
-
-
-
-
-
2518 vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
-
-
-
-
2525 "created vault must be empty",
-
2526 "updated zero sized vault must have no assets available",
-
2527 "assets available must not be greater than assets outstanding",
-
2528 "create operation must not have updated a vault",
-
-
-
-
2532 auto sleVault = ac.view().
peek(keylet);
-
-
-
2535 (*sleVault)[sfAssetsAvailable] = 9;
-
2536 ac.view().
update(sleVault);
-
-
-
-
-
-
-
-
-
2545 vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
-
-
-
-
2552 "created vault must be empty",
-
2553 "loss unrealized must not exceed the difference between assets "
-
2554 "outstanding and available",
-
2555 "vault transaction must not change loss unrealized",
-
2556 "create operation must not have updated a vault",
-
-
-
-
2560 auto sleVault = ac.view().
peek(keylet);
-
-
-
2563 (*sleVault)[sfLossUnrealized] = 1;
-
2564 ac.view().
update(sleVault);
-
-
-
-
-
-
-
-
-
2573 vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
-
-
-
-
2580 "created vault must be empty",
-
2581 "create operation must not have updated a vault",
-
-
-
-
2585 auto sleVault = ac.view().
peek(keylet);
-
-
-
2588 auto sleShares = ac.view().
peek(
-
-
-
-
2592 ac.view().
update(sleVault);
-
2593 (*sleShares)[sfOutstandingAmount] = 9;
-
2594 ac.view().
update(sleShares);
-
-
-
-
-
-
-
-
-
2603 vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
-
-
-
-
2610 "assets maximum must be positive",
-
2611 "create operation must not have updated a vault",
-
-
-
-
2615 auto sleVault = ac.view().
peek(keylet);
-
-
-
2618 (*sleVault)[sfAssetsMaximum] =
Number(-1);
-
2619 ac.view().
update(sleVault);
-
-
-
-
-
-
-
-
-
2628 vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
-
-
-
2634 {
"create operation must not have updated a vault",
-
2635 "shares issuer and vault pseudo-account must be the same",
-
2636 "shares issuer must be a pseudo-account",
-
2637 "shares issuer pseudo-account must point back to the vault"},
-
-
-
2640 auto sleVault = ac.view().
peek(keylet);
-
-
-
2643 auto sleShares = ac.view().
peek(
-
-
-
-
2647 ac.view().
update(sleVault);
-
2648 (*sleShares)[sfIssuer] =
A1.id();
-
2649 ac.view().
update(sleShares);
-
-
-
-
-
-
-
-
-
2658 vault.create({.owner =
A1, .asset =
xrpIssue()});
-
-
-
-
-
-
2664 {
"vault created by a wrong transaction type",
-
2665 "account root created illegally"},
-
-
-
-
-
2670 auto const sequence = ac.view().
seq();
-
-
-
2673 auto const vaultPage = ac.view().
dirInsert(
-
-
-
-
2677 sleVault->setFieldU64(sfOwnerNode, *vaultPage);
-
-
-
-
-
-
-
2684 sleAccount->setAccountID(sfAccount, pseudoId);
-
2685 sleAccount->setFieldAmount(sfBalance,
STAmount{});
-
-
-
-
-
2690 sleAccount->setFieldU32(sfSequence, seqno);
-
2691 sleAccount->setFieldU32(
-
-
-
2694 sleAccount->setFieldH256(sfVaultID, vaultKeylet.key);
-
2695 ac.view().
insert(sleAccount);
-
-
2697 auto const sharesMptId =
makeMptID(sequence, pseudoId);
-
-
-
2700 auto const sharesPage = ac.view().
dirInsert(
-
-
-
-
2704 sleShares->setFieldU64(sfOwnerNode, *sharesPage);
-
-
2706 sleShares->at(sfFlags) = 0;
-
2707 sleShares->at(sfIssuer) = pseudoId;
-
2708 sleShares->at(sfOutstandingAmount) = 0;
-
2709 sleShares->at(sfSequence) = sequence;
-
-
2711 sleVault->at(sfAccount) = pseudoId;
-
2712 sleVault->at(sfFlags) = 0;
-
2713 sleVault->at(sfSequence) = sequence;
-
2714 sleVault->at(sfOwner) =
A1.id();
-
2715 sleVault->at(sfAssetsTotal) =
Number(0);
-
2716 sleVault->at(sfAssetsAvailable) =
Number(0);
-
2717 sleVault->at(sfLossUnrealized) =
Number(0);
-
2718 sleVault->at(sfShareMPTID) = sharesMptId;
-
2719 sleVault->at(sfWithdrawalPolicy) =
-
-
-
2722 ac.view().
insert(sleVault);
-
2723 ac.view().
insert(sleShares);
-
-
-
-
-
-
-
-
2731 {
"shares issuer and vault pseudo-account must be the same",
-
2732 "shares issuer pseudo-account must point back to the vault"},
-
-
2734 auto const sequence = ac.view().
seq();
-
-
-
2737 auto const vaultPage = ac.view().
dirInsert(
-
-
-
-
2741 sleVault->setFieldU64(sfOwnerNode, *vaultPage);
-
-
-
-
-
-
-
2748 sleAccount->setAccountID(sfAccount, pseudoId);
-
2749 sleAccount->setFieldAmount(sfBalance,
STAmount{});
-
-
-
-
-
2754 sleAccount->setFieldU32(sfSequence, seqno);
-
2755 sleAccount->setFieldU32(
-
-
-
-
-
2760 sleAccount->setFieldH256(sfVaultID,
uint256(42));
-
2761 ac.view().
insert(sleAccount);
-
-
2763 auto const sharesMptId =
makeMptID(sequence, pseudoId);
-
-
-
2766 auto const sharesPage = ac.view().
dirInsert(
-
-
-
-
2770 sleShares->setFieldU64(sfOwnerNode, *sharesPage);
-
-
2772 sleShares->at(sfFlags) = 0;
-
2773 sleShares->at(sfIssuer) = pseudoId;
-
2774 sleShares->at(sfOutstandingAmount) = 0;
-
2775 sleShares->at(sfSequence) = sequence;
-
-
-
-
2779 sleVault->at(sfAccount) =
A2.id();
-
2780 sleVault->at(sfFlags) = 0;
-
2781 sleVault->at(sfSequence) = sequence;
-
2782 sleVault->at(sfOwner) =
A1.id();
-
2783 sleVault->at(sfAssetsTotal) =
Number(0);
-
2784 sleVault->at(sfAssetsAvailable) =
Number(0);
-
2785 sleVault->at(sfLossUnrealized) =
Number(0);
-
2786 sleVault->at(sfShareMPTID) = sharesMptId;
-
2787 sleVault->at(sfWithdrawalPolicy) =
-
-
-
2790 ac.view().
insert(sleVault);
-
2791 ac.view().
insert(sleShares);
-
-
-
-
-
-
-
-
2799 {
"shares issuer and vault pseudo-account must be the same",
-
2800 "shares issuer must exist"},
-
-
2802 auto const sequence = ac.view().
seq();
-
-
-
2805 auto const vaultPage = ac.view().
dirInsert(
-
-
-
-
2809 sleVault->setFieldU64(sfOwnerNode, *vaultPage);
-
-
2811 auto const sharesMptId =
makeMptID(sequence,
A2.id());
-
-
-
2814 auto const sharesPage = ac.view().
dirInsert(
-
-
-
-
2818 sleShares->setFieldU64(sfOwnerNode, *sharesPage);
-
-
2820 sleShares->at(sfFlags) = 0;
-
-
-
2823 sleShares->at(sfOutstandingAmount) = 0;
-
2824 sleShares->at(sfSequence) = sequence;
-
-
2826 sleVault->at(sfAccount) =
A2.id();
-
2827 sleVault->at(sfFlags) = 0;
-
2828 sleVault->at(sfSequence) = sequence;
-
2829 sleVault->at(sfOwner) =
A1.id();
-
2830 sleVault->at(sfAssetsTotal) =
Number(0);
-
2831 sleVault->at(sfAssetsAvailable) =
Number(0);
-
2832 sleVault->at(sfLossUnrealized) =
Number(0);
-
2833 sleVault->at(sfShareMPTID) = sharesMptId;
-
2834 sleVault->at(sfWithdrawalPolicy) =
-
-
-
2837 ac.view().
insert(sleVault);
-
2838 ac.view().
insert(sleShares);
-
-
-
-
-
-
-
-
-
2847 {
"deposit must change vault balance"},
-
-
-
-
-
-
2853 args(
A2.id(), 0, [&](Adjustements& sample) {}));
-
-
-
-
-
-
-
-
2861 {
"deposit assets outstanding must not exceed assets maximum"},
-
-
-
-
-
-
2867 args(
A2.id(), 200, [&](Adjustements& sample) {
-
2868 sample.assetsMaximum = 1;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
2886 {
"deposit must increase vault balance",
-
2887 "deposit must change depositor balance"},
-
-
-
-
-
-
-
-
2895 (*sleA4)[sfBalance] = *(*sleA4)[sfBalance] + 10;
-
-
-
-
-
-
2901 args(A3.id(), -10, [&](Adjustements& sample) {
-
2902 sample.accountAssets->amount = -100;
-
-
-
-
-
-
-
-
2910 tx[sfAccount] = A3.id();
-
-
-
-
-
-
2916 {
"deposit must increase vault balance",
-
2917 "deposit must decrease depositor balance",
-
2918 "deposit must change vault and depositor balance by equal amount",
-
2919 "deposit and assets outstanding must add up",
-
2920 "deposit and assets available must add up"},
-
-
-
-
-
-
-
-
2928 (*sleA3)[sfBalance] = *(*sleA3)[sfBalance] + 10;
-
-
-
-
-
-
2934 args(
A2.id(), 10, [&](Adjustements& sample) {
-
2935 sample.vaultAssets = -20;
-
2936 sample.accountAssets->amount = 10;
-
-
-
-
-
-
-
-
-
-
-
-
2948 {
"deposit must change depositor balance"},
-
-
-
-
-
-
-
-
2956 (*sleA3)[sfBalance] = *(*sleA3)[sfBalance] - 10;
-
-
-
-
-
-
2962 args(
A2.id(), 10, [&](Adjustements& sample) {
-
2963 sample.accountAssets->amount = 0;
-
-
-
-
-
-
-
-
-
-
-
-
2975 {
"deposit must change depositor shares"},
-
-
-
-
-
-
2981 args(
A2.id(), 10, [&](Adjustements& sample) {
-
2982 sample.accountShares->amount = 0;
-
-
-
-
-
-
-
-
-
-
-
-
2994 {
"deposit must change vault shares"},
-
-
-
-
-
-
3000 args(
A2.id(), 10, [&](Adjustements& sample) {
-
3001 sample.sharesTotal = 0;
-
-
-
-
-
-
-
-
-
-
-
-
3013 {
"deposit must increase depositor shares",
-
3014 "deposit must change depositor and vault shares by equal amount",
-
3015 "deposit must not change vault balance by more than deposited "
-
-
-
-
-
-
-
3022 args(
A2.id(), 10, [&](Adjustements& sample) {
-
3023 sample.accountShares->amount = -5;
-
3024 sample.sharesTotal = -10;
-
-
-
-
-
-
-
-
-
-
-
-
3036 {
"deposit and assets outstanding must add up",
-
3037 "deposit and assets available must add up"},
-
-
-
-
-
-
3043 args(
A2.id(), 10, [&](Adjustements& sample) {
-
3044 sample.assetsTotal = 7;
-
3045 sample.assetsAvailable = 7;
-
-
-
-
-
-
-
-
-
-
-
-
-
3058 {
"withdrawal must change vault balance"},
-
-
-
-
-
-
3064 args(
A2.id(), 0, [&](Adjustements& sample) {}));
-
-
-
-
-
-
-
-
-
-
-
-
3076 {
"withdrawal must change one destination balance"},
-
-
-
-
-
-
-
-
3084 (*sleA4)[sfBalance] = *(*sleA4)[sfBalance] + 10;
-
-
-
-
-
-
3090 args(A3.id(), -10, [&](Adjustements& sample) {
-
3091 sample.accountAssets->amount = -100;
-
-
-
-
-
-
-
-
3099 tx[sfAccount] = A3.id();
-
-
-
-
-
-
-
-
3107 {
"withdrawal must change vault and destination balance by "
-
-
3109 "withdrawal must decrease vault balance",
-
3110 "withdrawal must increase destination balance",
-
3111 "withdrawal and assets outstanding must add up",
-
3112 "withdrawal and assets available must add up"},
-
-
-
-
-
-
-
-
3120 (*sleA3)[sfBalance] = *(*sleA3)[sfBalance] + 10;
-
-
-
-
-
-
3126 args(
A2.id(), -10, [&](Adjustements& sample) {
-
3127 sample.vaultAssets = 10;
-
3128 sample.accountAssets->amount = -20;
-
-
-
-
-
-
-
-
-
-
3138 {
"withdrawal must change one destination balance"},
-
-
-
-
-
-
3144 args(
A2.id(), -10, [&](Adjustements& sample) {
-
3145 *sample.vaultAssets -= 5;
-
-
-
-
-
-
3151 (*sleA3)[sfBalance] = *(*sleA3)[sfBalance] + 5;
-
-
-
-
-
-
-
-
-
-
-
-
-
3164 {
"withdrawal must change depositor shares"},
-
-
-
-
-
-
3170 args(
A2.id(), -10, [&](Adjustements& sample) {
-
3171 sample.accountShares->amount = 0;
-
-
-
-
-
-
-
-
-
-
3181 {
"withdrawal must change vault shares"},
-
-
-
-
-
-
3187 args(
A2.id(), -10, [&](Adjustements& sample) {
-
3188 sample.sharesTotal = 0;
-
-
-
-
+
1895 {.depositor = A2, .id = keylet.key, .amount = XRP(10)}));
+
+
1897 {.depositor = A3, .id = keylet.key, .amount = XRP(10)}));
+
+
+
+
1901 testcase <<
"Vault general checks";
+
+
1903 {
"vault deletion succeeded without deleting a vault"},
+
+
+
1906 auto sleVault = ac.view().
peek(keylet);
+
+
+
1909 ac.view().
update(sleVault);
+
+
+
+
+
+
+
+
1917 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
+
+
+
1923 {
"vault updated by a wrong transaction type"},
+
+
+
1926 auto sleVault = ac.view().
peek(keylet);
+
+
+
1929 ac.view().
erase(sleVault);
+
+
+
+
+
+
+
+
1937 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
+
+
+
1943 {
"vault updated by a wrong transaction type"},
+
+
+
1946 auto sleVault = ac.view().
peek(keylet);
+
+
+
1949 ac.view().
update(sleVault);
+
+
+
+
+
+
+
+
1957 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
+
+
+
1963 {
"vault updated by a wrong transaction type"},
+
+
1965 auto const sequence = ac.view().
seq();
+
+
+
1968 auto const vaultPage = ac.view().
dirInsert(
+
+
+
+
1972 sleVault->setFieldU64(sfOwnerNode, *vaultPage);
+
1973 ac.view().
insert(sleVault);
+
+
+
+
+
+
+
+
1981 {
"vault deleted by a wrong transaction type"},
+
+
+
1984 auto sleVault = ac.view().
peek(keylet);
+
+
+
1987 ac.view().
erase(sleVault);
+
+
+
+
+
+
+
+
1995 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
+
+
+
2001 {
"vault operation updated more than single vault"},
+
+
+
+
2005 auto sleVault = ac.view().
peek(keylet);
+
+
+
2008 ac.view().
erase(sleVault);
+
+
+
+
2012 auto sleVault = ac.view().
peek(keylet);
+
+
+
2015 ac.view().
erase(sleVault);
+
+
+
+
+
+
+
+
+
+
+
2026 vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
+
+
2031 vault.create({.owner =
A2, .asset =
xrpIssue()});
+
+
+
+
+
+
+
2038 {
"vault operation updated more than single vault"},
+
+
2040 auto const sequence = ac.view().
seq();
+
2041 auto const insertVault = [&](
Account const A) {
+
+
+
2044 auto const vaultPage = ac.view().
dirInsert(
+
+
+
+
2048 sleVault->setFieldU64(sfOwnerNode, *vaultPage);
+
2049 ac.view().
insert(sleVault);
+
+
+
+
+
+
+
+
+
+
+
2060 {
"deleted vault must also delete shares"},
+
+
+
2063 auto sleVault = ac.view().
peek(keylet);
+
+
+
2066 ac.view().
erase(sleVault);
+
+
+
+
+
+
+
+
2074 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
+
+
+
2080 {
"deleted vault must have no shares outstanding",
+
2081 "deleted vault must have no assets outstanding",
+
2082 "deleted vault must have no assets available"},
+
+
+
2085 auto sleVault = ac.view().
peek(keylet);
+
+
+
2088 auto sleShares = ac.view().
peek(
+
+
+
+
2092 ac.view().
erase(sleVault);
+
2093 ac.view().
erase(sleShares);
+
+
+
+
+
+
+
+
+
2102 vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
2105 {.depositor = A1, .id = keylet.key, .amount = XRP(10)}));
+
+
+
+
+
2110 {
"vault operation succeeded without modifying a vault"},
+
+
+
2113 auto sleVault = ac.view().
peek(keylet);
+
+
+
2116 auto sleShares = ac.view().
peek(
+
+
+
+
+
+
2122 sleShares->setFieldH256(sfDomainID,
uint256(13));
+
2123 ac.view().
update(sleShares);
+
+
+
+
+
+
+
+
+
+
2133 {
"vault operation succeeded without modifying a vault"},
+
+
+
+
+
+
+
+
+
2142 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
+
+
+
2148 {
"vault operation succeeded without modifying a vault"},
+
+
+
+
+
+
+
+
+
2157 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
+
+
+
2163 {
"vault operation succeeded without modifying a vault"},
+
+
+
+
+
+
+
+
+
2172 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
+
+
+
2178 {
"vault operation succeeded without modifying a vault"},
+
+
+
+
+
+
+
+
+
2187 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
+
+
+
2193 {
"vault operation succeeded without modifying a vault"},
+
+
+
+
+
+
+
+
+
2202 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
+
+
+
2208 {
"updated vault must have shares"},
+
+
+
2211 auto sleVault = ac.view().
peek(keylet);
+
+
+
2214 (*sleVault)[sfAssetsMaximum] = 200;
+
2215 ac.view().
update(sleVault);
+
+
2217 auto sleShares = ac.view().
peek(
+
+
+
+
2221 ac.view().
erase(sleShares);
+
+
+
+
+
+
+
+
2229 auto [tx, _] = vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
+
+
+
2235 {
"vault operation succeeded without updating shares",
+
2236 "assets available must not be greater than assets outstanding"},
+
+
+
2239 auto sleVault = ac.view().
peek(keylet);
+
+
+
2242 (*sleVault)[sfAssetsTotal] = 9;
+
2243 ac.view().
update(sleVault);
+
+
+
+
+
+
+
+
+
2252 vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
2255 {.depositor = A1, .id = keylet.key, .amount = XRP(10)}));
+
+
+
+
+
2260 {
"set must not change assets outstanding",
+
2261 "set must not change assets available",
+
2262 "set must not change shares outstanding",
+
2263 "set must not change vault balance",
+
2264 "assets available must be positive",
+
2265 "assets available must not be greater than assets outstanding",
+
2266 "assets outstanding must be positive"},
+
+
+
2269 auto sleVault = ac.view().
peek(keylet);
+
+
+
2272 auto slePseudoAccount =
+
+
2274 if (!slePseudoAccount)
+
+
2276 (*slePseudoAccount)[sfBalance] =
+
2277 *(*slePseudoAccount)[sfBalance] - 10;
+
2278 ac.view().
update(slePseudoAccount);
+
+
+
+
+
+
2284 (*sleA4)[sfBalance] = *(*sleA4)[sfBalance] + 10;
+
+
+
+
+
+
2290 args(
A2.id(), 0, [&](Adjustments& sample) {
+
2291 sample.assetsAvailable = (DROPS_PER_XRP * -100).value();
+
2292 sample.assetsTotal = (DROPS_PER_XRP * -200).value();
+
2293 sample.sharesTotal = -1;
+
+
+
+
+
+
+
+
+
+
2303 {
"violation of vault immutable data"},
+
+
+
2306 auto sleVault = ac.view().
peek(keylet);
+
+
+
2309 sleVault->setFieldIssue(
+
+
2311 ac.view().
update(sleVault);
+
+
+
+
+
+
+
+
+
2320 {
"violation of vault immutable data"},
+
+
+
2323 auto sleVault = ac.view().
peek(keylet);
+
+
+
2326 sleVault->setAccountID(sfAccount,
A2.id());
+
2327 ac.view().
update(sleVault);
+
+
+
+
+
+
+
+
+
2336 {
"violation of vault immutable data"},
+
+
+
2339 auto sleVault = ac.view().
peek(keylet);
+
+
+
2342 (*sleVault)[sfShareMPTID] =
MPTID(42);
+
2343 ac.view().
update(sleVault);
+
+
+
+
+
+
+
+
+
2352 {
"vault transaction must not change loss unrealized",
+
2353 "set must not change assets outstanding"},
+
+
+
+
+
+
2359 args(
A2.id(), 0, [&](Adjustments& sample) {
+
2360 sample.lossUnrealized = 13;
+
2361 sample.assetsTotal = 20;
+
+
+
+
+
+
+
+
+
+
2371 {
"loss unrealized must not exceed the difference "
+
2372 "between assets outstanding and available",
+
2373 "vault transaction must not change loss unrealized"},
+
+
+
+
+
+
2379 args(
A2.id(), 100, [&](Adjustments& sample) {
+
2380 sample.lossUnrealized = 13;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2394 {
"set assets outstanding must not exceed assets maximum"},
+
+
+
+
+
+
2400 args(
A2.id(), 0, [&](Adjustments& sample) {
+
2401 sample.assetsMaximum = 1;
+
+
+
+
+
+
+
+
+
+
2411 {
"assets maximum must be positive"},
+
+
+
+
+
+
2417 args(
A2.id(), 0, [&](Adjustments& sample) {
+
2418 sample.assetsMaximum = -1;
+
+
+
+
+
+
+
+
+
+
2428 {
"set must not change shares outstanding",
+
2429 "updated zero sized vault must have no assets outstanding",
+
2430 "updated zero sized vault must have no assets available"},
+
+
+
2433 auto sleVault = ac.view().
peek(keylet);
+
+
+
2436 ac.view().
update(sleVault);
+
2437 auto sleShares = ac.view().
peek(
+
+
+
+
2441 (*sleShares)[sfOutstandingAmount] = 0;
+
2442 ac.view().
update(sleShares);
+
+
+
+
+
+
+
+
+
+
2452 {
"updated shares must not exceed maximum"},
+
+
+
2455 auto sleVault = ac.view().
peek(keylet);
+
+
+
2458 auto sleShares = ac.view().
peek(
+
+
+
+
2462 (*sleShares)[sfMaximumAmount] = 10;
+
2463 ac.view().
update(sleShares);
+
+
+
2466 ac.view(), keylet, args(
A2.id(), 10, [](Adjustments&) {}));
+
+
+
+
+
+
+
+
+
2475 {
"updated shares must not exceed maximum"},
+
+
+
+
2479 ac.view(), keylet, args(
A2.id(), 10, [](Adjustments&) {}));
+
+
2481 auto sleVault = ac.view().
peek(keylet);
+
+
+
2484 auto sleShares = ac.view().
peek(
+
+
+
+
+
2489 ac.view().
update(sleShares);
+
+
+
+
+
+
+
+
+
+
+
+
2501 "created vault must be empty",
+
2502 "updated zero sized vault must have no assets outstanding",
+
2503 "create operation must not have updated a vault",
+
+
+
+
2507 auto sleVault = ac.view().
peek(keylet);
+
+
+
2510 (*sleVault)[sfAssetsTotal] = 9;
+
2511 ac.view().
update(sleVault);
+
+
+
+
+
+
+
+
+
2520 vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
+
+
+
+
2527 "created vault must be empty",
+
2528 "updated zero sized vault must have no assets available",
+
2529 "assets available must not be greater than assets outstanding",
+
2530 "create operation must not have updated a vault",
+
+
+
+
2534 auto sleVault = ac.view().
peek(keylet);
+
+
+
2537 (*sleVault)[sfAssetsAvailable] = 9;
+
2538 ac.view().
update(sleVault);
+
+
+
+
+
+
+
+
+
2547 vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
+
+
+
+
2554 "created vault must be empty",
+
2555 "loss unrealized must not exceed the difference between assets "
+
2556 "outstanding and available",
+
2557 "vault transaction must not change loss unrealized",
+
2558 "create operation must not have updated a vault",
+
+
+
+
2562 auto sleVault = ac.view().
peek(keylet);
+
+
+
2565 (*sleVault)[sfLossUnrealized] = 1;
+
2566 ac.view().
update(sleVault);
+
+
+
+
+
+
+
+
+
2575 vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
+
+
+
+
2582 "created vault must be empty",
+
2583 "create operation must not have updated a vault",
+
+
+
+
2587 auto sleVault = ac.view().
peek(keylet);
+
+
+
2590 auto sleShares = ac.view().
peek(
+
+
+
+
2594 ac.view().
update(sleVault);
+
2595 (*sleShares)[sfOutstandingAmount] = 9;
+
2596 ac.view().
update(sleShares);
+
+
+
+
+
+
+
+
+
2605 vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
+
+
+
+
2612 "assets maximum must be positive",
+
2613 "create operation must not have updated a vault",
+
+
+
+
2617 auto sleVault = ac.view().
peek(keylet);
+
+
+
2620 (*sleVault)[sfAssetsMaximum] =
Number(-1);
+
2621 ac.view().
update(sleVault);
+
+
+
+
+
+
+
+
+
2630 vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
+
+
+
2636 {
"create operation must not have updated a vault",
+
2637 "shares issuer and vault pseudo-account must be the same",
+
2638 "shares issuer must be a pseudo-account",
+
2639 "shares issuer pseudo-account must point back to the vault"},
+
+
+
2642 auto sleVault = ac.view().
peek(keylet);
+
+
+
2645 auto sleShares = ac.view().
peek(
+
+
+
+
2649 ac.view().
update(sleVault);
+
2650 (*sleShares)[sfIssuer] =
A1.id();
+
2651 ac.view().
update(sleShares);
+
+
+
+
+
+
+
+
+
2660 vault.create({.owner =
A1, .asset =
xrpIssue()});
+
+
+
+
+
+
2666 {
"vault created by a wrong transaction type",
+
2667 "account root created illegally"},
+
+
+
+
+
2672 auto const sequence = ac.view().
seq();
+
+
+
2675 auto const vaultPage = ac.view().
dirInsert(
+
+
+
+
2679 sleVault->setFieldU64(sfOwnerNode, *vaultPage);
+
+
+
+
+
+
+
2686 sleAccount->setAccountID(sfAccount, pseudoId);
+
2687 sleAccount->setFieldAmount(sfBalance,
STAmount{});
+
+
+
+
+
2692 sleAccount->setFieldU32(sfSequence, seqno);
+
2693 sleAccount->setFieldU32(
+
+
+
2696 sleAccount->setFieldH256(sfVaultID, vaultKeylet.key);
+
2697 ac.view().
insert(sleAccount);
+
+
2699 auto const sharesMptId =
makeMptID(sequence, pseudoId);
+
+
+
2702 auto const sharesPage = ac.view().
dirInsert(
+
+
+
+
2706 sleShares->setFieldU64(sfOwnerNode, *sharesPage);
+
+
2708 sleShares->at(sfFlags) = 0;
+
2709 sleShares->at(sfIssuer) = pseudoId;
+
2710 sleShares->at(sfOutstandingAmount) = 0;
+
2711 sleShares->at(sfSequence) = sequence;
+
+
2713 sleVault->at(sfAccount) = pseudoId;
+
2714 sleVault->at(sfFlags) = 0;
+
2715 sleVault->at(sfSequence) = sequence;
+
2716 sleVault->at(sfOwner) =
A1.id();
+
2717 sleVault->at(sfAssetsTotal) =
Number(0);
+
2718 sleVault->at(sfAssetsAvailable) =
Number(0);
+
2719 sleVault->at(sfLossUnrealized) =
Number(0);
+
2720 sleVault->at(sfShareMPTID) = sharesMptId;
+
2721 sleVault->at(sfWithdrawalPolicy) =
+
+
+
2724 ac.view().
insert(sleVault);
+
2725 ac.view().
insert(sleShares);
+
+
+
+
+
+
+
+
2733 {
"shares issuer and vault pseudo-account must be the same",
+
2734 "shares issuer pseudo-account must point back to the vault"},
+
+
2736 auto const sequence = ac.view().
seq();
+
+
+
2739 auto const vaultPage = ac.view().
dirInsert(
+
+
+
+
2743 sleVault->setFieldU64(sfOwnerNode, *vaultPage);
+
+
+
+
+
+
+
2750 sleAccount->setAccountID(sfAccount, pseudoId);
+
2751 sleAccount->setFieldAmount(sfBalance,
STAmount{});
+
+
+
+
+
2756 sleAccount->setFieldU32(sfSequence, seqno);
+
2757 sleAccount->setFieldU32(
+
+
+
+
+
2762 sleAccount->setFieldH256(sfVaultID,
uint256(42));
+
2763 ac.view().
insert(sleAccount);
+
+
2765 auto const sharesMptId =
makeMptID(sequence, pseudoId);
+
+
+
2768 auto const sharesPage = ac.view().
dirInsert(
+
+
+
+
2772 sleShares->setFieldU64(sfOwnerNode, *sharesPage);
+
+
2774 sleShares->at(sfFlags) = 0;
+
2775 sleShares->at(sfIssuer) = pseudoId;
+
2776 sleShares->at(sfOutstandingAmount) = 0;
+
2777 sleShares->at(sfSequence) = sequence;
+
+
+
+
2781 sleVault->at(sfAccount) =
A2.id();
+
2782 sleVault->at(sfFlags) = 0;
+
2783 sleVault->at(sfSequence) = sequence;
+
2784 sleVault->at(sfOwner) =
A1.id();
+
2785 sleVault->at(sfAssetsTotal) =
Number(0);
+
2786 sleVault->at(sfAssetsAvailable) =
Number(0);
+
2787 sleVault->at(sfLossUnrealized) =
Number(0);
+
2788 sleVault->at(sfShareMPTID) = sharesMptId;
+
2789 sleVault->at(sfWithdrawalPolicy) =
+
+
+
2792 ac.view().
insert(sleVault);
+
2793 ac.view().
insert(sleShares);
+
+
+
+
+
+
+
+
2801 {
"shares issuer and vault pseudo-account must be the same",
+
2802 "shares issuer must exist"},
+
+
2804 auto const sequence = ac.view().
seq();
+
+
+
2807 auto const vaultPage = ac.view().
dirInsert(
+
+
+
+
2811 sleVault->setFieldU64(sfOwnerNode, *vaultPage);
+
+
2813 auto const sharesMptId =
makeMptID(sequence,
A2.id());
+
+
+
2816 auto const sharesPage = ac.view().
dirInsert(
+
+
+
+
2820 sleShares->setFieldU64(sfOwnerNode, *sharesPage);
+
+
2822 sleShares->at(sfFlags) = 0;
+
+
+
2825 sleShares->at(sfOutstandingAmount) = 0;
+
2826 sleShares->at(sfSequence) = sequence;
+
+
2828 sleVault->at(sfAccount) =
A2.id();
+
2829 sleVault->at(sfFlags) = 0;
+
2830 sleVault->at(sfSequence) = sequence;
+
2831 sleVault->at(sfOwner) =
A1.id();
+
2832 sleVault->at(sfAssetsTotal) =
Number(0);
+
2833 sleVault->at(sfAssetsAvailable) =
Number(0);
+
2834 sleVault->at(sfLossUnrealized) =
Number(0);
+
2835 sleVault->at(sfShareMPTID) = sharesMptId;
+
2836 sleVault->at(sfWithdrawalPolicy) =
+
+
+
2839 ac.view().
insert(sleVault);
+
2840 ac.view().
insert(sleShares);
+
+
+
+
+
+
+
+
+
2849 {
"deposit must change vault balance"},
+
+
+
+
+
+
2855 args(
A2.id(), 0, [](Adjustments& sample) {
+
2856 sample.vaultAssets.reset();
+
+
+
+
+
+
+
+
+
2865 {
"deposit assets outstanding must not exceed assets maximum"},
+
+
+
+
+
+
2871 args(
A2.id(), 200, [&](Adjustments& sample) {
+
2872 sample.assetsMaximum = 1;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2890 {
"deposit must increase vault balance",
+
2891 "deposit must change depositor balance"},
+
+
+
+
+
+
+
+
2899 (*sleA4)[sfBalance] = *(*sleA4)[sfBalance] + 10;
+
+
+
+
+
+
2905 args(A3.id(), -10, [&](Adjustments& sample) {
+
2906 sample.accountAssets->amount = -100;
+
+
+
+
+
+
+
+
2914 tx[sfAccount] = A3.id();
+
+
+
+
+
+
2920 {
"deposit must increase vault balance",
+
2921 "deposit must decrease depositor balance",
+
2922 "deposit must change vault and depositor balance by equal amount",
+
2923 "deposit and assets outstanding must add up",
+
2924 "deposit and assets available must add up"},
+
+
+
+
+
+
+
+
2932 (*sleA3)[sfBalance] = *(*sleA3)[sfBalance] + 10;
+
+
+
+
+
+
2938 args(
A2.id(), 10, [&](Adjustments& sample) {
+
2939 sample.vaultAssets = -20;
+
2940 sample.accountAssets->amount = 10;
+
+
+
+
+
+
+
+
+
+
+
+
2952 {
"deposit must change depositor balance"},
+
+
+
+
+
+
+
+
2960 (*sleA3)[sfBalance] = *(*sleA3)[sfBalance] - 10;
+
+
+
+
+
+
2966 args(
A2.id(), 10, [&](Adjustments& sample) {
+
2967 sample.accountAssets->amount = 0;
+
+
+
+
+
+
+
+
+
+
+
+
2979 {
"deposit must change depositor shares"},
+
+
+
+
+
+
2985 args(
A2.id(), 10, [&](Adjustments& sample) {
+
2986 sample.accountShares.reset();
+
+
+
+
+
+
+
+
+
+
+
+
2998 {
"deposit must change vault shares"},
+
+
+
+
+
+
+
3005 args(
A2.id(), 10, [](Adjustments& sample) {
+
3006 sample.sharesTotal = 0;
+
+
+
+
+
+
+
+
+
+
+
+
3018 {
"deposit must increase depositor shares",
+
3019 "deposit must change depositor and vault shares by equal amount",
+
3020 "deposit must not change vault balance by more than deposited "
+
+
+
+
+
+
+
3027 args(
A2.id(), 10, [&](Adjustments& sample) {
+
3028 sample.accountShares->amount = -5;
+
3029 sample.sharesTotal = -10;
+
+
+
+
+
+
+
+
+
+
+
+
3041 {
"deposit and assets outstanding must add up"},
+
+
+
3044 (*sleA3)[sfBalance] = *(*sleA3)[sfBalance] - 2000;
+
+
+
+
+
+
+
3051 args(
A2.id(), 10, [&](Adjustments& sample) {
+
3052 sample.assetsTotal = 11;
+
+
+
+
+
+
+
+
3060 tx[sfDelegate] = A3.id();
+
+
+
+
+
+
+
+
3068 {
"deposit and assets outstanding must add up",
+
3069 "deposit and assets available must add up"},
+
+
+
+
+
+
3075 args(
A2.id(), 10, [&](Adjustments& sample) {
+
3076 sample.assetsTotal = 7;
+
3077 sample.assetsAvailable = 7;
+
+
+
+
+
+
+
+
+
+
+
+
+
3090 {
"withdrawal must change vault balance"},
+
+
+
+
+
+
3096 args(
A2.id(), 0, [](Adjustments& sample) {
+
3097 sample.vaultAssets.reset();
+
+
+
+
+
+
+
+
+
+
+
+
+
3110 {
"withdrawal must change one destination balance"},
+
+
+
+
+
+
+
+
3118 (*sleA4)[sfBalance] = *(*sleA4)[sfBalance] + 10;
+
+
+
+
+
+
3124 args(A3.id(), -10, [&](Adjustments& sample) {
+
3125 sample.accountAssets->amount = -100;
+
+
+
+
+
+
+
+
3133 tx[sfAccount] = A3.id();
+
+
+
+
+
+
+
+
3141 {
"withdrawal must change vault and destination balance by "
+
+
3143 "withdrawal must decrease vault balance",
+
3144 "withdrawal must increase destination balance",
+
3145 "withdrawal and assets outstanding must add up",
+
3146 "withdrawal and assets available must add up"},
+
+
+
+
+
+
+
+
3154 (*sleA3)[sfBalance] = *(*sleA3)[sfBalance] + 10;
+
+
+
+
+
+
3160 args(
A2.id(), -10, [&](Adjustments& sample) {
+
3161 sample.vaultAssets = 10;
+
3162 sample.accountAssets->amount = -20;
+
+
+
+
+
+
+
+
+
+
3172 {
"withdrawal must change one destination balance"},
+
+
+
+
+
+
3178 args(
A2.id(), -10, [&](Adjustments& sample) {
+
3179 *sample.vaultAssets -= 5;
+
+
+
+
+
+
3185 (*sleA3)[sfBalance] = *(*sleA3)[sfBalance] + 5;
+
+
+
+
+
+
+
-
3198 {
"withdrawal must decrease depositor shares",
-
3199 "withdrawal must change depositor and vault shares by equal "
-
-
-
-
-
-
-
3206 args(
A2.id(), -10, [&](Adjustements& sample) {
-
3207 sample.accountShares->amount = 5;
-
3208 sample.sharesTotal = 10;
-
-
-
-
-
-
-
-
-
-
3218 {
"withdrawal and assets outstanding must add up",
-
3219 "withdrawal and assets available must add up"},
-
-
-
-
-
-
3225 args(
A2.id(), -10, [&](Adjustements& sample) {
-
3226 sample.assetsTotal = -15;
-
3227 sample.assetsAvailable = -15;
-
-
-
-
-
-
-
-
-
3236 auto const precloseMpt =
-
-
3238 env.fund(
XRP(1000), A3, A4);
-
-
-
-
-
3243 jv[sfAccount] = A3.human();
-
3244 jv[sfTransactionType] = jss::MPTokenIssuanceCreate;
-
-
-
-
-
-
3250 auto const mptID =
makeMptID(env.seq(A3) - 1, A3);
-
-
-
-
-
3255 jv[sfAccount] =
A1.human();
-
3256 jv[sfTransactionType] = jss::MPTokenAuthorize;
-
3257 jv[sfMPTokenIssuanceID] =
to_string(mptID);
-
-
3259 jv[sfAccount] =
A2.human();
-
-
3261 jv[sfAccount] = A4.human();
-
-
-
-
-
-
-
3268 env(
pay(A3,
A1, asset(1000)));
-
3269 env(
pay(A3,
A2, asset(1000)));
-
3270 env(
pay(A3, A4, asset(1000)));
-
-
-
-
-
3275 auto [tx, keylet] = vault.create({.owner =
A1, .asset = asset});
-
-
-
3278 {.depositor = A1, .id = keylet.key, .amount = asset(10)}));
-
-
3280 {.depositor = A2, .id = keylet.key, .amount = asset(10)}));
-
-
3282 {.depositor = A4, .id = keylet.key, .amount = asset(10)}));
-
-
-
-
-
3287 {
"withdrawal must decrease depositor shares",
-
3288 "withdrawal must change depositor and vault shares by equal "
-
-
-
-
-
-
-
3295 args(
A2.id(), -10, [&](Adjustements& sample) {
-
3296 sample.accountShares->amount = 5;
-
-
-
-
-
-
3302 [&](
STObject& tx) { tx[sfAccount] = A3.id(); }},
-
-
-
-
-
-
-
3309 {
"clawback must change vault balance"},
-
-
-
-
-
-
3315 args(
A2.id(), -1, [&](Adjustements& sample) {
-
3316 sample.vaultAssets = 0;
-
-
-
-
-
-
3322 [&](
STObject& tx) { tx[sfAccount] = A3.id(); }},
-
-
-
-
-
-
3328 {
"clawback may only be performed by the asset issuer"},
-
-
-
-
-
-
3334 args(
A2.id(), 0, [&](Adjustements& sample) {}));
-
-
-
-
-
-
-
-
-
3343 {
"clawback may only be performed by the asset issuer"},
-
-
-
-
-
-
3349 args(
A2.id(), 0, [&](Adjustements& sample) {}));
-
-
-
-
-
3354 [&](
STObject& tx) { tx[sfAccount] = A4.id(); }},
-
-
-
-
-
3359 {
"clawback must decrease vault balance",
-
3360 "clawback must decrease holder shares",
-
3361 "clawback must change vault shares"},
-
-
-
-
-
-
3367 args(A4.id(), 10, [&](Adjustements& sample) {
-
3368 sample.sharesTotal = 0;
-
-
-
-
-
-
-
3375 tx[sfAccount] = A3.id();
-
3376 tx[sfHolder] = A4.id();
-
-
-
-
-
-
3382 {
"clawback must change holder shares"},
-
-
-
-
-
-
3388 args(A4.id(), -10, [&](Adjustements& sample) {
-
3389 sample.accountShares->amount = 0;
-
-
-
-
-
-
-
3396 tx[sfAccount] = A3.id();
-
3397 tx[sfHolder] = A4.id();
-
+
3198 {
"withdrawal must change depositor shares"},
+
+
+
+
+
+
3204 args(
A2.id(), -10, [&](Adjustments& sample) {
+
3205 sample.accountShares.reset();
+
+
+
+
+
+
+
+
+
+
3215 {
"withdrawal must change vault shares"},
+
+
+
+
+
+
3221 args(
A2.id(), -10, [](Adjustments& sample) {
+
3222 sample.sharesTotal = 0;
+
+
+
+
+
+
+
+
+
+
3232 {
"withdrawal must decrease depositor shares",
+
3233 "withdrawal must change depositor and vault shares by equal "
+
+
+
+
+
+
+
3240 args(
A2.id(), -10, [&](Adjustments& sample) {
+
3241 sample.accountShares->amount = 5;
+
3242 sample.sharesTotal = 10;
+
+
+
+
+
+
+
+
+
+
3252 {
"withdrawal and assets outstanding must add up",
+
3253 "withdrawal and assets available must add up"},
+
+
+
+
+
+
3259 args(
A2.id(), -10, [&](Adjustments& sample) {
+
3260 sample.assetsTotal = -15;
+
3261 sample.assetsAvailable = -15;
+
+
+
+
+
+
+
+
+
+
3271 {
"withdrawal and assets outstanding must add up"},
+
+
+
3274 (*sleA3)[sfBalance] = *(*sleA3)[sfBalance] - 2000;
+
+
+
+
+
+
+
3281 args(
A2.id(), -10, [&](Adjustments& sample) {
+
3282 sample.assetsTotal = -7;
+
+
+
+
+
+
+
+
3290 tx[sfDelegate] = A3.id();
+
+
+
+
+
+
+
3297 auto const precloseMpt =
+
+
3299 env.fund(
XRP(1000), A3, A4);
+
+
+
+
+
3304 jv[sfAccount] = A3.human();
+
3305 jv[sfTransactionType] = jss::MPTokenIssuanceCreate;
+
+
+
+
+
+
3311 auto const mptID =
makeMptID(env.seq(A3) - 1, A3);
+
+
+
+
+
3316 jv[sfAccount] =
A1.human();
+
3317 jv[sfTransactionType] = jss::MPTokenAuthorize;
+
3318 jv[sfMPTokenIssuanceID] =
to_string(mptID);
+
+
3320 jv[sfAccount] =
A2.human();
+
+
3322 jv[sfAccount] = A4.human();
+
+
+
+
+
+
+
3329 env(
pay(A3,
A1, asset(1000)));
+
3330 env(
pay(A3,
A2, asset(1000)));
+
3331 env(
pay(A3, A4, asset(1000)));
+
+
+
+
+
3336 auto [tx, keylet] = vault.create({.owner =
A1, .asset = asset});
+
+
+
3339 {.depositor = A1, .id = keylet.key, .amount = asset(10)}));
+
+
3341 {.depositor = A2, .id = keylet.key, .amount = asset(10)}));
+
+
3343 {.depositor = A4, .id = keylet.key, .amount = asset(10)}));
+
+
+
+
+
3348 {
"withdrawal must decrease depositor shares",
+
3349 "withdrawal must change depositor and vault shares by equal "
+
+
+
+
+
+
+
3356 args(
A2.id(), -10, [&](Adjustments& sample) {
+
3357 sample.accountShares->amount = 5;
+
+
+
+
+
+
3363 [&](
STObject& tx) { tx[sfAccount] = A3.id(); }},
+
+
+
+
+
+
+
3370 {
"clawback must change vault balance"},
+
+
+
+
+
+
3376 args(
A2.id(), -1, [&](Adjustments& sample) {
+
3377 sample.vaultAssets.reset();
+
+
+
+
+
+
3383 [&](
STObject& tx) { tx[sfAccount] = A3.id(); }},
+
+
+
+
+
+
3389 {
"clawback may only be performed by the asset issuer"},
+
+
+
+
+
+
3395 args(
A2.id(), 0, [&](Adjustments& sample) {}));
+
+
+
-
+
-
-
3403 {
"clawback must change holder and vault shares by equal amount",
-
3404 "clawback and assets outstanding must add up",
-
3405 "clawback and assets available must add up"},
-
-
-
-
-
-
3411 args(A4.id(), -10, [&](Adjustements& sample) {
-
3412 sample.accountShares->amount = -8;
-
3413 sample.assetsTotal = -7;
-
3414 sample.assetsAvailable = -7;
-
-
-
-
-
-
-
3421 tx[sfAccount] = A3.id();
-
3422 tx[sfHolder] = A4.id();
-
-
-
-
+
+
+
3404 {
"clawback may only be performed by the asset issuer"},
+
+
+
+
+
+
3410 args(
A2.id(), 0, [&](Adjustments& sample) {}));
+
+
+
+
+
3415 [&](
STObject& tx) { tx[sfAccount] = A4.id(); }},
+
+
+
+
+
3420 {
"clawback must decrease vault balance",
+
3421 "clawback must decrease holder shares",
+
3422 "clawback must change vault shares"},
+
+
+
+
+
+
3428 args(A4.id(), 10, [&](Adjustments& sample) {
+
3429 sample.sharesTotal = 0;
+
+
+
+
+
+
+
3436 tx[sfAccount] = A3.id();
+
3437 tx[sfHolder] = A4.id();
+
+
+
+
+
+
3443 {
"clawback must change holder shares"},
+
+
+
+
+
+
3449 args(A4.id(), -10, [&](Adjustments& sample) {
+
3450 sample.accountShares.reset();
+
+
+
+
+
+
+
3457 tx[sfAccount] = A3.id();
+
3458 tx[sfHolder] = A4.id();
+
+
+
+
+
+
3464 {
"clawback must change holder and vault shares by equal amount",
+
3465 "clawback and assets outstanding must add up",
+
3466 "clawback and assets available must add up"},
+
+
+
+
+
+
3472 args(A4.id(), -10, [&](Adjustments& sample) {
+
3473 sample.accountShares->amount = -8;
+
3474 sample.assetsTotal = -7;
+
3475 sample.assetsAvailable = -7;
+
+
+
+
+
+
+
3482 tx[sfAccount] = A3.id();
+
3483 tx[sfHolder] = A4.id();
+
+
+
+
-