1#include <xrpl/tx/transactors/lending/LoanBrokerCoverClawback.h>
3#include <xrpl/ledger/helpers/TokenHelpers.h>
4#include <xrpl/protocol/STTakesAsset.h>
5#include <xrpl/tx/transactors/lending/LendingHelpers.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 if (holder == brokerPseudoAccountID)
126 return Issue{amount.getCurrency(), account};
132Expected<STAmount, TER>
134 SLE const& sleBroker,
135 Asset const& vaultAsset,
138 auto const maxClawAmount = [&]() {
141 auto const minRequiredCover =
145 return sleBroker[sfCoverAvailable] - minRequiredCover;
147 if (maxClawAmount <= beast::zero)
153 if (!amount || *amount == beast::zero)
154 return STAmount{vaultAsset, maxClawAmount};
155 Number const magnitude{*amount};
156 if (magnitude > maxClawAmount)
157 return STAmount{vaultAsset, maxClawAmount};
158 return STAmount{vaultAsset, magnitude};
161template <Val
idIssueType T>
171 if (!(sleIssuer.
isFlag(lsfAllowTrustLineClawback)) || (sleIssuer.
isFlag(lsfNoFreeze)))
181 SLE const& sleIssuer,
185 auto const sleIssuance = ctx.
view.
read(issuanceKey);
189 if (!sleIssuance->isFlag(lsfMPTCanClawback))
193 if (sleIssuance->at(sfIssuer) != sleIssuer[sfAccount])
202 auto const& tx = ctx.
tx;
204 auto const account = tx[sfAccount];
207 return findBrokerID.error();
208 auto const brokerID = *findBrokerID;
209 auto const amount = tx[~sfAmount];
214 JLOG(ctx.
j.
warn()) <<
"LoanBroker does not exist.";
218 auto const brokerPseudoAccountID = sleBroker->at(sfAccount);
224 JLOG(ctx.
j.
fatal()) <<
"Vault is missing for Broker " << brokerID;
229 auto const vaultAsset = vault->at(sfAsset);
231 if (vaultAsset.native())
233 JLOG(ctx.
j.
warn()) <<
"Cannot clawback native asset.";
239 if (vaultAsset.getIssuer() != account)
241 JLOG(ctx.
j.
warn()) <<
"Account is not the issuer of the vault asset.";
247 auto const findAsset =
determineAsset(ctx.
view, account, brokerPseudoAccountID, *amount);
249 return findAsset.error();
250 auto const txAsset = *findAsset;
251 if (txAsset != vaultAsset)
253 JLOG(ctx.
j.
warn()) <<
"Account is the correct issuer, but trying "
254 "to clawback the wrong asset from LoanBroker";
262 JLOG(ctx.
j.
warn()) <<
"LoanBroker cover is already at minimum.";
263 return findClawAmount.error();
265 STAmount const& clawAmount = *findClawAmount;
280 JLOG(ctx.
j.
fatal()) <<
"Issuer account does not exist.";
286 [&]<
typename T>(T
const&) {
return preclaimHelper<T>(ctx, *sleIssuer, clawAmount); },
294 auto const account = tx[sfAccount];
298 auto const brokerID = *findBrokerID;
299 auto const amount = tx[~sfAmount];
305 auto const brokerPseudoID = *sleBroker->at(sfAccount);
311 auto const vaultAsset = vault->at(sfAsset);
316 STAmount const& clawAmount = *findClawAmount;
322 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
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, 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)
TER preclaimHelper< MPTIssue >(PreclaimContext const &ctx, SLE const &sleIssuer, STAmount const &clawAmount)
void associateAsset(STLedgerEntry &sle, Asset const &asset)
Associate an Asset with all sMD_NeedsAsset fields in a ledger entry.
static TER preclaimHelper(PreclaimContext const &ctx, SLE const &sleIssuer, 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.