Add LoanBrokerCoverDeposit transaction

- Untested. Will need Withdraw to do a good test.
This commit is contained in:
Ed Hennis
2025-04-15 15:16:22 -04:00
parent fc66227f69
commit ffbc068dc8
4 changed files with 200 additions and 3 deletions

View File

@@ -554,17 +554,17 @@ TRANSACTION(ttLOAN_BROKER_DELETE, 75, LoanBrokerDelete,
{sfLoanBrokerID, soeREQUIRED},
}))
#if 0
/** This transaction deposits First Loss Capital into a Loan Broker */
TRANSACTION(ttLOAN_BROKER_COVER_DEPOSIT, 76, LoanBrokerCoverDeposit, noPriv, ({
{sfLoanBrokerID, soeREQUIRED},
{sfNumber, soeREQUIRED},
{sfAmount, soeREQUIRED},
}))
#if 0
/** This transaction withdraws First Loss Capital from a Loan Broker */
TRANSACTION(ttLOAN_BROKER_COVER_WITHDRAW, 77, LoanBrokerCoverWithdraw, noPriv, ({
{sfLoanBrokerID, soeREQUIRED},
{sfNumber, soeREQUIRED},
{sfAmount, soeREQUIRED},
}))
/** This transaction creates a Loan */

View File

@@ -0,0 +1,140 @@
//------------------------------------------------------------------------------
/*
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/LoanBrokerCoverDeposit.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/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/TER.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/XRPAmount.h>
namespace ripple {
bool
LoanBrokerCoverDeposit::isEnabled(PreflightContext const& ctx)
{
return lendingProtocolEnabled(ctx);
}
std::uint32_t
LoanBrokerCoverDeposit::getFlagsMask(PreflightContext const& ctx)
{
return tfUniversalMask;
}
NotTEC
LoanBrokerCoverDeposit::doPreflight(PreflightContext const& ctx)
{
if (ctx.tx[sfLoanBrokerID] == beast::zero)
return temINVALID;
if (ctx.tx[sfAmount] <= beast::zero)
return temBAD_AMOUNT;
return tesSUCCESS;
}
TER
LoanBrokerCoverDeposit::preclaim(PreclaimContext const& ctx)
{
auto const& tx = ctx.tx;
auto const account = tx[sfAccount];
auto const brokerID = tx[sfLoanBrokerID];
auto const amount = tx[sfAmount];
auto const sleBroker = ctx.view.read(keylet::loanbroker(brokerID));
if (!sleBroker)
{
JLOG(ctx.j.warn()) << "LoanBroker does not exist.";
return tecNO_ENTRY;
}
if (account != sleBroker->at(sfOwner))
{
JLOG(ctx.j.warn()) << "Account is not the owner of the LoanBroker.";
return tecNO_PERMISSION;
}
auto const vault = ctx.view.read(keylet::vault(sleBroker->at(sfVaultID)));
auto const vaultAsset = vault->at(sfAsset);
if (amount.asset() != vaultAsset)
return tecWRONG_ASSET;
// Cannot transfer a frozen Asset
if (isFrozen(ctx.view, account, vaultAsset))
return vaultAsset.holds<Issue>() ? tecFROZEN : tecLOCKED;
if (accountHolds(
ctx.view,
account,
vaultAsset,
FreezeHandling::fhZERO_IF_FROZEN,
AuthHandling::ahZERO_IF_UNAUTHORIZED,
ctx.j) < amount)
return tecINSUFFICIENT_FUNDS;
return tesSUCCESS;
}
TER
LoanBrokerCoverDeposit::doApply()
{
auto const& tx = ctx_.tx;
auto const brokerID = tx[sfLoanBrokerID];
auto const amount = tx[sfAmount];
auto broker = view().peek(keylet::loanbroker(brokerID));
auto const brokerPseudoID = broker->at(sfAccount);
// Transfer assets from depositor to pseudo-account.
if (auto ter = accountSend(
view(),
account_,
brokerPseudoID,
amount,
j_,
WaiveTransferFee::Yes))
return ter;
// Increase the LoanBroker's CoverAvailable by Amount
broker->at(sfCoverAvailable) += amount;
return tesSUCCESS;
}
//------------------------------------------------------------------------------
} // namespace ripple

View 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_LOANBROKERCOVERDEPOSIT_H_INCLUDED
#define RIPPLE_TX_LOANBROKERCOVERDEPOSIT_H_INCLUDED
#include <xrpld/app/tx/detail/Transactor.h>
namespace ripple {
class LoanBrokerCoverDeposit : public Transactor
{
public:
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
explicit LoanBrokerCoverDeposit(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

View File

@@ -41,6 +41,7 @@
#include <xrpld/app/tx/detail/DepositPreauth.h>
#include <xrpld/app/tx/detail/Escrow.h>
#include <xrpld/app/tx/detail/LedgerStateFix.h>
#include <xrpld/app/tx/detail/LoanBrokerCoverDeposit.h>
#include <xrpld/app/tx/detail/LoanBrokerDelete.h>
#include <xrpld/app/tx/detail/LoanBrokerSet.h>
#include <xrpld/app/tx/detail/MPTokenAuthorize.h>