mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Start implementing LoanManage transaction (untested)
- Also add a ValidLoan invariant
This commit is contained in:
@@ -759,6 +759,7 @@ TRANSACTION(ttLOAN_SET, 78, LoanSet, noPriv, ({
|
|||||||
TRANSACTION(ttLOAN_DELETE, 79, LoanDelete, noPriv, ({
|
TRANSACTION(ttLOAN_DELETE, 79, LoanDelete, noPriv, ({
|
||||||
{sfLoanID, soeREQUIRED},
|
{sfLoanID, soeREQUIRED},
|
||||||
}))
|
}))
|
||||||
|
#endif
|
||||||
|
|
||||||
/** This transaction is used to change the delinquency status of an existing Loan */
|
/** This transaction is used to change the delinquency status of an existing Loan */
|
||||||
#if TRANSACTION_INCLUDE
|
#if TRANSACTION_INCLUDE
|
||||||
@@ -768,6 +769,7 @@ TRANSACTION(ttLOAN_MANAGE, 80, LoanManage, noPriv, ({
|
|||||||
{sfLoanID, soeREQUIRED},
|
{sfLoanID, soeREQUIRED},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
#if 0
|
||||||
/** The Borrower uses this transaction to draws funds from the Loan. */
|
/** The Borrower uses this transaction to draws funds from the Loan. */
|
||||||
#if TRANSACTION_INCLUDE
|
#if TRANSACTION_INCLUDE
|
||||||
# include <xrpld/app/tx/detail/LoanDraw.h>
|
# include <xrpld/app/tx/detail/LoanDraw.h>
|
||||||
|
|||||||
@@ -1953,4 +1953,46 @@ ValidLoanBroker::finalize(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void
|
||||||
|
ValidLoan::visitEntry(
|
||||||
|
bool isDelete,
|
||||||
|
std::shared_ptr<SLE const> const& before,
|
||||||
|
std::shared_ptr<SLE const> const& after)
|
||||||
|
{
|
||||||
|
if (after && after->getType() == ltLOAN)
|
||||||
|
{
|
||||||
|
loans_.emplace_back(before, after);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ValidLoan::finalize(
|
||||||
|
STTx const& tx,
|
||||||
|
TER const,
|
||||||
|
XRPAmount const,
|
||||||
|
ReadView const& view,
|
||||||
|
beast::Journal const& j)
|
||||||
|
{
|
||||||
|
bool const enforce = view.rules().enabled(featureLendingProtocol);
|
||||||
|
|
||||||
|
for (auto const& [before, after] : loans_)
|
||||||
|
{
|
||||||
|
// https://github.com/Tapanito/XRPL-Standards/blob/xls-66-lending-protocol/XLS-0066d-lending-protocol/README.md#3223-invariants
|
||||||
|
// If `Loan.PaymentRemaining = 0` then `Loan.PrincipalOutstanding = 0`
|
||||||
|
if (after->at(sfPaymentRemaining) == 0 &&
|
||||||
|
after->at(sfPrincipalOutstanding) != 0)
|
||||||
|
{
|
||||||
|
XRPL_ASSERT(
|
||||||
|
enforce,
|
||||||
|
"ripple::ValidLoan::finalize : Enforcing "
|
||||||
|
"invariant: zero payments remaining");
|
||||||
|
if (enforce)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|||||||
@@ -717,6 +717,34 @@ public:
|
|||||||
beast::Journal const&);
|
beast::Journal const&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Invariants: Loans are internally consistent
|
||||||
|
*
|
||||||
|
* 1. If `Loan.PaymentRemaining = 0` then `Loan.PrincipalOutstanding = 0`
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class ValidLoan
|
||||||
|
{
|
||||||
|
// Pair is <before, after>. After is used for most of the checks, except
|
||||||
|
// those that check changed values.
|
||||||
|
std::vector<std::pair<SLE::const_pointer, SLE::const_pointer>> loans_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void
|
||||||
|
visitEntry(
|
||||||
|
bool,
|
||||||
|
std::shared_ptr<SLE const> const&,
|
||||||
|
std::shared_ptr<SLE const> const&);
|
||||||
|
|
||||||
|
bool
|
||||||
|
finalize(
|
||||||
|
STTx const&,
|
||||||
|
TER const,
|
||||||
|
XRPAmount const,
|
||||||
|
ReadView const&,
|
||||||
|
beast::Journal const&);
|
||||||
|
};
|
||||||
|
|
||||||
// additional invariant checks can be declared above and then added to this
|
// additional invariant checks can be declared above and then added to this
|
||||||
// tuple
|
// tuple
|
||||||
using InvariantChecks = std::tuple<
|
using InvariantChecks = std::tuple<
|
||||||
@@ -739,7 +767,8 @@ using InvariantChecks = std::tuple<
|
|||||||
ValidPermissionedDomain,
|
ValidPermissionedDomain,
|
||||||
NoModifiedUnmodifiableFields,
|
NoModifiedUnmodifiableFields,
|
||||||
ValidPseudoAccounts,
|
ValidPseudoAccounts,
|
||||||
ValidLoanBroker>;
|
ValidLoanBroker,
|
||||||
|
ValidLoan>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get a tuple of all invariant checks
|
* @brief get a tuple of all invariant checks
|
||||||
|
|||||||
313
src/xrpld/app/tx/detail/LoanManage.cpp
Normal file
313
src/xrpld/app/tx/detail/LoanManage.cpp
Normal file
@@ -0,0 +1,313 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2025 Ripple Labs Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include <xrpld/app/tx/detail/LoanManage.h>
|
||||||
|
//
|
||||||
|
#include <xrpld/app/tx/detail/LoanBrokerSet.h>
|
||||||
|
#include <xrpld/ledger/ApplyView.h>
|
||||||
|
#include <xrpld/ledger/View.h>
|
||||||
|
|
||||||
|
#include <xrpl/basics/Log.h>
|
||||||
|
#include <xrpl/basics/Number.h>
|
||||||
|
#include <xrpl/basics/chrono.h>
|
||||||
|
#include <xrpl/beast/utility/Journal.h>
|
||||||
|
#include <xrpl/beast/utility/instrumentation.h>
|
||||||
|
#include <xrpl/protocol/AccountID.h>
|
||||||
|
#include <xrpl/protocol/Feature.h>
|
||||||
|
#include <xrpl/protocol/Indexes.h>
|
||||||
|
#include <xrpl/protocol/Protocol.h>
|
||||||
|
#include <xrpl/protocol/PublicKey.h>
|
||||||
|
#include <xrpl/protocol/SField.h>
|
||||||
|
#include <xrpl/protocol/STAmount.h>
|
||||||
|
#include <xrpl/protocol/STNumber.h>
|
||||||
|
#include <xrpl/protocol/STObject.h>
|
||||||
|
#include <xrpl/protocol/STXChainBridge.h>
|
||||||
|
#include <xrpl/protocol/TER.h>
|
||||||
|
#include <xrpl/protocol/TxFlags.h>
|
||||||
|
#include <xrpl/protocol/XRPAmount.h>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
|
||||||
|
bool
|
||||||
|
LoanManage::isEnabled(PreflightContext const& ctx)
|
||||||
|
{
|
||||||
|
return lendingProtocolEnabled(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t
|
||||||
|
LoanManage::getFlagsMask(PreflightContext const& ctx)
|
||||||
|
{
|
||||||
|
return tfLoanManageMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
NotTEC
|
||||||
|
LoanManage::doPreflight(PreflightContext const& ctx)
|
||||||
|
{
|
||||||
|
// Is combining flags legal?
|
||||||
|
int numFlags = 0;
|
||||||
|
for (auto const flag : {
|
||||||
|
tfLoanDefault,
|
||||||
|
tfLoanImpair,
|
||||||
|
tfLoanUnimpair,
|
||||||
|
})
|
||||||
|
{
|
||||||
|
if (ctx.tx.isFlag(flag))
|
||||||
|
++numFlags;
|
||||||
|
}
|
||||||
|
if (numFlags > 1)
|
||||||
|
{
|
||||||
|
JLOG(ctx.j.warn())
|
||||||
|
<< "LoanManage: Only one of tfLoanDefault, tfLoanImpair, or "
|
||||||
|
"tfLoanUnimpair can be set.";
|
||||||
|
return temINVALID_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tesSUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
TER
|
||||||
|
LoanManage::preclaim(PreclaimContext const& ctx)
|
||||||
|
{
|
||||||
|
auto const& tx = ctx.tx;
|
||||||
|
|
||||||
|
auto const account = tx[sfAccount];
|
||||||
|
auto const loanID = tx[sfLoanID];
|
||||||
|
|
||||||
|
auto const loanSle = ctx.view.read(keylet::loan(loanID));
|
||||||
|
if (!loanSle)
|
||||||
|
{
|
||||||
|
JLOG(ctx.j.warn()) << "Loan does not exist.";
|
||||||
|
return tecNO_ENTRY;
|
||||||
|
}
|
||||||
|
// Impairment only allows certain transitions.
|
||||||
|
// 1. Once it's in default, it can't be changed.
|
||||||
|
// 2. It can get worse: unimpaired -> impaired -> default
|
||||||
|
// 3. It can get better: impaired -> unimpaired
|
||||||
|
// 4. If it's in a state, it can't be put in that state again.
|
||||||
|
// TODO: implement this.
|
||||||
|
if (loanSle->isFlag(lsfLoanDefault))
|
||||||
|
{
|
||||||
|
JLOG(ctx.j.warn())
|
||||||
|
<< "Loan is in default. A defaulted loan can not be modified.";
|
||||||
|
return tecNO_PERMISSION;
|
||||||
|
}
|
||||||
|
if (loanSle->isFlag(lsfLoanImpaired) && tx.isFlag(tfLoanImpair))
|
||||||
|
{
|
||||||
|
JLOG(ctx.j.warn())
|
||||||
|
<< "Loan is impaired. A loan can not be impaired twice.";
|
||||||
|
return tecNO_PERMISSION;
|
||||||
|
}
|
||||||
|
if (loanSle->at(sfPaymentRemaining) == 0)
|
||||||
|
{
|
||||||
|
JLOG(ctx.j.warn()) << "Loan is fully paid. A loan can not be modified "
|
||||||
|
"after it is fully paid.";
|
||||||
|
return tecNO_PERMISSION;
|
||||||
|
}
|
||||||
|
if (tx.isFlag(tfLoanDefault) &&
|
||||||
|
!hasExpired(
|
||||||
|
ctx.view,
|
||||||
|
loanSle->at(sfNextPaymentDueDate) + loanSle->at(sfGracePeriod)))
|
||||||
|
{
|
||||||
|
JLOG(ctx.j.warn())
|
||||||
|
<< "Loan is not in default. A loan can not be defaulted before the "
|
||||||
|
"next payment due date.";
|
||||||
|
return tecTOO_SOON;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const loanBrokerID = loanSle->at(sfLoanBrokerID);
|
||||||
|
auto const loanBrokerSle = ctx.view.read(keylet::loanbroker(loanBrokerID));
|
||||||
|
if (!loanBrokerSle)
|
||||||
|
{
|
||||||
|
// should be impossible
|
||||||
|
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||||
|
}
|
||||||
|
if (loanBrokerSle->at(sfOwner) != account)
|
||||||
|
{
|
||||||
|
JLOG(ctx.j.warn())
|
||||||
|
<< "LoanBroker for Loan does not belong to the account.";
|
||||||
|
return tecNO_PERMISSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tesSUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
TER
|
||||||
|
defaultLoan(
|
||||||
|
ApplyView& view,
|
||||||
|
SLE::ref loanSle,
|
||||||
|
SLE::ref brokerSle,
|
||||||
|
SLE::ref vaultSle,
|
||||||
|
Number const& principalOutstanding,
|
||||||
|
Number const& interestOutstanding,
|
||||||
|
beast::Journal j)
|
||||||
|
{
|
||||||
|
return temDISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
TER
|
||||||
|
impairLoan(
|
||||||
|
ApplyView& view,
|
||||||
|
SLE::ref loanSle,
|
||||||
|
SLE::ref brokerSle,
|
||||||
|
SLE::ref vaultSle,
|
||||||
|
Number const& principalOutstanding,
|
||||||
|
Number const& interestOutstanding,
|
||||||
|
beast::Journal j)
|
||||||
|
{
|
||||||
|
// Update the Vault object(set "paper loss")
|
||||||
|
vaultSle->at(sfLossUnrealized) +=
|
||||||
|
principalOutstanding + interestOutstanding;
|
||||||
|
view.update(vaultSle);
|
||||||
|
|
||||||
|
// Update the Loan object
|
||||||
|
loanSle->at(sfFlags) = lsfLoanImpaired;
|
||||||
|
auto nextDueProxy = loanSle->at(sfNextPaymentDueDate);
|
||||||
|
if (!hasExpired(view, nextDueProxy))
|
||||||
|
{
|
||||||
|
// loan payment is not yet late -
|
||||||
|
// move the next payment due date to now
|
||||||
|
nextDueProxy = view.parentCloseTime().time_since_epoch().count();
|
||||||
|
}
|
||||||
|
view.update(loanSle);
|
||||||
|
|
||||||
|
return tesSUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
TER
|
||||||
|
unimpairLoan(
|
||||||
|
ApplyView& view,
|
||||||
|
SLE::ref loanSle,
|
||||||
|
SLE::ref brokerSle,
|
||||||
|
SLE::ref vaultSle,
|
||||||
|
Number const& principalOutstanding,
|
||||||
|
Number const& interestOutstanding,
|
||||||
|
beast::Journal j)
|
||||||
|
{
|
||||||
|
// Update the Vault object(clear "paper loss")
|
||||||
|
vaultSle->at(sfLossUnrealized) -=
|
||||||
|
principalOutstanding + interestOutstanding;
|
||||||
|
view.update(vaultSle);
|
||||||
|
|
||||||
|
// Update the Loan object
|
||||||
|
loanSle->at(sfFlags) = 0;
|
||||||
|
auto const paymentInterval = loanSle->at(sfPaymentInterval);
|
||||||
|
auto const normalPaymentDueDate =
|
||||||
|
loanSle->at(sfPreviousPaymentDate) + paymentInterval;
|
||||||
|
if (!hasExpired(view, normalPaymentDueDate))
|
||||||
|
{
|
||||||
|
// loan was unimpaired within the payment interval
|
||||||
|
loanSle->at(sfNextPaymentDueDate) = normalPaymentDueDate;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// loan was unimpaired after the original payment due date
|
||||||
|
loanSle->at(sfNextPaymentDueDate) =
|
||||||
|
view.parentCloseTime().time_since_epoch().count() +
|
||||||
|
loanSle->at(sfPaymentInterval);
|
||||||
|
}
|
||||||
|
view.update(loanSle);
|
||||||
|
|
||||||
|
return tesSUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
TER
|
||||||
|
LoanManage::doApply()
|
||||||
|
{
|
||||||
|
auto const& tx = ctx_.tx;
|
||||||
|
auto& view = ctx_.view();
|
||||||
|
|
||||||
|
auto const loanID = tx[sfLoanID];
|
||||||
|
auto const loanSle = view.peek(keylet::loan(loanID));
|
||||||
|
if (!loanSle)
|
||||||
|
return tefBAD_LEDGER; // LCOV_EXCL_LINE
|
||||||
|
|
||||||
|
auto const brokerID = loanSle->at(sfLoanBrokerID);
|
||||||
|
auto const brokerSle = view.peek(keylet::loanbroker(brokerID));
|
||||||
|
if (!brokerSle)
|
||||||
|
return tefBAD_LEDGER; // LCOV_EXCL_LINE
|
||||||
|
|
||||||
|
auto const vaultSle = view.peek(keylet ::vault(brokerSle->at(sfVaultID)));
|
||||||
|
if (!vaultSle)
|
||||||
|
return tefBAD_LEDGER; // LCOV_EXCL_LINE
|
||||||
|
auto const vaultAsset = vaultSle->at(sfAsset);
|
||||||
|
|
||||||
|
TenthBips32 const interestRate{loanSle->at(sfInterestRate)};
|
||||||
|
auto const principalOutstanding = loanSle->at(sfPrincipalOutstanding);
|
||||||
|
auto const interestOutstanding =
|
||||||
|
tenthBipsOfValue(principalOutstanding, interestRate);
|
||||||
|
|
||||||
|
// Valid flag combinations are checked in preflight. Not flags is valid -
|
||||||
|
// just a noop.
|
||||||
|
if (tx.isFlag(tfLoanDefault))
|
||||||
|
{
|
||||||
|
if (auto const ter = defaultLoan(
|
||||||
|
view,
|
||||||
|
loanSle,
|
||||||
|
brokerSle,
|
||||||
|
vaultSle,
|
||||||
|
principalOutstanding,
|
||||||
|
interestOutstanding,
|
||||||
|
j_))
|
||||||
|
return ter;
|
||||||
|
}
|
||||||
|
if (tx.isFlag(tfLoanImpair))
|
||||||
|
{
|
||||||
|
if (auto const ter = impairLoan(
|
||||||
|
view,
|
||||||
|
loanSle,
|
||||||
|
brokerSle,
|
||||||
|
vaultSle,
|
||||||
|
principalOutstanding,
|
||||||
|
interestOutstanding,
|
||||||
|
j_))
|
||||||
|
return ter;
|
||||||
|
}
|
||||||
|
if (tx.isFlag(tfLoanUnimpair))
|
||||||
|
{
|
||||||
|
if (auto const ter = unimpairLoan(
|
||||||
|
view,
|
||||||
|
loanSle,
|
||||||
|
brokerSle,
|
||||||
|
vaultSle,
|
||||||
|
principalOutstanding,
|
||||||
|
interestOutstanding,
|
||||||
|
j_))
|
||||||
|
return ter;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
auto const brokerOwner = brokerSle->at(sfOwner);
|
||||||
|
auto const brokerOwnerSle = view.peek(keylet::account(brokerOwner));
|
||||||
|
|
||||||
|
auto const vaultPseudo = vaultSle->at(sfAccount);
|
||||||
|
|
||||||
|
auto const brokerPseudo = brokerSle->at(sfAccount);
|
||||||
|
auto const brokerPseudoSle = view.peek(keylet::account(brokerPseudo));
|
||||||
|
auto const principalRequested = tx[sfPrincipalRequested];
|
||||||
|
TenthBips32 const interestRate{tx[~sfInterestRate].value_or(0)};
|
||||||
|
auto const originationFee = tx[~sfLoanOriginationFee];
|
||||||
|
auto const loanAssetsAvailable =
|
||||||
|
principalRequested - originationFee.value_or(Number{});
|
||||||
|
*/
|
||||||
|
|
||||||
|
return tesSUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace ripple
|
||||||
56
src/xrpld/app/tx/detail/LoanManage.h
Normal file
56
src/xrpld/app/tx/detail/LoanManage.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2025 Ripple Labs Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#ifndef RIPPLE_TX_LOANMANAGE_H_INCLUDED
|
||||||
|
#define RIPPLE_TX_LOANMANAGE_H_INCLUDED
|
||||||
|
|
||||||
|
#include <xrpld/app/tx/detail/Transactor.h>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
|
||||||
|
class LoanManage : public Transactor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||||
|
|
||||||
|
explicit LoanManage(ApplyContext& ctx) : Transactor(ctx)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
isEnabled(PreflightContext const& ctx);
|
||||||
|
|
||||||
|
static std::uint32_t
|
||||||
|
getFlagsMask(PreflightContext const& ctx);
|
||||||
|
|
||||||
|
static NotTEC
|
||||||
|
doPreflight(PreflightContext const& ctx);
|
||||||
|
|
||||||
|
static TER
|
||||||
|
preclaim(PreclaimContext const& ctx);
|
||||||
|
|
||||||
|
TER
|
||||||
|
doApply() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace ripple
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user