1#include <xrpld/app/tx/detail/LoanBrokerCoverClawback.h>
3#include <xrpld/app/misc/LendingHelpers.h>
16 auto const brokerID = ctx.
tx[~sfLoanBrokerID];
17 auto const amount = ctx.
tx[~sfAmount];
19 if (!brokerID && !amount)
22 if (brokerID && *brokerID == beast::zero)
32 if (*amount < beast::zero)
44 auto const account = ctx.
tx[sfAccount];
48 auto const holder = amount->getIssuer();
49 if (holder == account || holder == beast::zero)
62 if (
auto const brokerID = tx[~sfLoanBrokerID])
68 auto const dstAmount = tx[~sfAmount];
69 if (!dstAmount || !dstAmount->holds<
Issue>())
81 auto const maybePseudo = dstAmount->getIssuer();
91 if (
auto const brokerID = sle->at(~sfLoanBrokerID))
108 return amount.asset();
112 auto const holder = amount.getIssuer();
116 if (holder == account)
118 return amount.asset();
120 else if (holder == brokerPseudoAccountID)
124 return Issue{amount.getCurrency(), account};
130Expected<STAmount, TER>
132 SLE const& sleBroker,
133 Asset const& vaultAsset,
136 auto const maxClawAmount = [&]() {
140 sleBroker[sfDebtTotal],
TenthBips32(sleBroker[sfCoverRateMinimum]));
143 return sleBroker[sfCoverAvailable] - minRequiredCover;
145 if (maxClawAmount <= beast::zero)
151 if (!amount || *amount == beast::zero)
152 return STAmount{vaultAsset, maxClawAmount};
153 Number const magnitude{*amount};
154 if (magnitude > maxClawAmount)
155 return STAmount{vaultAsset, maxClawAmount};
156 return STAmount{vaultAsset, magnitude};
159template <Val
idIssueType T>
163 SLE const& sleIssuer,
170 SLE const& sleIssuer,
186 SLE const& sleIssuer,
189 auto const issuanceKey =
191 auto const sleIssuance = ctx.
view.
read(issuanceKey);
199 if (sleIssuance->at(sfIssuer) != sleIssuer[sfAccount])
208 auto const& tx = ctx.
tx;
210 auto const account = tx[sfAccount];
213 return findBrokerID.error();
214 auto const brokerID = *findBrokerID;
215 auto const amount = tx[~sfAmount];
220 JLOG(ctx.
j.
warn()) <<
"LoanBroker does not exist.";
224 auto const brokerPseudoAccountID = sleBroker->at(sfAccount);
230 JLOG(ctx.
j.
fatal()) <<
"Vault is missing for Broker " << brokerID;
235 auto const vaultAsset = vault->at(sfAsset);
237 if (vaultAsset.native())
239 JLOG(ctx.
j.
warn()) <<
"Cannot clawback native asset.";
245 if (vaultAsset.getIssuer() != account)
247 JLOG(ctx.
j.
warn()) <<
"Account is not the issuer of the vault asset.";
253 auto const findAsset =
256 return findAsset.error();
257 auto const txAsset = *findAsset;
258 if (txAsset != vaultAsset)
260 JLOG(ctx.
j.
warn()) <<
"Account is the correct issuer, but trying "
261 "to clawback the wrong asset from LoanBroker";
266 auto const findClawAmount =
270 JLOG(ctx.
j.
warn()) <<
"LoanBroker cover is already at minimum.";
271 return findClawAmount.error();
273 STAmount const clawAmount = *findClawAmount;
280 brokerPseudoAccountID,
288 auto const sleIssuer =
291 [&]<
typename T>(T
const&) {
292 return preclaimHelper<T>(ctx, *sleIssuer, clawAmount);
301 auto const account = tx[sfAccount];
305 auto const brokerID = *findBrokerID;
306 auto const amount = tx[~sfAmount];
312 auto const brokerPseudoID = *sleBroker->at(sfAccount);
318 auto const vaultAsset = vault->at(sfAsset);
320 auto const findClawAmount =
324 STAmount const clawAmount = *findClawAmount;
330 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
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)
TenthBips< std::uint32_t > TenthBips32
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
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
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.