diff --git a/include/xrpl/ledger/View.h b/include/xrpl/ledger/View.h index 4958a89d8c..9558c73c07 100644 --- a/include/xrpl/ledger/View.h +++ b/include/xrpl/ledger/View.h @@ -58,6 +58,12 @@ isVaultPseudoAccountFrozen( AccountID const& account, MPTIssue const& mptShare, int depth); +[[nodiscard]] bool +isVaultPseudoAccountFrozen( + ReadView const& view, + AccountID const& account, + SLE const& mptSLE, + int depth); [[nodiscard]] bool isLPTokenFrozen( diff --git a/include/xrpl/ledger/helpers/MPTokenHelpers.h b/include/xrpl/ledger/helpers/MPTokenHelpers.h index 6544b18dd1..002977c9cc 100644 --- a/include/xrpl/ledger/helpers/MPTokenHelpers.h +++ b/include/xrpl/ledger/helpers/MPTokenHelpers.h @@ -26,9 +26,15 @@ isGlobalFrozen(ReadView const& view, MPTIssue const& mptIssue); [[nodiscard]] bool isIndividualFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue); +[[nodiscard]] bool +isIndividualFrozen(ReadView const& view, AccountID const& account, SLE const& mptSLE); + [[nodiscard]] bool isFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue, int depth = 0); +[[nodiscard]] bool +isFrozen(ReadView const& view, AccountID const& account, SLE const& mptSLE, int depth = 0); + [[nodiscard]] bool isAnyFrozen( ReadView const& view, diff --git a/src/libxrpl/ledger/View.cpp b/src/libxrpl/ledger/View.cpp index 55735ec0e6..10ba4270d4 100644 --- a/src/libxrpl/ledger/View.cpp +++ b/src/libxrpl/ledger/View.cpp @@ -52,11 +52,13 @@ hasExpired(ReadView const& view, std::optional const& exp) return exp && (view.parentCloseTime() >= tp{d{*exp}}); } +template + requires(std::is_same_v || std::is_same_v) bool isVaultPseudoAccountFrozen( ReadView const& view, + T const& mptShare, AccountID const& account, - MPTIssue const& mptShare, int depth) { if (!view.rules().enabled(featureSingleAssetVault)) @@ -65,11 +67,17 @@ isVaultPseudoAccountFrozen( if (depth >= maxAssetCheckDepth) return true; // LCOV_EXCL_LINE - auto const mptIssuance = view.read(keylet::mptIssuance(mptShare.getMptID())); - if (mptIssuance == nullptr) - return false; // zero MPToken won't block deletion of MPTokenIssuance + auto const issuer = [&]() { + if constexpr (std::is_same_v) + { + return mptShare.getIssuer(); + } + if constexpr (std::is_same_v) + { + return mptShare[sfAccount]; + } + }(); - auto const issuer = mptIssuance->getAccountID(sfIssuer); auto const mptIssuer = view.read(keylet::account(issuer)); if (mptIssuer == nullptr) { @@ -82,6 +90,13 @@ isVaultPseudoAccountFrozen( if (!mptIssuer->isFieldPresent(sfVaultID)) return false; // not a Vault pseudo-account, common case + if constexpr (std::is_same_v) + { + auto const mptIssuance = view.read(keylet::mptIssuance(mptShare.getMptID())); + if (mptIssuance == nullptr) + return false; // zero MPToken won't block deletion of MPTokenIssuance + } + auto const vault = view.read(keylet::vault(mptIssuer->getFieldH256(sfVaultID))); if (vault == nullptr) { // LCOV_EXCL_START @@ -93,6 +108,26 @@ isVaultPseudoAccountFrozen( return isAnyFrozen(view, {issuer, account}, vault->at(sfAsset), depth + 1); } +bool +isVaultPseudoAccountFrozen( + ReadView const& view, + AccountID const& account, + MPTIssue const& mptShare, + int depth) +{ + return isVaultPseudoAccountFrozen(view, mptShare, account, depth); +} + +bool +isVaultPseudoAccountFrozen( + ReadView const& view, + AccountID const& account, + SLE const& mptShareSLE, + int depth) +{ + return isVaultPseudoAccountFrozen(view, mptShareSLE, account, depth); +} + bool isLPTokenFrozen( ReadView const& view, diff --git a/src/libxrpl/ledger/helpers/AMMHelpers.cpp b/src/libxrpl/ledger/helpers/AMMHelpers.cpp index 94ca2469f7..399c47a939 100644 --- a/src/libxrpl/ledger/helpers/AMMHelpers.cpp +++ b/src/libxrpl/ledger/helpers/AMMHelpers.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -598,7 +599,7 @@ ammAccountHolds(ReadView const& view, AccountID const& ammAccountID, Asset const return asset.visit( [&](MPTIssue const& issue) { if (auto const sle = view.read(keylet::mptoken(issue, ammAccountID)); - sle && !isFrozen(view, ammAccountID, issue)) + sle && !isFrozen(view, ammAccountID, *sle.get())) return STAmount{issue, (*sle)[sfMPTAmount]}; return STAmount{asset}; }, diff --git a/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp b/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp index c3987ddb03..be67a69522 100644 --- a/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp +++ b/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp @@ -54,6 +54,12 @@ isIndividualFrozen(ReadView const& view, AccountID const& account, MPTIssue cons return false; } +bool +isIndividualFrozen(ReadView const& view, AccountID const& account, SLE const& mptSLE) +{ + return mptSLE.isFlag(lsfMPTLocked); +} + bool isFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue, int depth) { @@ -61,6 +67,14 @@ isFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssu isVaultPseudoAccountFrozen(view, account, mptIssue, depth); } +bool +isFrozen(ReadView const& view, AccountID const& account, SLE const& mptSLE, int depth) +{ + MPTIssue const mptIssue{mptSLE[sfMPTokenIssuanceID]}; + return isGlobalFrozen(view, mptIssue) || isIndividualFrozen(view, account, mptSLE) || + isVaultPseudoAccountFrozen(view, account, mptSLE, depth); +} + [[nodiscard]] bool isAnyFrozen( ReadView const& view,