This commit is contained in:
Mayukha Vadari
2026-03-22 02:35:37 -07:00
parent 8caf6b7210
commit 7491fc78c0
4 changed files with 31 additions and 38 deletions

View File

@@ -61,10 +61,7 @@ MPTokenIssuance::isAnyFrozen(std::initializer_list<AccountID> const& accounts, i
{
if (isIndividualFrozen(account))
return true;
}
for (auto const& account : accounts)
{
if (isVaultPseudoAccountFrozen(readView_, account, mptIssue_, depth))
return true;
}
@@ -157,18 +154,17 @@ WritableMPTokenIssuance::authorizeMPToken(
// - delete the MPToken
if (flags & tfMPTUnauthorize)
{
auto const mptokenKey = keylet::mptoken(mptID_, account);
auto const sleMpt = applyView_.peek(mptokenKey);
if (!sleMpt || (*sleMpt)[sfMPTAmount] != 0)
WritableMPToken mptoken(*this, account);
if (!mptoken.exists() || (*mptoken)[sfMPTAmount] != 0)
return tecINTERNAL; // LCOV_EXCL_LINE
if (!applyView_.dirRemove(
keylet::ownerDir(account), (*sleMpt)[sfOwnerNode], sleMpt->key(), false))
keylet::ownerDir(account), (*mptoken)[sfOwnerNode], mptoken->key(), false))
return tecINTERNAL; // LCOV_EXCL_LINE
wrappedAcct.adjustOwnerCount(-1, journal);
applyView_.erase(sleMpt);
mptoken.erase();
return tesSUCCESS;
}
@@ -371,8 +367,7 @@ WritableMPTokenIssuance::enforceMPTokenAuthorization(
if (account == mutableSle_->at(sfIssuer))
return tefINTERNAL; // LCOV_EXCL_LINE
auto const keylet = keylet::mptoken(mptID_, account);
auto const sleToken = readView_.read(keylet); // NOTE: might be null
MPToken mptoken(*this, account);
auto const maybeDomainID = mutableSle_->at(~sfDomainID);
bool expired = false;
bool const authorizedByDomain = [&]() -> bool {
@@ -388,7 +383,7 @@ WritableMPTokenIssuance::enforceMPTokenAuthorization(
return false;
}();
if (!authorizedByDomain && sleToken == nullptr)
if (!authorizedByDomain && !mptoken.exists())
{
// Could not find MPToken and won't create one, could be either of:
//
@@ -411,14 +406,14 @@ WritableMPTokenIssuance::enforceMPTokenAuthorization(
// We found an MPToken, but sfDomainID is not set, so this is a classic
// MPToken which requires authorization by the token issuer.
XRPL_ASSERT(
sleToken != nullptr && !maybeDomainID,
mptoken.exists() && !maybeDomainID,
"xrpl::enforceMPTokenAuthorization : found MPToken");
if (sleToken->isFlag(lsfMPTAuthorized))
if (mptoken->isFlag(lsfMPTAuthorized))
return tesSUCCESS;
return tecNO_AUTH;
}
if (authorizedByDomain && sleToken != nullptr)
if (authorizedByDomain && mptoken.exists())
{
// Found an MPToken, authorized by the domain. Ignore authorization flag
// lsfMPTAuthorized because it is meaningless. Return tesSUCCESS
@@ -430,7 +425,7 @@ WritableMPTokenIssuance::enforceMPTokenAuthorization(
// Could not find MPToken but there should be one because we are
// authorized by domain. Proceed to create it, then return tesSUCCESS
XRPL_ASSERT(
maybeDomainID && sleToken == nullptr,
maybeDomainID && !mptoken.exists(),
"xrpl::enforceMPTokenAuthorization : new MPToken for domain");
if (auto const err = authorizeMPToken(
priorBalance, // priorBalance
@@ -687,22 +682,21 @@ rippleUnlockEscrowMPT(
return tecINTERNAL;
} // LCOV_EXCL_STOP
// Decrease the MPT Holder EscrowedAmount
auto const mptokenID = keylet::mptoken(mptIssue.getMptID(), sender);
auto sle = view.peek(mptokenID);
if (!sle)
WritableMPToken mpt(mptIssuance, sender);
if (!mpt.exists())
{ // LCOV_EXCL_START
JLOG(j.error()) << "rippleUnlockEscrowMPT: MPToken not found for " << sender;
return tecOBJECT_NOT_FOUND;
} // LCOV_EXCL_STOP
if (!sle->isFieldPresent(sfLockedAmount))
if (!mpt->isFieldPresent(sfLockedAmount))
{ // LCOV_EXCL_START
JLOG(j.error()) << "rippleUnlockEscrowMPT: no locked amount in MPToken for "
<< to_string(sender);
return tecINTERNAL;
} // LCOV_EXCL_STOP
auto const locked = sle->getFieldU64(sfLockedAmount);
auto const locked = mpt->getFieldU64(sfLockedAmount);
auto const delta = grossAmount.mpt().value();
// Underflow check for subtraction
@@ -716,13 +710,13 @@ rippleUnlockEscrowMPT(
auto const newLocked = locked - delta;
if (newLocked == 0)
{
sle->makeFieldAbsent(sfLockedAmount);
mpt->makeFieldAbsent(sfLockedAmount);
}
else
{
sle->setFieldU64(sfLockedAmount, newLocked);
mpt->setFieldU64(sfLockedAmount, newLocked);
}
view.update(sle);
mpt.update();
// Note: The gross amount is the amount that was locked, the net
// amount is the amount that is being unlocked. The difference is the fee
@@ -782,9 +776,9 @@ MPTokenIssuance::accountHolds(
STAmount amount;
auto const sleMpt = readView_.read(keylet::mptoken(mptID_, account));
MPToken mpt(*this, account);
if (!sleMpt)
if (!mpt.exists())
{
amount.clear(mptIssue_);
}
@@ -794,7 +788,7 @@ MPTokenIssuance::accountHolds(
}
else
{
amount = STAmount{mptIssue_, sleMpt->getFieldU64(sfMPTAmount)};
amount = STAmount{mptIssue_, mpt->getFieldU64(sfMPTAmount)};
// Only if auth check is needed, as it needs to do an additional read
// operation. Note featureSingleAssetVault will affect error codes.
@@ -808,7 +802,7 @@ MPTokenIssuance::accountHolds(
{
// if auth is enabled on the issuance and mpt is not authorized,
// clear amount
if (sle_ && sle_->isFlag(lsfMPTRequireAuth) && !sleMpt->isFlag(lsfMPTAuthorized))
if (sle_ && sle_->isFlag(lsfMPTRequireAuth) && !mpt->isFlag(lsfMPTAuthorized))
amount.clear(mptIssue_);
}
}

View File

@@ -195,8 +195,7 @@ CheckCash::preclaim(PreclaimContext const& ctx)
// However, the trustline from destination to issuer may not
// be frozen.
IOUToken wrapped(ctx.view, Issue{currency, issuerId});
if (wrapped.isFrozen(dstId))
if (iouToken.isFrozen(dstId))
{
JLOG(ctx.j.warn()) << "Cashing a check to a frozen trustline.";
return tecFROZEN;

View File

@@ -830,6 +830,7 @@ tokenOfferCreatePreclaim(
std::optional<AccountID> const& owner,
std::uint32_t txFlags)
{
IOUToken token(view, amount.issue());
if (!(nftFlags & nft::flagCreateTrustLines) && !amount.native() && xferFee)
{
if (!view.exists(keylet::account(nftIssuer)))
@@ -843,13 +844,12 @@ tokenOfferCreatePreclaim(
!view.read(keylet::line(nftIssuer, amount.issue())))
return tecNO_LINE;
}
else if (!view.exists(keylet::line(nftIssuer, amount.issue())))
else if (!token.hasHolder(nftIssuer))
{
return tecNO_LINE;
}
IOUToken wrapped(view, amount.issue());
if (wrapped.isFrozen(nftIssuer))
if (token.isFrozen(nftIssuer))
return tecFROZEN;
}
@@ -862,7 +862,7 @@ tokenOfferCreatePreclaim(
return tefNFTOKEN_IS_NOT_TRANSFERABLE;
}
if (IOUToken(view, amount.issue()).isFrozen(acctID))
if (token.isFrozen(acctID))
return tecFROZEN;
// If this is an offer to buy the token, the account must have the

View File

@@ -62,8 +62,8 @@ VaultDeposit::preclaim(PreclaimContext const& ctx)
// LCOV_EXCL_STOP
}
auto const mptIssuance = MPTokenIssuance(ctx.view, vaultShare);
if (!mptIssuance)
auto const shareIssuance = MPTokenIssuance(ctx.view, vaultShare);
if (!shareIssuance)
{
// LCOV_EXCL_START
JLOG(ctx.j.error()) << "VaultDeposit: missing issuance of vault shares.";
@@ -71,7 +71,7 @@ VaultDeposit::preclaim(PreclaimContext const& ctx)
// LCOV_EXCL_STOP
}
if (mptIssuance->isFlag(lsfMPTLocked))
if (shareIssuance->isFlag(lsfMPTLocked))
{
// LCOV_EXCL_START
JLOG(ctx.j.error()) << "VaultDeposit: issuance of vault shares is locked.";
@@ -84,12 +84,12 @@ VaultDeposit::preclaim(PreclaimContext const& ctx)
return vaultAsset.holds<Issue>() ? tecFROZEN : tecLOCKED;
// Cannot deposit if the shares of the vault are frozen
if (MPTokenIssuance(ctx.view, vaultShare).isFrozen(account))
if (shareIssuance.isFrozen(account))
return tecLOCKED;
if (vault->isFlag(lsfVaultPrivate) && account != vault->at(sfOwner))
{
auto const maybeDomainID = mptIssuance->at(~sfDomainID);
auto const maybeDomainID = shareIssuance->at(~sfDomainID);
// Since this is a private vault and the account is not its owner, we
// perform authorization check based on DomainID read from mptIssuance.
// Had the vault shares been a regular MPToken, we would allow