Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions include/xrpl/ledger/View.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ canWithdraw(
AccountID const& to,
SLE::const_ref toSle,
STAmount const& amount,
bool hasDestinationTag);
bool hasDestinationTag,
std::optional<std::vector<uint256>> const& credentialIDs = std::nullopt);

/** Checks that can withdraw funds from an object to itself or a destination.
*
Expand All @@ -170,7 +171,7 @@ canWithdraw(
* if withdrawing to self.
* - If withdrawing to self, succeed.
* - If not, checks if the receiver requires deposit authorization, and if
* the sender has it.
* the sender has it (account-based or credential-based).
* - Checks that the receiver will not exceed the limit (IOU trustline limit
* or MPT MaximumAmount).
*/
Expand All @@ -180,7 +181,8 @@ canWithdraw(
AccountID const& from,
AccountID const& to,
STAmount const& amount,
bool hasDestinationTag);
bool hasDestinationTag,
std::optional<std::vector<uint256>> const& credentialIDs = std::nullopt);

/** Checks that can withdraw funds from an object to itself or a destination.
*
Expand Down
2 changes: 2 additions & 0 deletions include/xrpl/protocol/detail/transactions.macro
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,7 @@ TRANSACTION(ttVAULT_WITHDRAW, 69, VaultWithdraw,
{sfAmount, SoeRequired, SoeMptSupported},
{sfDestination, SoeOptional},
{sfDestinationTag, SoeOptional},
{sfCredentialIDs, SoeOptional},
}))

/** This transaction claws back tokens from a vault. */
Expand Down Expand Up @@ -998,6 +999,7 @@ TRANSACTION(ttLOAN_BROKER_COVER_WITHDRAW, 77, LoanBrokerCoverWithdraw,
{sfAmount, SoeRequired, SoeMptSupported},
{sfDestination, SoeOptional},
{sfDestinationTag, SoeOptional},
{sfCredentialIDs, SoeOptional},
}))

/** This transaction claws back First Loss Capital from a Loan Broker to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,32 @@ class LoanBrokerCoverWithdraw : public TransactionBase
{
return this->tx_->isFieldPresent(sfDestinationTag);
}

/**
* @brief Get sfCredentialIDs (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_VECTOR256::type::value_type>
getCredentialIDs() const
{
if (hasCredentialIDs())
{
return this->tx_->at(sfCredentialIDs);
}
return std::nullopt;
}

/**
* @brief Check if sfCredentialIDs is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasCredentialIDs() const
{
return this->tx_->isFieldPresent(sfCredentialIDs);
}
};

/**
Expand Down Expand Up @@ -212,6 +238,17 @@ class LoanBrokerCoverWithdrawBuilder : public TransactionBuilderBase<LoanBrokerC
return *this;
}

/**
* @brief Set sfCredentialIDs (SoeOptional)
* @return Reference to this builder for method chaining.
*/
LoanBrokerCoverWithdrawBuilder&
setCredentialIDs(std::decay_t<typename SF_VECTOR256::type::value_type> const& value)
{
object_[sfCredentialIDs] = value;
return *this;
}

/**
* @brief Build and return the LoanBrokerCoverWithdraw wrapper.
* @param publicKey The public key for signing.
Expand Down
37 changes: 37 additions & 0 deletions include/xrpl/protocol_autogen/transactions/VaultWithdraw.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,32 @@ class VaultWithdraw : public TransactionBase
{
return this->tx_->isFieldPresent(sfDestinationTag);
}

/**
* @brief Get sfCredentialIDs (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_VECTOR256::type::value_type>
getCredentialIDs() const
{
if (hasCredentialIDs())
{
return this->tx_->at(sfCredentialIDs);
}
return std::nullopt;
}

/**
* @brief Check if sfCredentialIDs is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasCredentialIDs() const
{
return this->tx_->isFieldPresent(sfCredentialIDs);
}
};

/**
Expand Down Expand Up @@ -212,6 +238,17 @@ class VaultWithdrawBuilder : public TransactionBuilderBase<VaultWithdrawBuilder>
return *this;
}

/**
* @brief Set sfCredentialIDs (SoeOptional)
* @return Reference to this builder for method chaining.
*/
VaultWithdrawBuilder&
setCredentialIDs(std::decay_t<typename SF_VECTOR256::type::value_type> const& value)
{
object_[sfCredentialIDs] = value;
return *this;
}

