rippled
Loading...
Searching...
No Matches
LoanBrokerCoverWithdraw.cpp
1#include <xrpld/app/tx/detail/LoanBrokerCoverWithdraw.h>
2//
3#include <xrpld/app/misc/LendingHelpers.h>
4#include <xrpld/app/tx/detail/Payment.h>
5
6#include <xrpl/ledger/CredentialHelpers.h>
7#include <xrpl/protocol/STTakesAsset.h>
8
9namespace xrpl {
10
11bool
16
19{
20 if (ctx.tx[sfLoanBrokerID] == beast::zero)
21 return temINVALID;
22
23 auto const dstAmount = ctx.tx[sfAmount];
24 if (dstAmount <= beast::zero)
25 return temBAD_AMOUNT;
26
27 if (!isLegalNet(dstAmount))
28 return temBAD_AMOUNT;
29
30 if (auto const destination = ctx.tx[~sfDestination])
31 {
32 if (*destination == beast::zero)
33 {
34 return temMALFORMED;
35 }
36 }
37
38 return tesSUCCESS;
39}
40
41TER
43{
44 auto const& tx = ctx.tx;
45
46 auto const account = tx[sfAccount];
47 auto const brokerID = tx[sfLoanBrokerID];
48 auto const amount = tx[sfAmount];
49
50 auto const dstAcct = tx[~sfDestination].value_or(account);
51
52 if (isPseudoAccount(ctx.view, dstAcct))
53 {
54 JLOG(ctx.j.warn()) << "Trying to withdraw into a pseudo-account.";
55 return tecPSEUDO_ACCOUNT;
56 }
57 auto const sleBroker = ctx.view.read(keylet::loanbroker(brokerID));
58 if (!sleBroker)
59 {
60 JLOG(ctx.j.warn()) << "LoanBroker does not exist.";
61 return tecNO_ENTRY;
62 }
63 if (account != sleBroker->at(sfOwner))
64 {
65 JLOG(ctx.j.warn()) << "Account is not the owner of the LoanBroker.";
66 return tecNO_PERMISSION;
67 }
68 auto const vault = ctx.view.read(keylet::vault(sleBroker->at(sfVaultID)));
69 if (!vault)
70 {
71 // LCOV_EXCL_START
72 JLOG(ctx.j.fatal()) << "Vault is missing for Broker " << brokerID;
73 return tefBAD_LEDGER;
74 // LCOV_EXCL_STOP
75 }
76
77 auto const vaultAsset = vault->at(sfAsset);
78 if (amount.asset() != vaultAsset)
79 return tecWRONG_ASSET;
80
81 // The broker's pseudo-account is the source of funds.
82 auto const pseudoAccountID = sleBroker->at(sfAccount);
83 // Cannot transfer a non-transferable Asset
84 if (auto const ret = canTransfer(ctx.view, vaultAsset, pseudoAccountID, dstAcct))
85 return ret;
86
87 // Withdrawal to a 3rd party destination account is essentially a transfer.
88 // Enforce all the usual asset transfer checks.
90 if (account != dstAcct)
91 {
92 if (auto const ret = canWithdraw(ctx.view, tx))
93 return ret;
94
95 // The destination account must have consented to receive the asset by
96 // creating a RippleState or MPToken
97 authType = AuthType::StrongAuth;
98 }
99
100 // Destination MPToken must exist (if asset is an MPT)
101 if (auto const ter = requireAuth(ctx.view, vaultAsset, dstAcct, authType))
102 return ter;
103
104 // Check for freezes, unless sending directly to the issuer
105 if (dstAcct != vaultAsset.getIssuer())
106 {
107 // Cannot send a frozen Asset
108 if (auto const ret = checkFrozen(ctx.view, pseudoAccountID, vaultAsset))
109 return ret;
110 // Destination account cannot receive if asset is deep frozen
111 if (auto const ret = checkDeepFrozen(ctx.view, dstAcct, vaultAsset))
112 return ret;
113 }
114
115 auto const coverAvail = sleBroker->at(sfCoverAvailable);
116 // Cover Rate is in 1/10 bips units
117 auto const currentDebtTotal = sleBroker->at(sfDebtTotal);
118 auto const minimumCover = [&]() {
119 // Always round the minimum required up.
120 // Applies to `tenthBipsOfValue` as well as `roundToAsset`.
122 return roundToAsset(
123 vaultAsset,
124 tenthBipsOfValue(currentDebtTotal, TenthBips32(sleBroker->at(sfCoverRateMinimum))),
125 currentDebtTotal.exponent());
126 }();
127 if (coverAvail < amount)
129 if ((coverAvail - amount) < minimumCover)
131
132 if (accountHolds(
133 ctx.view,
134 pseudoAccountID,
135 vaultAsset,
138 ctx.j) < amount)
140
141 return tesSUCCESS;
142}
143
144TER
146{
147 auto const& tx = ctx_.tx;
148
149 auto const brokerID = tx[sfLoanBrokerID];
150 auto const amount = tx[sfAmount];
151 auto const dstAcct = tx[~sfDestination].value_or(account_);
152
153 auto broker = view().peek(keylet::loanbroker(brokerID));
154 if (!broker)
155 return tecINTERNAL; // LCOV_EXCL_LINE
156
157 auto const vault = view().read(keylet::vault(broker->at(sfVaultID)));
158 if (!vault)
159 return tecINTERNAL; // LCOV_EXCL_LINE
160
161 auto const vaultAsset = vault->at(sfAsset);
162
163 auto const brokerPseudoID = *broker->at(sfAccount);
164
165 // Decrease the LoanBroker's CoverAvailable by Amount
166 broker->at(sfCoverAvailable) -= amount;
167 view().update(broker);
168
169 associateAsset(*broker, vaultAsset);
170
171 return doWithdraw(view(), tx, account_, dstAcct, brokerPseudoID, mPriorBalance, amount, j_);
172}
173
174//------------------------------------------------------------------------------
175
176} // namespace xrpl
Stream fatal() const
Definition Journal.h:324
Stream warn() const
Definition Journal.h:312
STTx const & tx
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.
static bool checkExtraFeatures(PreflightContext const &ctx)
static NotTEC preflight(PreflightContext const &ctx)
static TER preclaim(PreclaimContext const &ctx)
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
AccountID const account_
Definition Transactor.h:112
beast::Journal const j_
Definition Transactor.h:110
ApplyView & view()
Definition Transactor.h:128
XRPAmount mPriorBalance
Definition Transactor.h:113
ApplyContext & ctx_
Definition Transactor.h:108
Keylet loanbroker(AccountID const &owner, std::uint32_t seq) noexcept
Definition Indexes.cpp:498
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Definition Indexes.cpp:492
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
TER checkDeepFrozen(ReadView const &view, AccountID const &account, Issue const &issue)
Definition View.h:198
@ fhZERO_IF_FROZEN
Definition View.h:58
TER doWithdraw(ApplyView &view, STTx const &tx, AccountID const &senderAcct, AccountID const &dstAcct, AccountID const &sourceAcct, XRPAmount priorBalance, STAmount const &amount, beast::Journal j)
Definition View.cpp:1209
constexpr T tenthBipsOfValue(T value, TenthBips< TBips > bips)
Definition Protocol.h:107
TER checkFrozen(ReadView const &view, AccountID const &account, Issue const &issue)
Definition View.h:121
@ tefBAD_LEDGER
Definition TER.h:150
bool isLegalNet(STAmount const &value)
Definition STAmount.h:566
bool checkLendingProtocolDependencies(PreflightContext const &ctx)
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j, SpendableHandling includeFullBalance=shSIMPLE_BALANCE)
Definition View.cpp:392
TenthBips< std::uint32_t > TenthBips32
Definition Units.h:429
bool isPseudoAccount(std::shared_ptr< SLE const > sleAcct, std::set< SField const * > const &pseudoFieldFilter={})
Definition View.cpp:1020
@ ahZERO_IF_UNAUTHORIZED
Definition View.h:61
AuthType
Definition View.h:801
TER requireAuth(ReadView const &view, Issue const &issue, AccountID const &account, AuthType authType=AuthType::Legacy)
Check if the account lacks required authorization.
Definition View.cpp:2710
TER canTransfer(ReadView const &view, MPTIssue const &mptIssue, AccountID const &from, AccountID const &to)
Check if the destination account is allowed to receive MPT.
Definition View.cpp:2914
void roundToAsset(A const &asset, Number &value)
Round an arbitrary precision Number IN PLACE to the precision of a given Asset.
Definition STAmount.h:674
@ temINVALID
Definition TER.h:90
@ temMALFORMED
Definition TER.h:67
@ temBAD_AMOUNT
Definition TER.h:69
@ tecWRONG_ASSET
Definition TER.h:341
@ tecPSEUDO_ACCOUNT
Definition TER.h:343
@ tecNO_ENTRY
Definition TER.h:287
@ tecINTERNAL
Definition TER.h:291
@ tecINSUFFICIENT_FUNDS
Definition TER.h:306
@ tecNO_PERMISSION
Definition TER.h:286
TER canWithdraw(ReadView const &view, AccountID const &from, AccountID const &to, SLE::const_ref toSle, STAmount const &amount, bool hasDestinationTag)
Checks that can withdraw funds from an object to itself or a destination.
Definition View.cpp:1163
void associateAsset(STLedgerEntry &sle, Asset const &asset)
Associate an Asset with all sMD_NeedsAsset fields in a ledger entry.
@ tesSUCCESS
Definition TER.h:225
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:53
ReadView const & view
Definition Transactor.h:56
beast::Journal const j
Definition Transactor.h:61
State information when preflighting a tx.
Definition Transactor.h:15