diff --git a/include/xrpl/ledger/helpers/TokenHelpers.h b/include/xrpl/ledger/helpers/TokenHelpers.h index 7fcdf506f5..d4a42b5d43 100644 --- a/include/xrpl/ledger/helpers/TokenHelpers.h +++ b/include/xrpl/ledger/helpers/TokenHelpers.h @@ -150,6 +150,18 @@ checkWithdrawFreezes( AccountID const& dstAcct, Asset const& asset); +/** + * Checks freeze compliance for a pseudo-account deposit. + * - The source pseudo-account is not deep frozen for the asset + * - The submitting account is not individually frozen for the asset + */ +[[nodiscard]] TER +checkDepositFreeze( + ReadView const& view, + AccountID const& sourceAcct, + AccountID const& dstAcct, + Asset const& asset); + //------------------------------------------------------------------------------ // // Account balance functions (Asset-based dispatchers) diff --git a/src/libxrpl/ledger/helpers/TokenHelpers.cpp b/src/libxrpl/ledger/helpers/TokenHelpers.cpp index b88820e12f..131e7a3e18 100644 --- a/src/libxrpl/ledger/helpers/TokenHelpers.cpp +++ b/src/libxrpl/ledger/helpers/TokenHelpers.cpp @@ -167,13 +167,13 @@ checkDeepFrozen(ReadView const& view, AccountID const& account, Asset const& ass TER checkWithdrawFreezes( ReadView const& view, - AccountID const& sourceAcct, + AccountID const& srcAcct, AccountID const& submitterAcct, AccountID const& dstAcct, Asset const& asset) { XRPL_ASSERT( - isPseudoAccount(view, sourceAcct), + isPseudoAccount(view, srcAcct), "xrpl::checkWithdrawFreezes : source must be a pseudo-account"); // No matter what, funds can be sent to the issuer @@ -182,16 +182,39 @@ checkWithdrawFreezes( // The transfer is from Submitter to Destination via Source (pseudo-account) // Both Source and Submitter must not be frozen to allow sending funds - if (auto const ret = checkFrozen(view, sourceAcct, asset)) + if (auto const ret = checkFrozen(view, srcAcct, asset)) return ret; - if (auto const ret = checkFrozen(view, submitterAcct, asset)) - return ret; + // Check submitter's individual freeze only when Submitter != Destination (a regular freeze + // should not block self-withdrawal). + if (submitterAcct != dstAcct) + { + if (auto const ret = checkFrozen(view, submitterAcct, asset)) + return ret; + } // The destination account must not be deep frozen to receive the funds return checkDeepFrozen(view, dstAcct, asset); } +[[nodiscard]] TER +checkDepositFreeze( + ReadView const& view, + AccountID const& srcAcct, + AccountID const& dstAcct, + Asset const& asset) +{ + XRPL_ASSERT( + isPseudoAccount(view, dstAcct), + "xrpl::checkDepositFreeze : destination must be a pseudo-account"); + + if (auto const ret = checkFrozen(view, srcAcct, asset)) + return ret; + + // Pseudo-account cannot receive if asset is deep frozen + return checkDeepFrozen(view, dstAcct, asset); +} + //------------------------------------------------------------------------------ // // Account balance functions diff --git a/src/libxrpl/tx/transactors/lending/LoanBrokerCoverDeposit.cpp b/src/libxrpl/tx/transactors/lending/LoanBrokerCoverDeposit.cpp index 537996ba57..802fc5e9b9 100644 --- a/src/libxrpl/tx/transactors/lending/LoanBrokerCoverDeposit.cpp +++ b/src/libxrpl/tx/transactors/lending/LoanBrokerCoverDeposit.cpp @@ -77,12 +77,10 @@ LoanBrokerCoverDeposit::preclaim(PreclaimContext const& ctx) // Cannot transfer a non-transferable Asset if (auto const ret = canTransfer(ctx.view, vaultAsset, account, pseudoAccountID)) return ret; - // Cannot transfer a frozen Asset - if (auto const ret = checkFrozen(ctx.view, account, vaultAsset)) - return ret; - // Pseudo-account cannot receive if asset is deep frozen - if (auto const ret = checkDeepFrozen(ctx.view, pseudoAccountID, vaultAsset)) + + if (auto const ret = checkDepositFreeze(ctx.view, account, pseudoAccountID, vaultAsset)) return ret; + // Cannot transfer unauthorized asset if (auto const ret = requireAuth(ctx.view, vaultAsset, account, AuthType::StrongAuth)) return ret; diff --git a/src/libxrpl/tx/transactors/vault/VaultDeposit.cpp b/src/libxrpl/tx/transactors/vault/VaultDeposit.cpp index c08d1e957c..f73832e089 100644 --- a/src/libxrpl/tx/transactors/vault/VaultDeposit.cpp +++ b/src/libxrpl/tx/transactors/vault/VaultDeposit.cpp @@ -107,13 +107,21 @@ VaultDeposit::preclaim(PreclaimContext const& ctx) // LCOV_EXCL_STOP } - // Cannot deposit inside Vault an Asset frozen for the depositor - if (isFrozen(ctx.view, account, vaultAsset)) - return vaultAsset.holds() ? tecFROZEN : tecLOCKED; + if (ctx.view.rules().enabled(fixCleanup3_3_0)) + { + if (auto const ret = checkDepositFreeze(ctx.view, account, vaultAccount, vaultAsset)) + return ret; + } + else + { + // Cannot deposit inside Vault an Asset frozen for the depositor + if (isFrozen(ctx.view, account, vaultAsset)) + return vaultAsset.holds() ? tecFROZEN : tecLOCKED; - // Cannot deposit if the shares of the vault are frozen - if (isFrozen(ctx.view, account, vaultShare)) - return tecLOCKED; + // Cannot deposit if the shares of the vault are frozen + if (isFrozen(ctx.view, account, vaultShare)) + return tecLOCKED; + } if (vault->isFlag(lsfVaultPrivate) && account != vault->at(sfOwner)) {