diff --git a/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp b/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp index f6daad8116..ab6dd118a0 100644 --- a/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp +++ b/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp @@ -61,10 +61,7 @@ MPTokenIssuance::isAnyFrozen(std::initializer_list 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_); } } diff --git a/src/libxrpl/tx/transactors/check/CheckCash.cpp b/src/libxrpl/tx/transactors/check/CheckCash.cpp index ea3911afd4..e722769c6b 100644 --- a/src/libxrpl/tx/transactors/check/CheckCash.cpp +++ b/src/libxrpl/tx/transactors/check/CheckCash.cpp @@ -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; diff --git a/src/libxrpl/tx/transactors/nft/NFTokenUtils.cpp b/src/libxrpl/tx/transactors/nft/NFTokenUtils.cpp index 75d7d8dd8c..b7ff3b2c19 100644 --- a/src/libxrpl/tx/transactors/nft/NFTokenUtils.cpp +++ b/src/libxrpl/tx/transactors/nft/NFTokenUtils.cpp @@ -830,6 +830,7 @@ tokenOfferCreatePreclaim( std::optional 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 diff --git a/src/libxrpl/tx/transactors/vault/VaultDeposit.cpp b/src/libxrpl/tx/transactors/vault/VaultDeposit.cpp index 3d1c6829f0..feb87147b6 100644 --- a/src/libxrpl/tx/transactors/vault/VaultDeposit.cpp +++ b/src/libxrpl/tx/transactors/vault/VaultDeposit.cpp @@ -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() ? 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