mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-24 15:40:26 +00:00
more usage of MPToken
This commit is contained in:
@@ -37,6 +37,18 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] AccountID const&
|
||||
getIssuer() const
|
||||
{
|
||||
return issuer_;
|
||||
}
|
||||
|
||||
[[nodiscard]] Currency const&
|
||||
getCurrency() const
|
||||
{
|
||||
return currency_;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
isGlobalFrozen() const override
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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_);
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user