/**
* @brief Build and return the VaultWithdraw wrapper.
* @param publicKey The public key for signing.
Expand Down
3 changes: 3 additions & 0 deletions include/xrpl/tx/transactors/vault/VaultWithdraw.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ class VaultWithdraw : public Transactor
{
}

static bool
checkExtraFeatures(PreflightContext const& ctx);

static NotTEC
preflight(PreflightContext const& ctx);

Expand Down
26 changes: 21 additions & 5 deletions src/libxrpl/ledger/View.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <cstdint>
#include <optional>
#include <set>
#include <vector>

namespace xrpl {

Expand Down Expand Up @@ -390,7 +391,8 @@ canWithdraw(
AccountID const& to,
SLE::const_ref toSle,
STAmount const& amount,
bool hasDestinationTag)
bool hasDestinationTag,
std::optional<std::vector<uint256>> const& credentialIDs)
{
if (auto const ret = checkDestinationAndTag(toSle, hasDestinationTag))
return ret;
Expand All @@ -401,7 +403,19 @@ canWithdraw(
if (toSle->isFlag(lsfDepositAuth))
{
if (!view.exists(keylet::depositPreauth(to, from)))
return tecNO_PERMISSION;
{
if (credentialIDs.has_value())
{
if (auto const ret = credentials::authorizedDepositPreauth(
view, STVector256{*credentialIDs}, to);
!isTesSuccess(ret))
return ret;
}
else
{
return tecNO_PERMISSION;
}
}
}

return withdrawToDestExceedsLimit(view, from, to, amount);
Expand All @@ -413,11 +427,12 @@ canWithdraw(
AccountID const& from,
AccountID const& to,
STAmount const& amount,
bool hasDestinationTag)
bool hasDestinationTag,
std::optional<std::vector<uint256>> const& credentialIDs)
{
auto const toSle = view.read(keylet::account(to));

return canWithdraw(view, from, to, toSle, amount, hasDestinationTag);
return canWithdraw(view, from, to, toSle, amount, hasDestinationTag, credentialIDs);
}

[[nodiscard]] TER
Expand All @@ -426,7 +441,8 @@ canWithdraw(ReadView const& view, STTx const& tx)
auto const from = tx[sfAccount];
auto const to = tx[~sfDestination].value_or(from);

return canWithdraw(view, from, to, tx[sfAmount], tx.isFieldPresent(sfDestinationTag));
return canWithdraw(
view, from, to, tx[sfAmount], tx.isFieldPresent(sfDestinationTag), tx[~sfCredentialIDs]);
}

TER
Expand Down
16 changes: 15 additions & 1 deletion src/libxrpl/tx/transactors/lending/LoanBrokerCoverWithdraw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/LendingHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/Feature.h>
Expand All @@ -25,7 +26,11 @@ namespace xrpl {
bool
LoanBrokerCoverWithdraw::checkExtraFeatures(PreflightContext const& ctx)
{
return checkLendingProtocolDependencies(ctx.rules, ctx.tx);
if (!checkLendingProtocolDependencies(ctx.rules, ctx.tx))
return false;

return !ctx.tx.isFieldPresent(sfCredentialIDs) ||
(ctx.rules.enabled(featureCredentials) && ctx.rules.enabled(fixCleanup3_2_0));
}

NotTEC
Expand All @@ -49,6 +54,9 @@ LoanBrokerCoverWithdraw::preflight(PreflightContext const& ctx)
}
}

if (auto const err = credentials::checkFields(ctx.tx, ctx.j); !isTesSuccess(err))
return err;

return tesSUCCESS;
}

Expand Down Expand Up @@ -108,6 +116,12 @@ LoanBrokerCoverWithdraw::preclaim(PreclaimContext const& ctx)
if (auto const ret = canTransfer(ctx.view, vaultAsset, pseudoAccountID, dstAcct, waive))
return ret;

// Validate credentials (if any) before canWithdraw, since canWithdraw may
// call credentials::authorizedDepositPreauth which assumes credentials
// already exist.
if (auto const err = credentials::valid(ctx.tx, ctx.view, account, ctx.j); !isTesSuccess(err))
return err;

// Withdrawal to a 3rd party destination account is essentially a transfer.
// Enforce all the usual asset transfer checks.
AuthType authType = AuthType::WeakAuth;
Expand Down
20 changes: 19 additions & 1 deletion src/libxrpl/tx/transactors/vault/VaultWithdraw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/ledger/helpers/VaultHelpers.h>
#include <xrpl/protocol/AccountID.h>
Expand All @@ -27,6 +28,13 @@

namespace xrpl {

bool
VaultWithdraw::checkExtraFeatures(PreflightContext const& ctx)
{
return !ctx.tx.isFieldPresent(sfCredentialIDs) ||
(ctx.rules.enabled(featureCredentials) && ctx.rules.enabled(fixCleanup3_2_0));
}

static WaiveUnrealizedLoss
shouldWaiveWithdrawal(ReadView const& view, AccountID const& account, SLE::const_ref issuance)
{
Expand Down Expand Up @@ -59,6 +67,9 @@ VaultWithdraw::preflight(PreflightContext const& ctx)
}
}

if (auto const err = credentials::checkFields(ctx.tx, ctx.j); !isTesSuccess(err))
return err;

return tesSUCCESS;
}

Expand Down Expand Up @@ -100,6 +111,12 @@ VaultWithdraw::preclaim(PreclaimContext const& ctx)
// LCOV_EXCL_STOP
}

// Validate credentials (if any) before canWithdraw, since canWithdraw may
// call credentials::authorizedDepositPreauth which assumes credentials
// already exist.
if (auto const err = credentials::valid(ctx.tx, ctx.view, account, ctx.j); !isTesSuccess(err))
return err;

if (ctx.view.rules().enabled(fixCleanup3_1_3) && amount.asset() == vaultShare)
{
// Post-fixCleanup3_1_3: if the user specified shares, convert
Expand Down Expand Up @@ -131,7 +148,8 @@ VaultWithdraw::preclaim(PreclaimContext const& ctx)
account,
dstAcct,
*maybeAssets,
ctx.tx.isFieldPresent(sfDestinationTag)))
ctx.tx.isFieldPresent(sfDestinationTag),
ctx.tx[~sfCredentialIDs]))
return ret;
}
catch (std::overflow_error const&)
Expand Down
Loading
Loading