more usage of MPToken

This commit is contained in:
Mayukha Vadari
2026-03-21 22:31:37 -07:00
parent 96d4a69a37
commit ad2c359f21
16 changed files with 123 additions and 102 deletions

View File

@@ -37,6 +37,18 @@ public:
{
}
[[nodiscard]] AccountID const&
getIssuer() const
{
return issuer_;
}
[[nodiscard]] Currency const&
getCurrency() const
{
return currency_;
}
[[nodiscard]] bool
isGlobalFrozen() const override
{

View File

@@ -1,5 +1,6 @@
#pragma once
#include <xrpl/ledger/entries/MPTokenHelpers.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
@@ -21,7 +22,7 @@ namespace xrpl {
[[nodiscard]] std::optional<STAmount>
assetsToSharesDeposit(
std::shared_ptr<SLE const> const& vault,
std::shared_ptr<SLE const> 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<STAmount>
sharesToAssetsDeposit(
std::shared_ptr<SLE const> const& vault,
std::shared_ptr<SLE const> 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<STAmount>
assetsToSharesWithdraw(
std::shared_ptr<SLE const> const& vault,
std::shared_ptr<SLE const> const& issuance,
MPToken const& issuance,
STAmount const& assets,
TruncateShares truncate = TruncateShares::no);
@@ -75,7 +76,7 @@ assetsToSharesWithdraw(
[[nodiscard]] std::optional<STAmount>
sharesToAssetsWithdraw(
std::shared_ptr<SLE const> const& vault,
std::shared_ptr<SLE const> const& issuance,
MPToken const& issuance,
STAmount const& shares);
} // namespace xrpl

View File

@@ -1,5 +1,6 @@
#pragma once
#include <xrpl/ledger/entries/MPTokenHelpers.h>
#include <xrpl/tx/Transactor.h>
namespace xrpl {
@@ -26,7 +27,7 @@ private:
Expected<std::pair<STAmount, STAmount>, TER>
assetsToClawback(
std::shared_ptr<SLE> const& vault,
std::shared_ptr<SLE const> const& sleShareIssuance,
MPToken const& shareIssuance,
AccountID const& holder,
STAmount const& clawbackAmount);
};

View File

@@ -9,7 +9,7 @@ namespace xrpl {
[[nodiscard]] std::optional<STAmount>
assetsToSharesDeposit(
std::shared_ptr<SLE const> const& vault,
std::shared_ptr<SLE const> 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<STAmount>
sharesToAssetsDeposit(
std::shared_ptr<SLE const> const& vault,
std::shared_ptr<SLE const> 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<STAmount>
assetsToSharesWithdraw(
std::shared_ptr<SLE const> const& vault,
std::shared_ptr<SLE const> const& issuance,
MPToken const& issuance,
STAmount const& assets,
TruncateShares truncate)
{
@@ -89,7 +89,7 @@ assetsToSharesWithdraw(
[[nodiscard]] std::optional<STAmount>
sharesToAssetsWithdraw(
std::shared_ptr<SLE const> const& vault,
std::shared_ptr<SLE const> const& issuance,
MPToken const& issuance,
STAmount const& shares)
{
XRPL_ASSERT(!shares.negative(), "xrpl::sharesToAssetsDeposit : non-negative shares");

View File

@@ -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;
}

View File

@@ -73,8 +73,8 @@ AMMClawback::preclaim(PreclaimContext const& ctx)
{
auto const asset = ctx.tx[sfAsset].get<Issue>();
auto const asset2 = ctx.tx[sfAsset2].get<Issue>();
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;

View File

@@ -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;

View File

@@ -1,6 +1,7 @@
#include <xrpl/tx/transactors/lending/LoanBrokerCoverClawback.h>
//
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/protocol/STTakesAsset.h>
#include <xrpl/tx/transactors/lending/LendingHelpers.h>
@@ -181,16 +182,15 @@ preclaimHelper<MPTIssue>(
SLE const& sleIssuer,
STAmount const& clawAmount)
{
auto const issuanceKey = keylet::mptIssuance(clawAmount.get<MPTIssue>().getMptID());
auto const sleIssuance = ctx.view.read(issuanceKey);
if (!sleIssuance)
MPToken const mptIssuance(ctx.view, clawAmount.get<MPTIssue>());
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;

View File

@@ -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.

View File

@@ -1,4 +1,5 @@
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/MPTokenHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/tx/transactors/token/MPTokenIssuanceDestroy.h>
@@ -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_);

View File

@@ -1,3 +1,4 @@
#include <xrpl/ledger/entries/MPTokenHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/TxFlags.h>
@@ -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))

View File

@@ -1,6 +1,7 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/MPTIssue.h>
@@ -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(
[&]<ValidIssueType TIss>(TIss const& issue) -> TER {
if constexpr (std::is_same_v<TIss, MPTIssue>)
{
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<TIss, Issue>)
{
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<std::pair<STAmount, STAmount>, TER>
VaultClawback::assetsToClawback(
std::shared_ptr<SLE> const& vault,
std::shared_ptr<SLE const> 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();

View File

@@ -1,5 +1,6 @@
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/MPTIssue.h>
@@ -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)))

View File

@@ -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

View File

@@ -1,4 +1,5 @@
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/MPTokenHelpers.h>
#include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -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

View File

@@ -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;
}