diff --git a/include/xrpl/ledger/helpers/RippleStateHelpers.h b/include/xrpl/ledger/helpers/RippleStateHelpers.h index d20401efbe..753860beac 100644 --- a/include/xrpl/ledger/helpers/RippleStateHelpers.h +++ b/include/xrpl/ledger/helpers/RippleStateHelpers.h @@ -37,6 +37,18 @@ public: { } + [[nodiscard]] AccountID const& + getIssuer() const + { + return issuer_; + } + + [[nodiscard]] Currency const& + getCurrency() const + { + return currency_; + } + [[nodiscard]] bool isGlobalFrozen() const override { diff --git a/include/xrpl/ledger/helpers/VaultHelpers.h b/include/xrpl/ledger/helpers/VaultHelpers.h index 8aef30aa27..9751daa1bc 100644 --- a/include/xrpl/ledger/helpers/VaultHelpers.h +++ b/include/xrpl/ledger/helpers/VaultHelpers.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -21,7 +22,7 @@ namespace xrpl { [[nodiscard]] std::optional assetsToSharesDeposit( std::shared_ptr const& vault, - std::shared_ptr const& issuance, + MPToken const& issuance, STAmount const& assets); /** From the perspective of a vault, return the number of assets to take from @@ -37,7 +38,7 @@ assetsToSharesDeposit( [[nodiscard]] std::optional sharesToAssetsDeposit( std::shared_ptr const& vault, - std::shared_ptr const& issuance, + MPToken const& issuance, STAmount const& shares); /** Controls whether to truncate shares instead of rounding. */ @@ -58,7 +59,7 @@ enum class TruncateShares : bool { no = false, yes = true }; [[nodiscard]] std::optional assetsToSharesWithdraw( std::shared_ptr const& vault, - std::shared_ptr const& issuance, + MPToken const& issuance, STAmount const& assets, TruncateShares truncate = TruncateShares::no); @@ -75,7 +76,7 @@ assetsToSharesWithdraw( [[nodiscard]] std::optional sharesToAssetsWithdraw( std::shared_ptr const& vault, - std::shared_ptr const& issuance, + MPToken const& issuance, STAmount const& shares); } // namespace xrpl diff --git a/include/xrpl/tx/transactors/vault/VaultClawback.h b/include/xrpl/tx/transactors/vault/VaultClawback.h index 131a1d87e7..270b3102ee 100644 --- a/include/xrpl/tx/transactors/vault/VaultClawback.h +++ b/include/xrpl/tx/transactors/vault/VaultClawback.h @@ -1,5 +1,6 @@ #pragma once +#include #include namespace xrpl { @@ -26,7 +27,7 @@ private: Expected, TER> assetsToClawback( std::shared_ptr const& vault, - std::shared_ptr const& sleShareIssuance, + MPToken const& shareIssuance, AccountID const& holder, STAmount const& clawbackAmount); }; diff --git a/src/libxrpl/ledger/helpers/VaultHelpers.cpp b/src/libxrpl/ledger/helpers/VaultHelpers.cpp index 3ded720289..8e5140d015 100644 --- a/src/libxrpl/ledger/helpers/VaultHelpers.cpp +++ b/src/libxrpl/ledger/helpers/VaultHelpers.cpp @@ -9,7 +9,7 @@ namespace xrpl { [[nodiscard]] std::optional assetsToSharesDeposit( std::shared_ptr const& vault, - std::shared_ptr const& issuance, + MPToken const& issuance, STAmount const& assets) { XRPL_ASSERT(!assets.negative(), "xrpl::assetsToSharesDeposit : non-negative assets"); @@ -36,7 +36,7 @@ assetsToSharesDeposit( [[nodiscard]] std::optional sharesToAssetsDeposit( std::shared_ptr const& vault, - std::shared_ptr const& issuance, + MPToken const& issuance, STAmount const& shares) { XRPL_ASSERT(!shares.negative(), "xrpl::sharesToAssetsDeposit : non-negative shares"); @@ -62,7 +62,7 @@ sharesToAssetsDeposit( [[nodiscard]] std::optional assetsToSharesWithdraw( std::shared_ptr const& vault, - std::shared_ptr const& issuance, + MPToken const& issuance, STAmount const& assets, TruncateShares truncate) { @@ -89,7 +89,7 @@ assetsToSharesWithdraw( [[nodiscard]] std::optional sharesToAssetsWithdraw( std::shared_ptr const& vault, - std::shared_ptr const& issuance, + MPToken const& issuance, STAmount const& shares) { XRPL_ASSERT(!shares.negative(), "xrpl::sharesToAssetsDeposit : non-negative shares"); diff --git a/src/libxrpl/tx/transactors/bridge/XChainBridge.cpp b/src/libxrpl/tx/transactors/bridge/XChainBridge.cpp index b11bb29d8c..3d753364c2 100644 --- a/src/libxrpl/tx/transactors/bridge/XChainBridge.cpp +++ b/src/libxrpl/tx/transactors/bridge/XChainBridge.cpp @@ -1394,13 +1394,16 @@ XChainCreateBridge::preclaim(PreclaimContext const& ctx) if (!isXRP(bridgeSpec.issue(chainType))) { AccountRoot const acctIssuer(bridgeSpec.issue(chainType).account, ctx.view); + IOUToken const iouToken(ctx.view, bridgeSpec.issue(chainType)); - if (!acctIssuer) + if (!iouToken) return tecNO_ISSUER; // Allowing clawing back funds would break the bridge's invariant that // wrapped funds are always backed by locked funds - if (acctIssuer->getFlags() & lsfAllowTrustLineClawback) + // NOTE: DO NOT use `iouToken.canClawback()` here, because that function also checks + // `lsfNoFreeze`, which is not checked here + if (iouToken->getFlags() & lsfAllowTrustLineClawback) return tecNO_PERMISSION; } diff --git a/src/libxrpl/tx/transactors/dex/AMMClawback.cpp b/src/libxrpl/tx/transactors/dex/AMMClawback.cpp index 5645311b37..53525b3385 100644 --- a/src/libxrpl/tx/transactors/dex/AMMClawback.cpp +++ b/src/libxrpl/tx/transactors/dex/AMMClawback.cpp @@ -73,8 +73,8 @@ AMMClawback::preclaim(PreclaimContext const& ctx) { auto const asset = ctx.tx[sfAsset].get(); auto const asset2 = ctx.tx[sfAsset2].get(); - AccountRoot const acctIssuer(ctx.tx[sfAccount], ctx.view); - if (!acctIssuer) + IOUToken const assetToken(ctx.view, asset); + if (!assetToken) return terNO_ACCOUNT; // LCOV_EXCL_LINE if (AccountRoot const acctHolder(ctx.tx[sfHolder], ctx.view); !acctHolder) @@ -87,11 +87,9 @@ AMMClawback::preclaim(PreclaimContext const& ctx) return terNO_AMM; } - std::uint32_t const issuerFlagsIn = acctIssuer->getFieldU32(sfFlags); - // If AllowTrustLineClawback is not set or NoFreeze is set, return no // permission - if (!(issuerFlagsIn & lsfAllowTrustLineClawback) || (issuerFlagsIn & lsfNoFreeze)) + if (!assetToken.canClawback()) return tecNO_PERMISSION; return tesSUCCESS; diff --git a/src/libxrpl/tx/transactors/dex/AMMCreate.cpp b/src/libxrpl/tx/transactors/dex/AMMCreate.cpp index 8095b162cb..e94bc333c0 100644 --- a/src/libxrpl/tx/transactors/dex/AMMCreate.cpp +++ b/src/libxrpl/tx/transactors/dex/AMMCreate.cpp @@ -171,6 +171,8 @@ AMMCreate::preclaim(PreclaimContext const& ctx) AccountRoot const acct(issue.account, ctx.view); if (!acct) return tecINTERNAL; // LCOV_EXCL_LINE + // NOTE: DO NOT use `iouToken.canClawback()` here, because that function also checks + // `lsfNoFreeze`, which is not checked here if (acct->getFlags() & lsfAllowTrustLineClawback) return tecNO_PERMISSION; return tesSUCCESS; diff --git a/src/libxrpl/tx/transactors/lending/LoanBrokerCoverClawback.cpp b/src/libxrpl/tx/transactors/lending/LoanBrokerCoverClawback.cpp index b77ad79b0e..86f0d66d50 100644 --- a/src/libxrpl/tx/transactors/lending/LoanBrokerCoverClawback.cpp +++ b/src/libxrpl/tx/transactors/lending/LoanBrokerCoverClawback.cpp @@ -1,6 +1,7 @@ #include // #include +#include #include #include @@ -181,16 +182,15 @@ preclaimHelper( SLE const& sleIssuer, STAmount const& clawAmount) { - auto const issuanceKey = keylet::mptIssuance(clawAmount.get().getMptID()); - auto const sleIssuance = ctx.view.read(issuanceKey); - if (!sleIssuance) + MPToken const mptIssuance(ctx.view, clawAmount.get()); + if (!mptIssuance) return tecOBJECT_NOT_FOUND; - if (!sleIssuance->isFlag(lsfMPTCanClawback)) + if (!mptIssuance.canClawback()) return tecNO_PERMISSION; // With all the checking already done, this should be impossible - if (sleIssuance->at(sfIssuer) != sleIssuer[sfAccount]) + if (mptIssuance.getIssuer() != sleIssuer[sfAccount]) return tecINTERNAL; // LCOV_EXCL_LINE return tesSUCCESS; diff --git a/src/libxrpl/tx/transactors/token/MPTokenAuthorize.cpp b/src/libxrpl/tx/transactors/token/MPTokenAuthorize.cpp index e491fdd0cc..67d3adb32d 100644 --- a/src/libxrpl/tx/transactors/token/MPTokenAuthorize.cpp +++ b/src/libxrpl/tx/transactors/token/MPTokenAuthorize.cpp @@ -78,12 +78,12 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx) } // Now test when the holder wants to hold/create/authorize a new MPT - auto const sleMptIssuance = ctx.view.read(keylet::mptIssuance(ctx.tx[sfMPTokenIssuanceID])); + MPToken const mptIssuance(ctx.view, MPTIssue{ctx.tx[sfMPTokenIssuanceID]}); - if (!sleMptIssuance) + if (!mptIssuance) return tecOBJECT_NOT_FOUND; - if (accountID == (*sleMptIssuance)[sfIssuer]) + if (accountID == mptIssuance.getIssuer()) return tecNO_PERMISSION; // if holder wants to use and create a mpt @@ -96,12 +96,10 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx) if (AccountRoot const acctHolder(*holderID, ctx.view); !acctHolder) return tecNO_DST; - auto const sleMptIssuance = ctx.view.read(keylet::mptIssuance(ctx.tx[sfMPTokenIssuanceID])); - if (!sleMptIssuance) + MPToken const mptIssuance(ctx.view, MPTIssue{ctx.tx[sfMPTokenIssuanceID]}); + if (!mptIssuance) return tecOBJECT_NOT_FOUND; - std::uint32_t const mptIssuanceFlags = sleMptIssuance->getFieldU32(sfFlags); - // If tx is submitted by issuer, they would either try to do the following // for allowlisting: // 1. authorize an account @@ -109,12 +107,12 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx) // // Note: `accountID` is issuer's account // `holderID` is holder's account - if (accountID != (*sleMptIssuance)[sfIssuer]) + if (accountID != mptIssuance.getIssuer()) return tecNO_PERMISSION; // If tx is submitted by issuer, it only applies for MPT with // lsfMPTRequireAuth set - if (!(mptIssuanceFlags & lsfMPTRequireAuth)) + if (!mptIssuance.requiresAuth()) return tecNO_AUTH; // The holder must create the MPT before the issuer can authorize it. diff --git a/src/libxrpl/tx/transactors/token/MPTokenIssuanceDestroy.cpp b/src/libxrpl/tx/transactors/token/MPTokenIssuanceDestroy.cpp index 3b457d4988..2cd43a6ebc 100644 --- a/src/libxrpl/tx/transactors/token/MPTokenIssuanceDestroy.cpp +++ b/src/libxrpl/tx/transactors/token/MPTokenIssuanceDestroy.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -15,19 +16,19 @@ TER MPTokenIssuanceDestroy::preclaim(PreclaimContext const& ctx) { // ensure that issuance exists - auto const sleMPT = ctx.view.read(keylet::mptIssuance(ctx.tx[sfMPTokenIssuanceID])); - if (!sleMPT) + MPToken const mptIssuance(ctx.view, ctx.tx[sfMPTokenIssuanceID]); + if (!mptIssuance) return tecOBJECT_NOT_FOUND; // ensure it is issued by the tx submitter - if ((*sleMPT)[sfIssuer] != ctx.tx[sfAccount]) + if (mptIssuance.getIssuer() != ctx.tx[sfAccount]) return tecNO_PERMISSION; // ensure it has no outstanding balances - if ((*sleMPT)[sfOutstandingAmount] != 0) + if (mptIssuance->at(sfOutstandingAmount) != 0) return tecHAS_OBLIGATIONS; - if ((*sleMPT)[~sfLockedAmount].value_or(0) != 0) + if (mptIssuance->at(~sfLockedAmount).value_or(0) != 0) return tecHAS_OBLIGATIONS; // LCOV_EXCL_LINE return tesSUCCESS; @@ -36,14 +37,15 @@ MPTokenIssuanceDestroy::preclaim(PreclaimContext const& ctx) TER MPTokenIssuanceDestroy::doApply() { - auto const mpt = view().peek(keylet::mptIssuance(ctx_.tx[sfMPTokenIssuanceID])); - if (accountID_ != mpt->getAccountID(sfIssuer)) + WritableMPToken mptIssuance(view(), ctx_.tx[sfMPTokenIssuanceID]); + if (accountID_ != mptIssuance.getIssuer()) return tecINTERNAL; // LCOV_EXCL_LINE - if (!view().dirRemove(keylet::ownerDir(accountID_), (*mpt)[sfOwnerNode], mpt->key(), false)) + if (!view().dirRemove( + keylet::ownerDir(accountID_), (*mptIssuance)[sfOwnerNode], mptIssuance->key(), false)) return tefBAD_LEDGER; // LCOV_EXCL_LINE - view().erase(mpt); + mptIssuance.erase(); WritableAccountRoot acct(accountID_, view()); acct.adjustOwnerCount(-1, j_); diff --git a/src/libxrpl/tx/transactors/token/MPTokenIssuanceSet.cpp b/src/libxrpl/tx/transactors/token/MPTokenIssuanceSet.cpp index dc5827419b..4a0167cee1 100644 --- a/src/libxrpl/tx/transactors/token/MPTokenIssuanceSet.cpp +++ b/src/libxrpl/tx/transactors/token/MPTokenIssuanceSet.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -149,11 +150,11 @@ TER MPTokenIssuanceSet::preclaim(PreclaimContext const& ctx) { // ensure that issuance exists - auto const sleMptIssuance = ctx.view.read(keylet::mptIssuance(ctx.tx[sfMPTokenIssuanceID])); - if (!sleMptIssuance) + MPToken const mptIssuance(ctx.view, MPTIssue{ctx.tx[sfMPTokenIssuanceID]}); + if (!mptIssuance) return tecOBJECT_NOT_FOUND; - if (!sleMptIssuance->isFlag(lsfMPTCanLock)) + if (!mptIssuance->isFlag(lsfMPTCanLock)) { // For readability two separate `if` rather than `||` of two conditions if (!ctx.view.rules().enabled(featureSingleAssetVault) && @@ -168,7 +169,7 @@ MPTokenIssuanceSet::preclaim(PreclaimContext const& ctx) } // ensure it is issued by the tx submitter - if ((*sleMptIssuance)[sfIssuer] != ctx.tx[sfAccount]) + if (mptIssuance.getIssuer() != ctx.tx[sfAccount]) return tecNO_PERMISSION; if (auto const holderID = ctx.tx[~sfHolder]) @@ -184,7 +185,7 @@ MPTokenIssuanceSet::preclaim(PreclaimContext const& ctx) if (auto const domain = ctx.tx[~sfDomainID]) { - if (not sleMptIssuance->isFlag(lsfMPTRequireAuth)) + if (!mptIssuance.requiresAuth()) return tecNO_PERMISSION; if (*domain != beast::zero) @@ -197,7 +198,7 @@ MPTokenIssuanceSet::preclaim(PreclaimContext const& ctx) // sfMutableFlags is soeDEFAULT, defaulting to 0 if not specified on // the ledger. - auto const currentMutableFlags = sleMptIssuance->getFieldU32(sfMutableFlags); + auto const currentMutableFlags = mptIssuance->getFieldU32(sfMutableFlags); auto isMutableFlag = [&](std::uint32_t mutableFlag) -> bool { return currentMutableFlags & mutableFlag; @@ -224,7 +225,7 @@ MPTokenIssuanceSet::preclaim(PreclaimContext const& ctx) // was previously enabled (at issuance or via a prior mutation). Setting // it by tmfMPTSetCanTransfer in the current transaction does not meet // this requirement. - if (fee > 0u && !sleMptIssuance->isFlag(lsfMPTCanTransfer)) + if (fee > 0u && !mptIssuance->isFlag(lsfMPTCanTransfer)) return tecNO_PERMISSION; if (!isMutableFlag(lsmfMPTCanMutateTransferFee)) diff --git a/src/libxrpl/tx/transactors/vault/VaultClawback.cpp b/src/libxrpl/tx/transactors/vault/VaultClawback.cpp index 54675b09fe..cc694d59ee 100644 --- a/src/libxrpl/tx/transactors/vault/VaultClawback.cpp +++ b/src/libxrpl/tx/transactors/vault/VaultClawback.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -70,8 +71,9 @@ VaultClawback::preclaim(PreclaimContext const& ctx) auto const holder = ctx.tx[sfHolder]; auto const maybeAmount = ctx.tx[~sfAmount]; auto const mptIssuanceID = vault->at(sfShareMPTID); - auto const sleShareIssuance = ctx.view.read(keylet::mptIssuance(mptIssuanceID)); - if (!sleShareIssuance) + MPTIssue const share{mptIssuanceID}; + MPToken const shareIssuance(ctx.view, share); + if (!shareIssuance) { // LCOV_EXCL_START JLOG(ctx.j.error()) << "VaultClawback: missing issuance of vault shares."; @@ -79,8 +81,6 @@ VaultClawback::preclaim(PreclaimContext const& ctx) // LCOV_EXCL_STOP } - Asset const share = MPTIssue{mptIssuanceID}; - // Ambiguous case: If Issuer is Owner they must specify the asset if (!maybeAmount && !vaultAsset.native() && vaultAsset.getIssuer() == vault->at(sfOwner)) { @@ -105,7 +105,7 @@ VaultClawback::preclaim(PreclaimContext const& ctx) auto const assetsTotal = vault->at(sfAssetsTotal); auto const assetsAvailable = vault->at(sfAssetsAvailable); - auto const sharesTotal = sleShareIssuance->at(sfOutstandingAmount); + auto const sharesTotal = shareIssuance->at(sfOutstandingAmount); // Owner can clawback funds when the vault has shares but no assets if (sharesTotal == 0 || (assetsTotal != 0 || assetsAvailable != 0)) @@ -162,16 +162,22 @@ VaultClawback::preclaim(PreclaimContext const& ctx) return tecNO_PERMISSION; } + auto const vaultAssetToken = makeTokenBase(ctx.view, vaultAsset); + if (!vaultAssetToken) + { + JLOG(ctx.j.error()) << "VaultClawback: missing vault asset token."; + return tefINTERNAL; + } + return std::visit( [&](TIss const& issue) -> TER { if constexpr (std::is_same_v) { - auto const mptIssue = ctx.view.read(keylet::mptIssuance(issue.getMptID())); - if (mptIssue == nullptr) + MPToken const mptIssuance(ctx.view, issue); + if (!mptIssuance) return tecOBJECT_NOT_FOUND; - std::uint32_t const issueFlags = mptIssue->getFieldU32(sfFlags); - if (!(issueFlags & lsfMPTCanClawback)) + if (!mptIssuance.canClawback()) { JLOG(ctx.j.debug()) << "VaultClawback: cannot clawback " "MPT vault asset."; @@ -180,8 +186,8 @@ VaultClawback::preclaim(PreclaimContext const& ctx) } else if constexpr (std::is_same_v) { - AccountRoot const acctIssuer(account, ctx.view); - if (!acctIssuer) + IOUToken const iouToken(ctx.view, issue); + if (!iouToken) { // LCOV_EXCL_START JLOG(ctx.j.error()) << "VaultClawback: missing submitter account."; @@ -189,8 +195,7 @@ VaultClawback::preclaim(PreclaimContext const& ctx) // LCOV_EXCL_STOP } - std::uint32_t const issuerFlags = acctIssuer->getFieldU32(sfFlags); - if (!(issuerFlags & lsfAllowTrustLineClawback) || (issuerFlags & lsfNoFreeze)) + if (!iouToken.canClawback()) { JLOG(ctx.j.debug()) << "VaultClawback: cannot clawback " "IOU vault asset."; @@ -209,7 +214,7 @@ VaultClawback::preclaim(PreclaimContext const& ctx) Expected, TER> VaultClawback::assetsToClawback( std::shared_ptr const& vault, - std::shared_ptr const& sleShareIssuance, + MPToken const& shareIssuance, AccountID const& holder, STAmount const& clawbackAmount) { @@ -235,7 +240,7 @@ VaultClawback::assetsToClawback( FreezeHandling::fhIGNORE_FREEZE, AuthHandling::ahIGNORE_AUTH, j_); - auto const maybeAssets = sharesToAssetsWithdraw(vault, sleShareIssuance, sharesDestroyed); + auto const maybeAssets = sharesToAssetsWithdraw(vault, shareIssuance, sharesDestroyed); if (!maybeAssets) return Unexpected(tecINTERNAL); // LCOV_EXCL_LINE @@ -247,14 +252,13 @@ VaultClawback::assetsToClawback( try { { - auto const maybeShares = - assetsToSharesWithdraw(vault, sleShareIssuance, assetsRecovered); + auto const maybeShares = assetsToSharesWithdraw(vault, shareIssuance, assetsRecovered); if (!maybeShares) return Unexpected(tecINTERNAL); // LCOV_EXCL_LINE sharesDestroyed = *maybeShares; } - auto const maybeAssets = sharesToAssetsWithdraw(vault, sleShareIssuance, sharesDestroyed); + auto const maybeAssets = sharesToAssetsWithdraw(vault, shareIssuance, sharesDestroyed); if (!maybeAssets) return Unexpected(tecINTERNAL); // LCOV_EXCL_LINE assetsRecovered = *maybeAssets; @@ -268,14 +272,13 @@ VaultClawback::assetsToClawback( // AssetsAvailable { auto const maybeShares = assetsToSharesWithdraw( - vault, sleShareIssuance, assetsRecovered, TruncateShares::yes); + vault, shareIssuance, assetsRecovered, TruncateShares::yes); if (!maybeShares) return Unexpected(tecINTERNAL); // LCOV_EXCL_LINE sharesDestroyed = *maybeShares; } - auto const maybeAssets = - sharesToAssetsWithdraw(vault, sleShareIssuance, sharesDestroyed); + auto const maybeAssets = sharesToAssetsWithdraw(vault, shareIssuance, sharesDestroyed); if (!maybeAssets) return Unexpected(tecINTERNAL); // LCOV_EXCL_LINE assetsRecovered = *maybeAssets; @@ -296,7 +299,7 @@ VaultClawback::assetsToClawback( << "VaultClawback: overflow error with" << " scale=" << (int)vault->at(sfScale).value() // << ", assetsTotal=" << vault->at(sfAssetsTotal).value() - << ", sharesTotal=" << sleShareIssuance->at(sfOutstandingAmount) + << ", sharesTotal=" << shareIssuance->at(sfOutstandingAmount) << ", amount=" << clawbackAmount.value(); return Unexpected(tecPATH_DRY); } @@ -313,15 +316,15 @@ VaultClawback::doApply() return tefINTERNAL; // LCOV_EXCL_LINE auto const mptIssuanceID = *vault->at(sfShareMPTID); - auto const sleIssuance = view().read(keylet::mptIssuance(mptIssuanceID)); - if (!sleIssuance) + MPTIssue const share{mptIssuanceID}; + MPToken const shareIssuance(view(), share); + if (!shareIssuance) { // LCOV_EXCL_START JLOG(j_.error()) << "VaultClawback: missing issuance of vault shares."; return tefINTERNAL; // LCOV_EXCL_STOP } - MPTIssue const share{mptIssuanceID}; Asset const vaultAsset = vault->at(sfAsset); STAmount const amount = clawbackAmount(vault, tx[~sfAmount], accountID_); @@ -353,7 +356,7 @@ VaultClawback::doApply() { XRPL_ASSERT(amount.asset() == vaultAsset, "xrpl::VaultClawback::doApply : matching asset"); - auto const clawbackParts = assetsToClawback(vault, sleIssuance, holder, amount); + auto const clawbackParts = assetsToClawback(vault, shareIssuance, holder, amount); if (!clawbackParts) return clawbackParts.error(); diff --git a/src/libxrpl/tx/transactors/vault/VaultDelete.cpp b/src/libxrpl/tx/transactors/vault/VaultDelete.cpp index 3c4bb631de..699a11bd69 100644 --- a/src/libxrpl/tx/transactors/vault/VaultDelete.cpp +++ b/src/libxrpl/tx/transactors/vault/VaultDelete.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -49,9 +50,9 @@ VaultDelete::preclaim(PreclaimContext const& ctx) } // Verify we can destroy MPTokenIssuance - auto const sleMPT = ctx.view.read(keylet::mptIssuance(vault->at(sfShareMPTID))); + MPToken const shareIssuance(ctx.view, vault->at(sfShareMPTID)); - if (!sleMPT) + if (!shareIssuance) { // LCOV_EXCL_START JLOG(ctx.j.error()) << "VaultDeposit: missing issuance of vault shares."; @@ -59,7 +60,7 @@ VaultDelete::preclaim(PreclaimContext const& ctx) // LCOV_EXCL_STOP } - if (sleMPT->at(sfIssuer) != vault->getAccountID(sfAccount)) + if (shareIssuance.getIssuer() != vault->getAccountID(sfAccount)) { // LCOV_EXCL_START JLOG(ctx.j.error()) << "VaultDeposit: invalid owner of vault shares."; @@ -67,7 +68,7 @@ VaultDelete::preclaim(PreclaimContext const& ctx) // LCOV_EXCL_STOP } - if (sleMPT->at(sfOutstandingAmount) != 0) + if (shareIssuance->at(sfOutstandingAmount) != 0) { JLOG(ctx.j.debug()) << "VaultDelete: nonzero outstanding shares."; return tecHAS_OBLIGATIONS; @@ -104,8 +105,8 @@ VaultDelete::doApply() // Destroy the share issuance. Do not use MPTokenIssuanceDestroy for this, // no special logic needed. First run few checks, duplicated from preclaim. auto const shareMPTID = *vault->at(sfShareMPTID); - auto const mpt = view().peek(keylet::mptIssuance(shareMPTID)); - if (!mpt) + WritableMPToken shareIssuance(view(), shareMPTID); + if (!shareIssuance) { // LCOV_EXCL_START JLOG(j_.error()) << "VaultDelete: missing issuance of vault shares."; @@ -131,7 +132,8 @@ VaultDelete::doApply() } } - if (!view().dirRemove(keylet::ownerDir(pseudoID), (*mpt)[sfOwnerNode], mpt->key(), false)) + if (!view().dirRemove( + keylet::ownerDir(pseudoID), (*shareIssuance)[sfOwnerNode], shareIssuance->key(), false)) { // LCOV_EXCL_START JLOG(j_.error()) << "VaultDelete: failed to delete issuance object."; @@ -140,7 +142,7 @@ VaultDelete::doApply() } pseudoAcct.adjustOwnerCount(-1, j_); - view().erase(mpt); + shareIssuance.erase(); // The pseudo-account's directory should have been deleted already. if (view().peek(keylet::ownerDir(pseudoID))) diff --git a/src/libxrpl/tx/transactors/vault/VaultDeposit.cpp b/src/libxrpl/tx/transactors/vault/VaultDeposit.cpp index 20ea48acc9..899f7d0e8f 100644 --- a/src/libxrpl/tx/transactors/vault/VaultDeposit.cpp +++ b/src/libxrpl/tx/transactors/vault/VaultDeposit.cpp @@ -173,7 +173,7 @@ VaultDeposit::doApply() XRPL_ASSERT( accountID_ == vault->at(sfOwner), "xrpl::VaultDeposit::doApply : account is owner"); if (auto const err = mptoken.authorizeMPToken( - preFeeBalance_, // priorBalance + preFeeBalance_, // priorBalance mptoken->at(sfIssuer), // account ctx_.journal, {}, // flags @@ -189,7 +189,7 @@ VaultDeposit::doApply() { // Compute exchange before transferring any amounts. { - auto const maybeShares = assetsToSharesDeposit(vault, mptoken.sle(), amount); + auto const maybeShares = assetsToSharesDeposit(vault, mptoken, amount); if (!maybeShares) return tecINTERNAL; // LCOV_EXCL_LINE sharesCreated = *maybeShares; @@ -197,7 +197,7 @@ VaultDeposit::doApply() if (sharesCreated == beast::zero) return tecPRECISION_LOSS; - auto const maybeAssets = sharesToAssetsDeposit(vault, mptoken.sle(), sharesCreated); + auto const maybeAssets = sharesToAssetsDeposit(vault, mptoken, sharesCreated); if (!maybeAssets) { return tecINTERNAL; // LCOV_EXCL_LINE diff --git a/src/libxrpl/tx/transactors/vault/VaultSet.cpp b/src/libxrpl/tx/transactors/vault/VaultSet.cpp index 532edcdcef..8153ef49b1 100644 --- a/src/libxrpl/tx/transactors/vault/VaultSet.cpp +++ b/src/libxrpl/tx/transactors/vault/VaultSet.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -71,9 +72,8 @@ VaultSet::preclaim(PreclaimContext const& ctx) return tecNO_PERMISSION; } - auto const mptIssuanceID = (*vault)[sfShareMPTID]; - auto const sleIssuance = ctx.view.read(keylet::mptIssuance(mptIssuanceID)); - if (!sleIssuance) + MPToken const shareIssuance(ctx.view, (*vault)[sfShareMPTID]); + if (!shareIssuance) { // LCOV_EXCL_START JLOG(ctx.j.error()) << "VaultSet: missing issuance of vault shares."; @@ -98,7 +98,7 @@ VaultSet::preclaim(PreclaimContext const& ctx) } // Sanity check only, this should be enforced by VaultCreate - if ((sleIssuance->getFlags() & lsfMPTRequireAuth) == 0) + if (!shareIssuance.requiresAuth()) { // LCOV_EXCL_START JLOG(ctx.j.error()) << "VaultSet: issuance of vault shares is not private."; @@ -126,9 +126,8 @@ VaultSet::doApply() auto const vaultAsset = vault->at(sfAsset); - auto const mptIssuanceID = (*vault)[sfShareMPTID]; - auto const sleIssuance = view().peek(keylet::mptIssuance(mptIssuanceID)); - if (!sleIssuance) + WritableMPToken shareIssuance(view(), (*vault)[sfShareMPTID]); + if (!shareIssuance) { // LCOV_EXCL_START JLOG(j_.error()) << "VaultSet: missing issuance of vault shares."; @@ -155,13 +154,13 @@ VaultSet::doApply() // vault public (i.e. removal of lsfVaultPrivate flag). The // sfDomainID flag must be set in the MPTokenIssuance object and can // be freely updated. - sleIssuance->setFieldH256(sfDomainID, *domainId); + shareIssuance->setFieldH256(sfDomainID, *domainId); } - else if (sleIssuance->isFieldPresent(sfDomainID)) + else if (shareIssuance->isFieldPresent(sfDomainID)) { - sleIssuance->makeFieldAbsent(sfDomainID); + shareIssuance->makeFieldAbsent(sfDomainID); } - view().update(sleIssuance); + shareIssuance.update(); } // Note, we must update Vault object even if only DomainID is being updated diff --git a/src/libxrpl/tx/transactors/vault/VaultWithdraw.cpp b/src/libxrpl/tx/transactors/vault/VaultWithdraw.cpp index ba4d391da2..e4daf4a5e3 100644 --- a/src/libxrpl/tx/transactors/vault/VaultWithdraw.cpp +++ b/src/libxrpl/tx/transactors/vault/VaultWithdraw.cpp @@ -98,8 +98,9 @@ VaultWithdraw::doApply() return tefINTERNAL; // LCOV_EXCL_LINE auto const mptIssuanceID = *((*vault)[sfShareMPTID]); - auto const sleIssuance = view().read(keylet::mptIssuance(mptIssuanceID)); - if (!sleIssuance) + MPTIssue const share{mptIssuanceID}; + MPToken const shareIssuance(view(), mptIssuanceID); + if (!shareIssuance) { // LCOV_EXCL_START JLOG(j_.error()) << "VaultWithdraw: missing issuance of vault shares."; @@ -114,8 +115,6 @@ VaultWithdraw::doApply() auto const amount = ctx_.tx[sfAmount]; Asset const vaultAsset = vault->at(sfAsset); - - MPTIssue const share{mptIssuanceID}; STAmount sharesRedeemed = {share}; STAmount assetsWithdrawn; try @@ -124,7 +123,7 @@ VaultWithdraw::doApply() { // Fixed assets, variable shares. { - auto const maybeShares = assetsToSharesWithdraw(vault, sleIssuance, amount); + auto const maybeShares = assetsToSharesWithdraw(vault, shareIssuance, amount); if (!maybeShares) return tecINTERNAL; // LCOV_EXCL_LINE sharesRedeemed = *maybeShares; @@ -132,7 +131,7 @@ VaultWithdraw::doApply() if (sharesRedeemed == beast::zero) return tecPRECISION_LOSS; - auto const maybeAssets = sharesToAssetsWithdraw(vault, sleIssuance, sharesRedeemed); + auto const maybeAssets = sharesToAssetsWithdraw(vault, shareIssuance, sharesRedeemed); if (!maybeAssets) return tecINTERNAL; // LCOV_EXCL_LINE assetsWithdrawn = *maybeAssets; @@ -141,7 +140,7 @@ VaultWithdraw::doApply() { // Fixed shares, variable assets. sharesRedeemed = amount; - auto const maybeAssets = sharesToAssetsWithdraw(vault, sleIssuance, sharesRedeemed); + auto const maybeAssets = sharesToAssetsWithdraw(vault, shareIssuance, sharesRedeemed); if (!maybeAssets) return tecINTERNAL; // LCOV_EXCL_LINE assetsWithdrawn = *maybeAssets; @@ -159,7 +158,7 @@ VaultWithdraw::doApply() << "VaultWithdraw: overflow error with" << " scale=" << (int)vault->at(sfScale).value() // << ", assetsTotal=" << vault->at(sfAssetsTotal).value() - << ", sharesTotal=" << sleIssuance->at(sfOutstandingAmount) + << ", sharesTotal=" << shareIssuance->at(sfOutstandingAmount) << ", amount=" << amount.value(); return tecPATH_DRY; }