1#include <xrpld/app/tx/detail/LoanBrokerCoverClawback.h>
3#include <xrpld/app/misc/LendingHelpers.h>
5#include <xrpl/protocol/STTakesAsset.h>
18 auto const brokerID = ctx.
tx[~sfLoanBrokerID];
19 auto const amount = ctx.
tx[~sfAmount];
21 if (!brokerID && !amount)
24 if (brokerID && *brokerID == beast::zero)
34 if (*amount < beast::zero)
46 auto const account = ctx.
tx[sfAccount];
50 auto const holder = amount->getIssuer();
51 if (holder == account || holder == beast::zero)
64 if (
auto const brokerID = tx[~sfLoanBrokerID])
70 auto const dstAmount = tx[~sfAmount];
71 if (!dstAmount || !dstAmount->holds<
Issue>())
83 auto const maybePseudo = dstAmount->getIssuer();
93 if (
auto const brokerID = sle->at(~sfLoanBrokerID))
110 return amount.asset();
114 auto const holder = amount.getIssuer();
118 if (holder == account)
120 return amount.asset();
122 else if (holder == brokerPseudoAccountID)
126 return Issue{amount.getCurrency(), account};
132Expected<STAmount, TER>
135 auto const maxClawAmount = [&]() {
138 auto const minRequiredCover =
142 return sleBroker[sfCoverAvailable] - minRequiredCover;
144 if (maxClawAmount <= beast::zero)
150 if (!amount || *amount == beast::zero)
151 return STAmount{vaultAsset, maxClawAmount};
152 Number const magnitude{*amount};
153 if (magnitude > maxClawAmount)
154 return STAmount{vaultAsset, maxClawAmount};
155 return STAmount{vaultAsset, magnitude};
158template <Val
idIssueType T>
179 auto const sleIssuance = ctx.
view.
read(issuanceKey);
187 if (sleIssuance->at(sfIssuer) != sleIssuer[sfAccount])
196 auto const& tx = ctx.
tx;
198 auto const account = tx[sfAccount];
201 return findBrokerID.error();
202 auto const brokerID = *findBrokerID;
203 auto const amount = tx[~sfAmount];
208 JLOG(ctx.
j.
warn()) <<
"LoanBroker does not exist.";
212 auto const brokerPseudoAccountID = sleBroker->at(sfAccount);
218 JLOG(ctx.
j.
fatal()) <<
"Vault is missing for Broker " << brokerID;
223 auto const vaultAsset = vault->at(sfAsset);
225 if (vaultAsset.native())
227 JLOG(ctx.
j.
warn()) <<
"Cannot clawback native asset.";
233 if (vaultAsset.getIssuer() != account)
235 JLOG(ctx.
j.
warn()) <<
"Account is not the issuer of the vault asset.";
241 auto const findAsset =
determineAsset(ctx.
view, account, brokerPseudoAccountID, *amount);
243 return findAsset.error();
244 auto const txAsset = *findAsset;
245 if (txAsset != vaultAsset)
247 JLOG(ctx.
j.
warn()) <<
"Account is the correct issuer, but trying "
248 "to clawback the wrong asset from LoanBroker";
256 JLOG(ctx.
j.
warn()) <<
"LoanBroker cover is already at minimum.";
257 return findClawAmount.error();
259 STAmount const& clawAmount = *findClawAmount;
272 JLOG(ctx.
j.
fatal()) <<
"Issuer account does not exist.";
278 [&]<
typename T>(T
const&) {
return preclaimHelper<T>(ctx, *sleIssuer, clawAmount); }, vaultAsset.value());
285 auto const account = tx[sfAccount];
289 auto const brokerID = *findBrokerID;
290 auto const amount = tx[~sfAmount];
296 auto const brokerPseudoID = *sleBroker->at(sfAccount);
302 auto const vaultAsset = vault->at(sfAsset);
307 STAmount const& clawAmount = *findClawAmount;
313 sleBroker->at(sfCoverAvailable) -= clawAmount;
virtual void update(std::shared_ptr< SLE > const &sle)=0
Indicate changes to a peeked SLE.
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
A currency issued by an account.
static TER preclaim(PreclaimContext const &ctx)
static NotTEC preflight(PreflightContext const &ctx)
static bool checkExtraFeatures(PreflightContext const &ctx)
constexpr MPTID const & getMptID() const
Number is a floating point type that can represent a wide range of values.
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
constexpr TIss const & get() const
bool native() const noexcept
bool isFlag(std::uint32_t) const
Keylet loanbroker(AccountID const &owner, std::uint32_t seq) noexcept
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Keylet account(AccountID const &id) noexcept
AccountID root.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
constexpr T tenthBipsOfValue(T value, TenthBips< TBips > bips)
bool isLegalNet(STAmount const &value)
bool checkLendingProtocolDependencies(PreflightContext const &ctx)
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j, SpendableHandling includeFullBalance=shSIMPLE_BALANCE)
TenthBips< std::uint32_t > TenthBips32
static TER preclaimHelper(PreclaimContext const &ctx, SLE const &sleIssuer, AccountID const &issuer, AccountID const &holder, STAmount const &clawAmount)
TER accountSend(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee=WaiveTransferFee::No)
Calls static accountSendIOU if saAmount represents Issue.
TERSubset< CanCvtToTER > TER
TER preclaimHelper< Issue >(PreclaimContext const &ctx, SLE const &sleIssuer, AccountID const &issuer, AccountID const &holder, STAmount const &clawAmount)
Expected< uint256, TER > determineBrokerID(ReadView const &view, STTx const &tx)
Expected< STAmount, TER > determineClawAmount(SLE const &sleBroker, Asset const &vaultAsset, std::optional< STAmount > const &amount)
@ lsfAllowTrustLineClawback
void associateAsset(STLedgerEntry &sle, Asset const &asset)
Associate an Asset with all sMD_NeedsAsset fields in a ledger entry.
TER preclaimHelper< MPTIssue >(PreclaimContext const &ctx, SLE const &sleIssuer, AccountID const &issuer, AccountID const &holder, STAmount const &clawAmount)
Expected< Asset, TER > determineAsset(ReadView const &view, AccountID const &account, AccountID const &brokerPseudoAccountID, STAmount const &amount)
State information when determining if a tx is likely to claim a fee.
State information when preflighting a tx.