mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Remove conditional LoanDraw code
This commit is contained in:
@@ -563,11 +563,6 @@ LEDGER_ENTRY(ltLOAN, 0x0089, Loan, loan, ({
|
||||
{sfPreviousPaymentDate, soeREQUIRED},
|
||||
{sfNextPaymentDueDate, soeREQUIRED},
|
||||
{sfPaymentRemaining, soeREQUIRED},
|
||||
//#if LOANDRAW
|
||||
// TODO: Remove this when you remove the rest of the LOANDRAW blocks.
|
||||
// Directives don't work with macro expansion.
|
||||
{sfAssetsAvailable, soeDEFAULT},
|
||||
//#endif
|
||||
{sfPrincipalOutstanding, soeREQUIRED},
|
||||
// Save the original request amount for rounding / scaling of
|
||||
// other computations, particularly for IOUs
|
||||
|
||||
@@ -1065,20 +1065,6 @@ TRANSACTION(ttLOAN_MANAGE, 82, LoanManage,
|
||||
{sfLoanID, soeREQUIRED},
|
||||
}))
|
||||
|
||||
#if LOANDRAW
|
||||
/** The Borrower uses this transaction to draws funds from the Loan. */
|
||||
#if TRANSACTION_INCLUDE
|
||||
# include <xrpld/app/tx/detail/LoanDraw.h>
|
||||
#endif
|
||||
TRANSACTION(ttLOAN_DRAW, 83, LoanDraw,
|
||||
Delegation::delegatable,
|
||||
featureLendingProtocol,
|
||||
noPriv, ({
|
||||
{sfLoanID, soeREQUIRED},
|
||||
{sfAmount, soeREQUIRED, soeMPTSupported},
|
||||
}))
|
||||
#endif
|
||||
|
||||
/** The Borrower uses this transaction to make a Payment on the Loan. */
|
||||
#if TRANSACTION_INCLUDE
|
||||
# include <xrpld/app/tx/detail/LoanPay.h>
|
||||
|
||||
@@ -86,11 +86,7 @@ class Loan_test : public beast::unit_test::suite
|
||||
env(del(alice, loanKeylet.key), ter(temDISABLED));
|
||||
// 3. LoanManage
|
||||
env(manage(alice, loanKeylet.key, tfLoanImpair), ter(temDISABLED));
|
||||
#if LOANDRAW && 0
|
||||
// 4. LoanDraw
|
||||
env(draw(alice, loanKeylet.key, XRP(500)), ter(temDISABLED));
|
||||
#endif
|
||||
// 5. LoanPay
|
||||
// 4. LoanPay
|
||||
env(pay(alice, loanKeylet.key, XRP(500)), ter(temDISABLED));
|
||||
};
|
||||
failAll(all - featureMPTokensV1);
|
||||
@@ -237,9 +233,6 @@ class Loan_test : public beast::unit_test::suite
|
||||
loan->at(sfNextPaymentDueDate) == nextPaymentDate);
|
||||
env.test.BEAST_EXPECT(
|
||||
loan->at(sfPaymentRemaining) == paymentRemaining);
|
||||
#if LOANDRAW
|
||||
env.test.BEAST_EXPECT(loan->at(sfAssetsAvailable) == 0);
|
||||
#endif
|
||||
env.test.BEAST_EXPECT(
|
||||
loan->at(sfPrincipalRequested) == principalRequested);
|
||||
env.test.BEAST_EXPECT(
|
||||
@@ -618,9 +611,6 @@ class Loan_test : public beast::unit_test::suite
|
||||
BEAST_EXPECT(
|
||||
loan->at(sfNextPaymentDueDate) == startDate + interval);
|
||||
BEAST_EXPECT(loan->at(sfPaymentRemaining) == total);
|
||||
#if LOANDRAW
|
||||
BEAST_EXPECT(loan->at(sfAssetsAvailable) == beast::zero);
|
||||
#endif
|
||||
BEAST_EXPECT(loan->at(sfPrincipalRequested) == principalRequest);
|
||||
BEAST_EXPECT(loan->at(sfPrincipalOutstanding) == principalRequest);
|
||||
}
|
||||
@@ -1258,15 +1248,6 @@ class Loan_test : public beast::unit_test::suite
|
||||
// defaulted
|
||||
env.close(nextDueDate + 60s);
|
||||
|
||||
#if LOANDRAW && 0
|
||||
if (impair)
|
||||
{
|
||||
// Impaired loans can't be drawn against
|
||||
env(draw(borrower, loanKeylet.key, broker.asset(100)),
|
||||
ter(tecNO_PERMISSION));
|
||||
}
|
||||
#endif
|
||||
|
||||
auto const [amountToBeCovered, brokerAcct] =
|
||||
getDefaultInfo(state, broker);
|
||||
|
||||
@@ -1287,12 +1268,6 @@ class Loan_test : public beast::unit_test::suite
|
||||
state.principalOutstanding = 0;
|
||||
verifyLoanStatus(state);
|
||||
|
||||
#if LOANDRAW && 0
|
||||
// Defaulted loans can't be drawn against, either
|
||||
env(draw(borrower, loanKeylet.key, broker.asset(100)),
|
||||
ter(tecNO_PERMISSION));
|
||||
#endif
|
||||
|
||||
// Once a loan is defaulted, it can't be managed
|
||||
env(manage(lender, loanKeylet.key, tfLoanUnimpair),
|
||||
ter(tecNO_PERMISSION));
|
||||
@@ -1310,45 +1285,13 @@ class Loan_test : public beast::unit_test::suite
|
||||
auto state =
|
||||
getCurrentState(env, broker, loanKeylet, verifyLoanStatus);
|
||||
BEAST_EXPECT(state.flags == baseFlag);
|
||||
#if LOANDRAW && 0
|
||||
auto const borrowerStartingBalance =
|
||||
env.balance(borrower, broker.asset);
|
||||
|
||||
// Try to make a payment before the loan starts
|
||||
env(pay(borrower, loanKeylet.key, broker.asset(500)),
|
||||
ter(tecTOO_SOON));
|
||||
|
||||
// Advance to the start date of the loan
|
||||
env.close(state.startDate + 5s);
|
||||
|
||||
verifyLoanStatus(state);
|
||||
|
||||
// Need to account for fees if the loan is in XRP
|
||||
PrettyAmount adjustment = broker.asset(0);
|
||||
if (broker.asset.raw().native())
|
||||
{
|
||||
adjustment = 2 * env.current()->fees().base;
|
||||
}
|
||||
|
||||
// Draw the entire available balance
|
||||
// Need to create the STAmount directly to avoid
|
||||
// PrettyAsset scaling.
|
||||
STAmount const drawAmount{broker.asset, state.assetsAvailable};
|
||||
env(draw(borrower, loanKeylet.key, drawAmount));
|
||||
#else
|
||||
STAmount const drawAmount =
|
||||
STAmount(broker.asset, state.principalRequested - 1);
|
||||
#endif
|
||||
env.close(state.startDate + 20s);
|
||||
auto const loanAge = (env.now() - state.startDate).count();
|
||||
BEAST_EXPECT(loanAge == 30);
|
||||
|
||||
verifyLoanStatus(state);
|
||||
#if LOANDRAW && 0
|
||||
BEAST_EXPECT(
|
||||
env.balance(borrower, broker.asset) ==
|
||||
borrowerStartingBalance + drawAmount - adjustment);
|
||||
#endif
|
||||
|
||||
// Send some bogus pay transactions
|
||||
env(pay(borrower,
|
||||
@@ -1544,64 +1487,8 @@ class Loan_test : public beast::unit_test::suite
|
||||
broker.brokerID,
|
||||
broker.asset(coverDepositParameter).number());
|
||||
|
||||
#if LOANDRAW && 0
|
||||
auto const borrowerStartingBalance =
|
||||
env.balance(borrower, broker.asset);
|
||||
|
||||
// Draw the balance
|
||||
env(draw(
|
||||
borrower,
|
||||
keylet::loan(uint256(0)).key,
|
||||
broker.asset(10)),
|
||||
ter(temINVALID));
|
||||
env(draw(borrower, loanKeylet.key, broker.asset(-100)),
|
||||
ter(temBAD_AMOUNT));
|
||||
env(draw(borrower, broker.brokerID, broker.asset(100)),
|
||||
ter(tecNO_ENTRY));
|
||||
env(draw(evan, loanKeylet.key, broker.asset(500)),
|
||||
ter(tecNO_PERMISSION));
|
||||
env(draw(borrower, loanKeylet.key, broker.asset(500)),
|
||||
ter(tecTOO_SOON));
|
||||
|
||||
// Advance to the start date of the loan
|
||||
env.close(state.startDate + 5s);
|
||||
env(draw(borrower, loanKeylet.key, broker.asset(10000)),
|
||||
ter(tecINSUFFICIENT_FUNDS));
|
||||
{
|
||||
auto const otherAsset =
|
||||
broker.asset.raw() == assets[0].raw() ? assets[1]
|
||||
: assets[0];
|
||||
env(draw(borrower, loanKeylet.key, otherAsset(100)),
|
||||
ter(tecWRONG_ASSET));
|
||||
}
|
||||
|
||||
verifyLoanStatus(state);
|
||||
|
||||
// Need to account for fees if the loan is in XRP
|
||||
PrettyAmount adjustment = broker.asset(0);
|
||||
if (broker.asset.raw().native())
|
||||
{
|
||||
adjustment = 5 * env.current()->fees().base;
|
||||
}
|
||||
|
||||
// Draw about half the balance
|
||||
auto const drawAmount = broker.asset(500);
|
||||
env(draw(borrower, loanKeylet.key, drawAmount));
|
||||
|
||||
state.assetsAvailable -= drawAmount.number();
|
||||
verifyLoanStatus(state);
|
||||
BEAST_EXPECT(
|
||||
env.balance(borrower, broker.asset) ==
|
||||
borrowerStartingBalance + drawAmount - adjustment);
|
||||
#endif
|
||||
|
||||
// move past the due date + grace period (60s)
|
||||
env.close(tp{d{state.nextPaymentDate}} + 60s + 20s);
|
||||
#if LOANDRAW && 0
|
||||
// Try to draw
|
||||
env(draw(borrower, loanKeylet.key, broker.asset(100)),
|
||||
ter(tecNO_PERMISSION));
|
||||
#endif
|
||||
|
||||
auto const [amountToBeCovered, brokerAcct] =
|
||||
getDefaultInfo(state, broker);
|
||||
@@ -1624,12 +1511,6 @@ class Loan_test : public beast::unit_test::suite
|
||||
|
||||
verifyLoanStatus(state);
|
||||
|
||||
#if LOANDRAW && 0
|
||||
// Same error, different check
|
||||
env(draw(borrower, loanKeylet.key, broker.asset(100)),
|
||||
ter(tecNO_PERMISSION));
|
||||
#endif
|
||||
|
||||
// Can't make a payment on it either
|
||||
env(pay(borrower, loanKeylet.key, broker.asset(300)),
|
||||
ter(tecKILLED));
|
||||
@@ -1689,34 +1570,10 @@ class Loan_test : public beast::unit_test::suite
|
||||
|
||||
verifyLoanStatus(state);
|
||||
|
||||
#if LOANDRAW && 0
|
||||
auto const borrowerStartingBalance =
|
||||
env.balance(borrower, broker.asset);
|
||||
|
||||
// Need to account for fees if the loan is in XRP
|
||||
PrettyAmount adjustment = broker.asset(0);
|
||||
if (broker.asset.raw().native())
|
||||
{
|
||||
adjustment = env.current()->fees().base;
|
||||
}
|
||||
|
||||
// Draw the entire available balance
|
||||
// Need to create the STAmount directly to avoid
|
||||
// PrettyAsset scaling.
|
||||
STAmount const drawAmount{broker.asset, state.assetsAvailable};
|
||||
env(draw(borrower, loanKeylet.key, drawAmount));
|
||||
#endif
|
||||
env.close(state.startDate + 20s);
|
||||
auto const loanAge = (env.now() - state.startDate).count();
|
||||
BEAST_EXPECT(loanAge == 30);
|
||||
|
||||
#if LOANDRAW && 0
|
||||
verifyLoanStatus(state);
|
||||
BEAST_EXPECT(
|
||||
env.balance(borrower, broker.asset) ==
|
||||
borrowerStartingBalance + drawAmount - adjustment);
|
||||
#endif
|
||||
|
||||
// Periodic payment amount will consist of
|
||||
// 1. principal outstanding (1000)
|
||||
// 2. interest interest rate (at 12%)
|
||||
@@ -2145,11 +2002,6 @@ class Loan_test : public beast::unit_test::suite
|
||||
|
||||
env.close(startDate);
|
||||
|
||||
#if LOANDRAW && 0
|
||||
// Draw the loan
|
||||
env(draw(lender, loanKeylet.key, broker.asset(1000)));
|
||||
env.close();
|
||||
#endif
|
||||
// Make a payment
|
||||
env(pay(lender, loanKeylet.key, broker.asset(1000)));
|
||||
}
|
||||
@@ -2335,23 +2187,6 @@ class Loan_test : public beast::unit_test::suite
|
||||
BEAST_EXPECT(loan->at(sfPrincipalOutstanding) == actualPrincipal);
|
||||
}
|
||||
|
||||
#if LOANDRAW && 0
|
||||
auto loanDrawTx =
|
||||
env.json(draw(borrower, keylet.key, STAmount{broker.asset, Number {
|
||||
6
|
||||
}}));
|
||||
env(loanDrawTx, ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
if (auto const loan = env.le(keylet); BEAST_EXPECT(loan))
|
||||
{
|
||||
// Verify the payment decreased the principal
|
||||
BEAST_EXPECT(loan->at(sfPaymentRemaining) == numPayments);
|
||||
BEAST_EXPECT(loan->at(sfPrincipalRequested) == actualPrincipal);
|
||||
BEAST_EXPECT(loan->at(sfPrincipalOutstanding) == actualPrincipal);
|
||||
}
|
||||
#endif
|
||||
|
||||
auto loanPayTx = env.json(
|
||||
pay(borrower, keylet.key, STAmount{broker.asset, serviceFee + 6}));
|
||||
env(loanPayTx, ter(tesSUCCESS));
|
||||
|
||||
@@ -835,15 +835,6 @@ manage(AccountID const& account, uint256 const& loanID, std::uint32_t flags);
|
||||
Json::Value
|
||||
del(AccountID const& account, uint256 const& loanID, std::uint32_t flags = 0);
|
||||
|
||||
#if loandraw
|
||||
Json::Value
|
||||
draw(
|
||||
AccountID const& account,
|
||||
uint256 const& loanID,
|
||||
STAmount const& amount,
|
||||
std::uint32_t flags = 0);
|
||||
#endif
|
||||
|
||||
Json::Value
|
||||
pay(AccountID const& account,
|
||||
uint256 const& loanID,
|
||||
|
||||
@@ -487,24 +487,6 @@ del(AccountID const& account, uint256 const& loanID, std::uint32_t flags)
|
||||
return jv;
|
||||
}
|
||||
|
||||
#if LOANDRAW
|
||||
Json::Value
|
||||
draw(
|
||||
AccountID const& account,
|
||||
uint256 const& loanID,
|
||||
STAmount const& amount,
|
||||
std::uint32_t flags)
|
||||
{
|
||||
Json::Value jv;
|
||||
jv[sfTransactionType] = jss::LoanDraw;
|
||||
jv[sfAccount] = to_string(account);
|
||||
jv[sfLoanID] = to_string(loanID);
|
||||
jv[sfAmount] = amount.getJson();
|
||||
jv[sfFlags] = flags;
|
||||
return jv;
|
||||
}
|
||||
#endif
|
||||
|
||||
Json::Value
|
||||
pay(AccountID const& account,
|
||||
uint256 const& loanID,
|
||||
|
||||
@@ -101,23 +101,6 @@ LoanDelete::doApply()
|
||||
if (!vaultSle)
|
||||
return tefBAD_LEDGER; // LCOV_EXCL_LINE
|
||||
|
||||
#if LOANDRAW
|
||||
// transfer any remaining funds to the borrower
|
||||
auto const vaultAsset = vaultSle->at(sfAsset);
|
||||
auto assetsAvailableProxy = loanSle->at(sfAssetsAvailable);
|
||||
if (assetsAvailableProxy != 0)
|
||||
{
|
||||
if (auto const ter = accountSend(
|
||||
view,
|
||||
brokerPseudoAccount,
|
||||
borrower,
|
||||
STAmount{vaultAsset, assetsAvailableProxy},
|
||||
j_,
|
||||
WaiveTransferFee::Yes))
|
||||
return ter;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Remove LoanID from Directory of the LoanBroker pseudo-account.
|
||||
if (!view.dirRemove(
|
||||
keylet::ownerDir(brokerPseudoAccount),
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
#if LOANDRAW
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/LoanDraw.h>
|
||||
//
|
||||
#include <xrpld/app/misc/LendingHelpers.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
bool
|
||||
LoanDraw::checkExtraFeatures(PreflightContext const& ctx)
|
||||
{
|
||||
return checkLendingProtocolDependencies(ctx);
|
||||
}
|
||||
|
||||
NotTEC
|
||||
LoanDraw::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
if (ctx.tx[sfLoanID] == beast::zero)
|
||||
return temINVALID;
|
||||
|
||||
if (ctx.tx[sfAmount] <= beast::zero)
|
||||
return temBAD_AMOUNT;
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
TER
|
||||
LoanDraw::preclaim(PreclaimContext const& ctx)
|
||||
{
|
||||
auto const& tx = ctx.tx;
|
||||
|
||||
auto const account = tx[sfAccount];
|
||||
auto const loanID = tx[sfLoanID];
|
||||
auto const amount = tx[sfAmount];
|
||||
|
||||
auto const loanSle = ctx.view.read(keylet::loan(loanID));
|
||||
if (!loanSle)
|
||||
{
|
||||
JLOG(ctx.j.warn()) << "Loan does not exist.";
|
||||
return tecNO_ENTRY;
|
||||
}
|
||||
|
||||
if (loanSle->at(sfBorrower) != account)
|
||||
{
|
||||
JLOG(ctx.j.warn()) << "Loan does not belong to the account.";
|
||||
return tecNO_PERMISSION;
|
||||
}
|
||||
|
||||
if (loanSle->isFlag(lsfLoanImpaired) || loanSle->isFlag(lsfLoanDefault))
|
||||
{
|
||||
JLOG(ctx.j.warn()) << "Loan is impaired or in default.";
|
||||
return tecNO_PERMISSION;
|
||||
}
|
||||
|
||||
if (!hasExpired(ctx.view, loanSle->at(sfStartDate)))
|
||||
{
|
||||
JLOG(ctx.j.warn()) << "Loan has not started yet.";
|
||||
return tecTOO_SOON;
|
||||
}
|
||||
|
||||
auto const loanBrokerID = loanSle->at(sfLoanBrokerID);
|
||||
auto const loanBrokerSle = ctx.view.read(keylet::loanbroker(loanBrokerID));
|
||||
if (!loanBrokerSle)
|
||||
{
|
||||
// This should be impossible
|
||||
// LCOV_EXCL_START
|
||||
JLOG(ctx.j.fatal()) << "LoanBroker does not exist.";
|
||||
return tefBAD_LEDGER;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
auto const brokerPseudoAccount = loanBrokerSle->at(sfAccount);
|
||||
auto const vaultID = loanBrokerSle->at(sfVaultID);
|
||||
auto const vaultSle = ctx.view.read(keylet::vault(vaultID));
|
||||
if (!vaultSle)
|
||||
{
|
||||
// This should be impossible
|
||||
// LCOV_EXCL_START
|
||||
JLOG(ctx.j.fatal()) << "Vault does not exist.";
|
||||
return tefBAD_LEDGER;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
auto const asset = vaultSle->at(sfAsset);
|
||||
|
||||
if (amount.asset() != asset)
|
||||
{
|
||||
JLOG(ctx.j.warn()) << "Draw amount does not match the Vault asset.";
|
||||
return tecWRONG_ASSET;
|
||||
}
|
||||
|
||||
if (loanSle->at(sfAssetsAvailable) < amount)
|
||||
{
|
||||
JLOG(ctx.j.warn()) << "Loan does not have enough assets available.";
|
||||
return tecINSUFFICIENT_FUNDS;
|
||||
}
|
||||
|
||||
if (auto const ret = checkFrozen(ctx.view, brokerPseudoAccount, asset))
|
||||
{
|
||||
JLOG(ctx.j.warn()) << "Loan Broker pseudo-account is frozen.";
|
||||
return ret;
|
||||
}
|
||||
if (auto const ret = checkDeepFrozen(ctx.view, account, asset))
|
||||
{
|
||||
JLOG(ctx.j.warn())
|
||||
<< "Borrower account cannot receive funds (deep frozen).";
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (hasExpired(ctx.view, loanSle->at(sfNextPaymentDueDate)))
|
||||
{
|
||||
JLOG(ctx.j.warn()) << "Loan payment is overdue.";
|
||||
return tecNO_PERMISSION;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
TER
|
||||
LoanDraw::doApply()
|
||||
{
|
||||
auto const& tx = ctx_.tx;
|
||||
auto& view = ctx_.view();
|
||||
|
||||
auto const amount = tx[sfAmount];
|
||||
|
||||
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 brokerPseudoAccount = brokerSle->at(sfAccount);
|
||||
|
||||
if (auto const ter = accountSend(
|
||||
view,
|
||||
brokerPseudoAccount,
|
||||
account_,
|
||||
amount,
|
||||
j_,
|
||||
WaiveTransferFee::Yes))
|
||||
return ter;
|
||||
|
||||
loanSle->at(sfAssetsAvailable) -= amount;
|
||||
view.update(loanSle);
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // namespace ripple
|
||||
#endif
|
||||
@@ -1,55 +0,0 @@
|
||||
#if LOANDRAW
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_LOANDRAW_H_INCLUDED
|
||||
#define RIPPLE_TX_LOANDRAW_H_INCLUDED
|
||||
|
||||
#include <xrpld/app/tx/detail/Transactor.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class LoanDraw : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit LoanDraw(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static bool
|
||||
checkExtraFeatures(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -150,15 +150,6 @@ LoanManage::defaultLoan(
|
||||
auto brokerDebtTotalProxy = brokerSle->at(sfDebtTotal);
|
||||
auto const totalDefaultAmount = principalOutstanding + interestOutstanding;
|
||||
|
||||
#if LOANDRAW
|
||||
// The default Amount equals the outstanding principal and interest,
|
||||
// excluding any funds unclaimed by the Borrower.
|
||||
auto loanAssetsAvailableProxy = loanSle->at(sfAssetsAvailable);
|
||||
auto const defaultAmount = totalDefaultAmount - loanAssetsAvailableProxy;
|
||||
#else
|
||||
// TODO: get rid of this and just use totalDefaultAmount
|
||||
auto const defaultAmount = totalDefaultAmount;
|
||||
#endif
|
||||
// Apply the First-Loss Capital to the Default Amount
|
||||
TenthBips32 const coverRateMinimum{brokerSle->at(sfCoverRateMinimum)};
|
||||
TenthBips32 const coverRateLiquidation{
|
||||
@@ -170,14 +161,10 @@ LoanManage::defaultLoan(
|
||||
tenthBipsOfValue(
|
||||
brokerDebtTotalProxy.value(), coverRateMinimum),
|
||||
coverRateLiquidation),
|
||||
defaultAmount),
|
||||
totalDefaultAmount),
|
||||
originalPrincipalRequested);
|
||||
#if LOANDRAW
|
||||
auto const returnToVault = defaultCovered + loanAssetsAvailableProxy;
|
||||
#else
|
||||
auto const returnToVault = defaultCovered;
|
||||
#endif
|
||||
auto const vaultDefaultAmount = defaultAmount - defaultCovered;
|
||||
|
||||
auto const vaultDefaultAmount = totalDefaultAmount - defaultCovered;
|
||||
|
||||
// Update the Vault object:
|
||||
|
||||
@@ -196,7 +183,7 @@ LoanManage::defaultLoan(
|
||||
vaultAssetsTotalProxy -= vaultDefaultAmount;
|
||||
// Increase the Asset Available of the Vault by liquidated First-Loss
|
||||
// Capital and any unclaimed funds amount:
|
||||
vaultAssetsAvailableProxy += returnToVault;
|
||||
vaultAssetsAvailableProxy += defaultCovered;
|
||||
if (*vaultAssetsAvailableProxy > *vaultAssetsTotalProxy &&
|
||||
!vaultAsset.native() && vaultAsset.holds<Issue>())
|
||||
{
|
||||
@@ -275,9 +262,6 @@ LoanManage::defaultLoan(
|
||||
// Update the Loan object:
|
||||
loanSle->setFlag(lsfLoanDefault);
|
||||
loanSle->at(sfPaymentRemaining) = 0;
|
||||
#if LOANDRAW
|
||||
loanAssetsAvailableProxy = 0;
|
||||
#endif
|
||||
loanSle->at(sfPrincipalOutstanding) = 0;
|
||||
view.update(loanSle);
|
||||
|
||||
@@ -287,7 +271,7 @@ LoanManage::defaultLoan(
|
||||
view,
|
||||
brokerSle->at(sfAccount),
|
||||
vaultSle->at(sfAccount),
|
||||
STAmount{vaultAsset, returnToVault},
|
||||
STAmount{vaultAsset, defaultCovered},
|
||||
j,
|
||||
WaiveTransferFee::Yes);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user