rippled
Loading...
Searching...
No Matches
CashCheck.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2017 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpld/app/ledger/Ledger.h>
21#include <xrpld/app/paths/Flow.h>
22#include <xrpld/app/tx/detail/CashCheck.h>
23#include <xrpl/basics/Log.h>
24#include <xrpl/basics/scope.h>
25#include <xrpl/protocol/Feature.h>
26#include <xrpl/protocol/Indexes.h>
27#include <xrpl/protocol/STAccount.h>
28#include <xrpl/protocol/TER.h>
29#include <xrpl/protocol/TxFlags.h>
30
31#include <algorithm>
32
33namespace ripple {
34
37{
38 if (!ctx.rules.enabled(featureChecks))
39 return temDISABLED;
40
41 NotTEC const ret{preflight1(ctx)};
42 if (!isTesSuccess(ret))
43 return ret;
44
45 if (ctx.tx.getFlags() & tfUniversalMask)
46 {
47 // There are no flags (other than universal) for CashCheck yet.
48 JLOG(ctx.j.warn()) << "Malformed transaction: Invalid flags set.";
49 return temINVALID_FLAG;
50 }
51
52 // Exactly one of Amount or DeliverMin must be present.
53 auto const optAmount = ctx.tx[~sfAmount];
54 auto const optDeliverMin = ctx.tx[~sfDeliverMin];
55
56 if (static_cast<bool>(optAmount) == static_cast<bool>(optDeliverMin))
57 {
58 JLOG(ctx.j.warn())
59 << "Malformed transaction: "
60 "does not specify exactly one of Amount and DeliverMin.";
61 return temMALFORMED;
62 }
63
64 // Make sure the amount is valid.
65 STAmount const value{optAmount ? *optAmount : *optDeliverMin};
66 if (!isLegalNet(value) || value.signum() <= 0)
67 {
68 JLOG(ctx.j.warn()) << "Malformed transaction: bad amount: "
69 << value.getFullText();
70 return temBAD_AMOUNT;
71 }
72
73 if (badCurrency() == value.getCurrency())
74 {
75 JLOG(ctx.j.warn()) << "Malformed transaction: Bad currency.";
76 return temBAD_CURRENCY;
77 }
78
79 return preflight2(ctx);
80}
81
82TER
84{
85 auto const sleCheck = ctx.view.read(keylet::check(ctx.tx[sfCheckID]));
86 if (!sleCheck)
87 {
88 JLOG(ctx.j.warn()) << "Check does not exist.";
89 return tecNO_ENTRY;
90 }
91
92 // Only cash a check with this account as the destination.
93 AccountID const dstId = sleCheck->at(sfDestination);
94 if (ctx.tx[sfAccount] != dstId)
95 {
96 JLOG(ctx.j.warn()) << "Cashing a check with wrong Destination.";
97 return tecNO_PERMISSION;
98 }
99 AccountID const srcId = sleCheck->at(sfAccount);
100 if (srcId == dstId)
101 {
102 // They wrote a check to themselves. This should be caught when
103 // the check is created, but better late than never.
104 JLOG(ctx.j.error()) << "Malformed transaction: Cashing check to self.";
105 return tecINTERNAL;
106 }
107 {
108 auto const sleSrc = ctx.view.read(keylet::account(srcId));
109 auto const sleDst = ctx.view.read(keylet::account(dstId));
110 if (!sleSrc || !sleDst)
111 {
112 // If the check exists this should never occur.
113 JLOG(ctx.j.warn())
114 << "Malformed transaction: source or destination not in ledger";
115 return tecNO_ENTRY;
116 }
117
118 if ((sleDst->getFlags() & lsfRequireDestTag) &&
119 !sleCheck->isFieldPresent(sfDestinationTag))
120 {
121 // The tag is basically account-specific information we don't
122 // understand, but we can require someone to fill it in.
123 JLOG(ctx.j.warn())
124 << "Malformed transaction: DestinationTag required in check.";
125 return tecDST_TAG_NEEDED;
126 }
127 }
128
129 if (hasExpired(ctx.view, sleCheck->at(~sfExpiration)))
130 {
131 JLOG(ctx.j.warn()) << "Cashing a check that has already expired.";
132 return tecEXPIRED;
133 }
134
135 {
136 // Preflight verified exactly one of Amount or DeliverMin is present.
137 // Make sure the requested amount is reasonable.
138 STAmount const value{[](STTx const& tx) {
139 auto const optAmount = tx[~sfAmount];
140 return optAmount ? *optAmount : tx[sfDeliverMin];
141 }(ctx.tx)};
142
143 STAmount const sendMax = sleCheck->at(sfSendMax);
144 Currency const currency{value.getCurrency()};
145 if (currency != sendMax.getCurrency())
146 {
147 JLOG(ctx.j.warn()) << "Check cash does not match check currency.";
148 return temMALFORMED;
149 }
150 AccountID const issuerId{value.getIssuer()};
151 if (issuerId != sendMax.getIssuer())
152 {
153 JLOG(ctx.j.warn()) << "Check cash does not match check issuer.";
154 return temMALFORMED;
155 }
156 if (value > sendMax)
157 {
158 JLOG(ctx.j.warn()) << "Check cashed for more than check sendMax.";
159 return tecPATH_PARTIAL;
160 }
161
162 // Make sure the check owner holds at least value. If they have
163 // less than value the check cannot be cashed.
164 {
165 STAmount availableFunds{accountFunds(
166 ctx.view,
167 sleCheck->at(sfAccount),
168 value,
170 ctx.j)};
171
172 // Note that src will have one reserve's worth of additional XRP
173 // once the check is cashed, since the check's reserve will no
174 // longer be required. So, if we're dealing in XRP, we add one
175 // reserve's worth to the available funds.
176 if (value.native())
177 availableFunds += XRPAmount{ctx.view.fees().increment};
178
179 if (value > availableFunds)
180 {
181 JLOG(ctx.j.warn())
182 << "Check cashed for more than owner's balance.";
183 return tecPATH_PARTIAL;
184 }
185 }
186
187 // An issuer can always accept their own currency.
188 if (!value.native() && (value.getIssuer() != dstId))
189 {
190 auto const sleTrustLine =
191 ctx.view.read(keylet::line(dstId, issuerId, currency));
192
193 if (!sleTrustLine &&
194 !ctx.view.rules().enabled(featureCheckCashMakesTrustLine))
195 {
196 JLOG(ctx.j.warn())
197 << "Cannot cash check for IOU without trustline.";
198 return tecNO_LINE;
199 }
200
201 auto const sleIssuer = ctx.view.read(keylet::account(issuerId));
202 if (!sleIssuer)
203 {
204 JLOG(ctx.j.warn())
205 << "Can't receive IOUs from non-existent issuer: "
206 << to_string(issuerId);
207 return tecNO_ISSUER;
208 }
209
210 if (sleIssuer->at(sfFlags) & lsfRequireAuth)
211 {
212 if (!sleTrustLine)
213 {
214 // We can only create a trust line if the issuer does not
215 // have requireAuth set.
216 return tecNO_AUTH;
217 }
218
219 // Entries have a canonical representation, determined by a
220 // lexicographical "greater than" comparison employing strict
221 // weak ordering. Determine which entry we need to access.
222 bool const canonical_gt(dstId > issuerId);
223
224 bool const is_authorized(
225 sleTrustLine->at(sfFlags) &
226 (canonical_gt ? lsfLowAuth : lsfHighAuth));
227
228 if (!is_authorized)
229 {
230 JLOG(ctx.j.warn())
231 << "Can't receive IOUs from issuer without auth.";
232 return tecNO_AUTH;
233 }
234 }
235
236 // The trustline from source to issuer does not need to
237 // be checked for freezing, since we already verified that the
238 // source has sufficient non-frozen funds available.
239
240 // However, the trustline from destination to issuer may not
241 // be frozen.
242 if (isFrozen(ctx.view, dstId, currency, issuerId))
243 {
244 JLOG(ctx.j.warn()) << "Cashing a check to a frozen trustline.";
245 return tecFROZEN;
246 }
247 }
248 }
249 return tesSUCCESS;
250}
251
252TER
254{
255 // Flow requires that we operate on a PaymentSandbox, rather than
256 // directly on a View.
257 PaymentSandbox psb(&ctx_.view());
258
259 auto sleCheck = psb.peek(keylet::check(ctx_.tx[sfCheckID]));
260 if (!sleCheck)
261 {
262 JLOG(j_.fatal()) << "Precheck did not verify check's existence.";
264 }
265
266 AccountID const srcId{sleCheck->getAccountID(sfAccount)};
267 if (!psb.exists(keylet::account(srcId)) ||
269 {
270 JLOG(ctx_.journal.fatal())
271 << "Precheck did not verify source or destination's existence.";
273 }
274
275 // Preclaim already checked that source has at least the requested
276 // funds.
277 //
278 // Therefore, if this is a check written to self, (and it shouldn't be)
279 // we know they have sufficient funds to pay the check. Since they are
280 // taking the funds from their own pocket and putting it back in their
281 // pocket no balance will change.
282 //
283 // If it is not a check to self (as should be the case), then there's
284 // work to do...
285 auto viewJ = ctx_.app.journal("View");
286 auto const optDeliverMin = ctx_.tx[~sfDeliverMin];
287 bool const doFix1623{psb.rules().enabled(fix1623)};
288
289 if (srcId != account_)
290 {
291 STAmount const sendMax = sleCheck->at(sfSendMax);
292
293 // Flow() doesn't do XRP to XRP transfers.
294 if (sendMax.native())
295 {
296 // Here we need to calculate the amount of XRP src can send.
297 // The amount they have available is their balance minus their
298 // reserve.
299 //
300 // Since (if we're successful) we're about to remove an entry
301 // from src's directory, we allow them to send that additional
302 // incremental reserve amount in the transfer. Hence the -1
303 // argument.
304 STAmount const srcLiquid{xrpLiquid(psb, srcId, -1, viewJ)};
305
306 // Now, how much do they need in order to be successful?
307 STAmount const xrpDeliver{
308 optDeliverMin
309 ? std::max(*optDeliverMin, std::min(sendMax, srcLiquid))
310 : ctx_.tx.getFieldAmount(sfAmount)};
311
312 if (srcLiquid < xrpDeliver)
313 {
314 // Vote no. However the transaction might succeed if applied
315 // in a different order.
316 JLOG(j_.trace()) << "Cash Check: Insufficient XRP: "
317 << srcLiquid.getFullText() << " < "
318 << xrpDeliver.getFullText();
319 return tecUNFUNDED_PAYMENT;
320 }
321
322 if (optDeliverMin && doFix1623)
323 // Set the DeliveredAmount metadata.
324 ctx_.deliver(xrpDeliver);
325
326 // The source account has enough XRP so make the ledger change.
327 if (TER const ter{
328 transferXRP(psb, srcId, account_, xrpDeliver, viewJ)};
329 ter != tesSUCCESS)
330 {
331 // The transfer failed. Return the error code.
332 return ter;
333 }
334 }
335 else
336 {
337 // Note that for DeliverMin we don't know exactly how much
338 // currency we want flow to deliver. We can't ask for the
339 // maximum possible currency because there might be a gateway
340 // transfer rate to account for. Since the transfer rate cannot
341 // exceed 200%, we use 1/2 maxValue as our limit.
342 STAmount const flowDeliver{
343 optDeliverMin ? STAmount(
344 optDeliverMin->issue(),
347 : ctx_.tx.getFieldAmount(sfAmount)};
348
349 // If a trust line does not exist yet create one.
350 Issue const& trustLineIssue = flowDeliver.issue();
351 AccountID const issuer = flowDeliver.getIssuer();
352 AccountID const truster = issuer == account_ ? srcId : account_;
353 Keylet const trustLineKey = keylet::line(truster, trustLineIssue);
354 bool const destLow = issuer > account_;
355
356 bool const checkCashMakesTrustLine =
357 psb.rules().enabled(featureCheckCashMakesTrustLine);
358
359 if (checkCashMakesTrustLine && !psb.exists(trustLineKey))
360 {
361 // 1. Can the check casher meet the reserve for the trust line?
362 // 2. Create trust line between destination (this) account
363 // and the issuer.
364 // 3. Apply correct noRipple settings on trust line. Use...
365 // a. this (destination) account and
366 // b. issuing account (not sending account).
367
368 auto const sleDst = psb.peek(keylet::account(account_));
369
370 // Can the account cover the trust line's reserve?
371 if (std::uint32_t const ownerCount = {sleDst->at(sfOwnerCount)};
372 mPriorBalance < psb.fees().accountReserve(ownerCount + 1))
373 {
374 JLOG(j_.trace()) << "Trust line does not exist. "
375 "Insufficent reserve to create line.";
376
378 }
379
380 Currency const currency = flowDeliver.getCurrency();
381 STAmount initialBalance(flowDeliver.issue());
382 initialBalance.setIssuer(noAccount());
383
384 // clang-format off
385 if (TER const ter = trustCreate(
386 psb, // payment sandbox
387 destLow, // is dest low?
388 issuer, // source
389 account_, // destination
390 trustLineKey.key, // ledger index
391 sleDst, // Account to add to
392 false, // authorize account
393 (sleDst->getFlags() & lsfDefaultRipple) == 0,
394 false, // freeze trust line
395 false, // deep freeze trust line
396 initialBalance, // zero initial balance
397 Issue(currency, account_), // limit of zero
398 0, // quality in
399 0, // quality out
400 viewJ); // journal
401 !isTesSuccess(ter))
402 {
403 return ter;
404 }
405 // clang-format on
406
407 psb.update(sleDst);
408
409 // Note that we _don't_ need to be careful about destroying
410 // the trust line if the check cashing fails. The transaction
411 // machinery will automatically clean it up.
412 }
413
414 // Since the destination is signing the check, they clearly want
415 // the funds even if their new total funds would exceed the limit
416 // on their trust line. So we tweak the trust line limits before
417 // calling flow and then restore the trust line limits afterwards.
418 auto const sleTrustLine = psb.peek(trustLineKey);
419 if (!sleTrustLine)
420 return tecNO_LINE;
421
422 SF_AMOUNT const& tweakedLimit = destLow ? sfLowLimit : sfHighLimit;
423 STAmount const savedLimit = sleTrustLine->at(tweakedLimit);
424
425 // Make sure the tweaked limits are restored when we leave scope.
426 scope_exit fixup(
427 [&psb, &trustLineKey, &tweakedLimit, &savedLimit]() {
428 if (auto const sleTrustLine = psb.peek(trustLineKey))
429 sleTrustLine->at(tweakedLimit) = savedLimit;
430 });
431
432 if (checkCashMakesTrustLine)
433 {
434 // Set the trust line limit to the highest possible value
435 // while flow runs.
436 STAmount const bigAmount(
438 sleTrustLine->at(tweakedLimit) = bigAmount;
439 }
440
441 // Let flow() do the heavy lifting on a check for an IOU.
442 auto const result = flow(
443 psb,
444 flowDeliver,
445 srcId,
446 account_,
447 STPathSet{},
448 true, // default path
449 static_cast<bool>(optDeliverMin), // partial payment
450 true, // owner pays transfer fee
452 std::nullopt,
453 sleCheck->getFieldAmount(sfSendMax),
454 viewJ);
455
456 if (result.result() != tesSUCCESS)
457 {
458 JLOG(ctx_.journal.warn()) << "flow failed when cashing check.";
459 return result.result();
460 }
461
462 // Make sure that deliverMin was satisfied.
463 if (optDeliverMin)
464 {
465 if (result.actualAmountOut < *optDeliverMin)
466 {
467 JLOG(ctx_.journal.warn())
468 << "flow did not produce DeliverMin.";
469 return tecPATH_PARTIAL;
470 }
471 if (doFix1623 && !checkCashMakesTrustLine)
472 // Set the delivered_amount metadata.
473 ctx_.deliver(result.actualAmountOut);
474 }
475
476 // Set the delivered amount metadata in all cases, not just
477 // for DeliverMin.
478 if (checkCashMakesTrustLine)
479 ctx_.deliver(result.actualAmountOut);
480
481 sleCheck = psb.peek(keylet::check(ctx_.tx[sfCheckID]));
482 }
483 }
484
485 // Check was cashed. If not a self send (and it shouldn't be), remove
486 // check link from destination directory.
487 if (srcId != account_ &&
488 !psb.dirRemove(
490 sleCheck->at(sfDestinationNode),
491 sleCheck->key(),
492 true))
493 {
494 JLOG(j_.fatal()) << "Unable to delete check from destination.";
495 return tefBAD_LEDGER;
496 }
497
498 // Remove check from check owner's directory.
499 if (!psb.dirRemove(
500 keylet::ownerDir(srcId),
501 sleCheck->at(sfOwnerNode),
502 sleCheck->key(),
503 true))
504 {
505 JLOG(j_.fatal()) << "Unable to delete check from owner.";
506 return tefBAD_LEDGER;
507 }
508
509 // If we succeeded, update the check owner's reserve.
510 adjustOwnerCount(psb, psb.peek(keylet::account(srcId)), -1, viewJ);
511
512 // Remove check from ledger.
513 psb.erase(sleCheck);
514
515 psb.apply(ctx_.rawView());
516 return tesSUCCESS;
517}
518
519} // namespace ripple
Stream fatal() const
Definition: Journal.h:341
Stream error() const
Definition: Journal.h:335
Stream trace() const
Severity stream access functions.
Definition: Journal.h:311
Stream warn() const
Definition: Journal.h:329
virtual beast::Journal journal(std::string const &name)=0
RawView & rawView()
Definition: ApplyContext.h:67
ApplyView & view()
Definition: ApplyContext.h:54
Application & app
Definition: ApplyContext.h:47
beast::Journal const journal
Definition: ApplyContext.h:51
void deliver(STAmount const &amount)
Sets the DeliveredAmount field in the metadata.
Definition: ApplyContext.h:80
bool dirRemove(Keylet const &directory, std::uint64_t page, uint256 const &key, bool keepRoot)
Remove an entry from a directory.
Definition: ApplyView.cpp:189
static TER preclaim(PreclaimContext const &ctx)
Definition: CashCheck.cpp:83
TER doApply() override
Definition: CashCheck.cpp:253
static NotTEC preflight(PreflightContext const &ctx)
Definition: CashCheck.cpp:36
A currency issued by an account.
Definition: Issue.h:36
A wrapper which makes credits unavailable to balances.
void apply(RawView &to)
Apply changes to base view.
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
virtual Fees const & fees() const =0
Returns the fees for the base ledger.
virtual Rules const & rules() const =0
Returns the tx processing rules.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition: Rules.cpp:122
void setIssuer(AccountID const &uIssuer)
Definition: STAmount.h:569
Currency const & getCurrency() const
Definition: STAmount.h:493
static const int cMaxOffset
Definition: STAmount.h:66
AccountID const & getIssuer() const
Definition: STAmount.h:499
bool native() const noexcept
Definition: STAmount.h:449
static const std::uint64_t cMaxValue
Definition: STAmount.h:70
STAmount const & getFieldAmount(SField const &field) const
Definition: STObject.cpp:635
std::uint32_t getFlags() const
Definition: STObject.cpp:507
AccountID const account_
Definition: Transactor.h:91
beast::Journal const j_
Definition: Transactor.h:89
XRPAmount mPriorBalance
Definition: Transactor.h:92
ApplyContext & ctx_
Definition: Transactor.h:88
Fees const & fees() const override
Returns the fees for the base ledger.
void erase(std::shared_ptr< SLE > const &sle) override
Remove a peeked SLE.
void update(std::shared_ptr< SLE > const &sle) override
Indicate changes to a peeked SLE.
bool exists(Keylet const &k) const override
Determine if a state item exists.
Rules const & rules() const override
Returns the tx processing rules.
std::shared_ptr< SLE > peek(Keylet const &k) override
Prepare to modify the SLE associated with key.
T max(T... args)
T min(T... args)
Keylet line(AccountID const &id0, AccountID const &id1, Currency const &currency) noexcept
The index of a trust line for a given currency.
Definition: Indexes.cpp:220
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:160
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition: Indexes.cpp:350
Keylet check(AccountID const &id, std::uint32_t seq) noexcept
A Check.
Definition: Indexes.cpp:312
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
AccountID const & noAccount()
A placeholder for empty accounts.
Definition: AccountID.cpp:177
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
Definition: UintTypes.cpp:129
STAmount accountFunds(ReadView const &view, AccountID const &id, STAmount const &saDefault, FreezeHandling freezeHandling, beast::Journal j)
Definition: View.cpp:442
@ fhZERO_IF_FROZEN
Definition: View.h:80
bool isLegalNet(STAmount const &value)
Definition: STAmount.h:581
@ lsfRequireDestTag
@ lsfDefaultRipple
@ lsfRequireAuth
bool isTesSuccess(TER x)
Definition: TER.h:656
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
Definition: Transactor.cpp:82
TER transferXRP(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &amount, beast::Journal j)
Definition: View.cpp:1856
StrandResult< TInAmt, TOutAmt > flow(PaymentSandbox const &baseView, Strand const &strand, std::optional< TInAmt > const &maxIn, TOutAmt const &out, beast::Journal j)
Request out amount from a strand.
Definition: StrandFlow.h:106
bool isFrozen(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer)
Definition: View.cpp:238
@ tefBAD_LEDGER
Definition: TER.h:170
@ no
Definition: Steps.h:42
static bool adjustOwnerCount(ApplyContext &ctx, int count)
Definition: SetOracle.cpp:186
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
Definition: Transactor.cpp:134
TER trustCreate(ApplyView &view, const bool bSrcHigh, AccountID const &uSrcAccountID, AccountID const &uDstAccountID, uint256 const &uIndex, SLE::ref sleAccount, const bool bAuth, const bool bNoRipple, const bool bFreeze, bool bDeepFreeze, STAmount const &saBalance, STAmount const &saLimit, std::uint32_t uQualityIn, std::uint32_t uQualityOut, beast::Journal j)
Create a trust line.
Definition: View.cpp:933
@ tecNO_ENTRY
Definition: TER.h:293
@ tecNO_LINE_INSUF_RESERVE
Definition: TER.h:279
@ tecNO_ISSUER
Definition: TER.h:286
@ tecFROZEN
Definition: TER.h:290
@ tecINTERNAL
Definition: TER.h:297
@ tecNO_PERMISSION
Definition: TER.h:292
@ tecDST_TAG_NEEDED
Definition: TER.h:296
@ tecPATH_PARTIAL
Definition: TER.h:269
@ tecNO_LINE
Definition: TER.h:288
@ tecUNFUNDED_PAYMENT
Definition: TER.h:272
@ tecFAILED_PROCESSING
Definition: TER.h:273
@ tecEXPIRED
Definition: TER.h:301
@ tecNO_AUTH
Definition: TER.h:287
@ tesSUCCESS
Definition: TER.h:242
std::string to_string(base_uint< Bits, Tag > const &a)
Definition: base_uint.h:629
constexpr std::uint32_t tfUniversalMask
Definition: TxFlags.h:62
bool hasExpired(ReadView const &view, std::optional< std::uint32_t > const &exp)
Determines whether the given expiration time has passed.
Definition: View.cpp:164
TERSubset< CanCvtToNotTEC > NotTEC
Definition: TER.h:587
XRPAmount xrpLiquid(ReadView const &view, AccountID const &id, std::int32_t ownerCountAdj, beast::Journal j)
Definition: View.cpp:506
@ temBAD_AMOUNT
Definition: TER.h:89
@ temBAD_CURRENCY
Definition: TER.h:90
@ temMALFORMED
Definition: TER.h:87
@ temINVALID_FLAG
Definition: TER.h:111
@ temDISABLED
Definition: TER.h:114
XRPAmount increment
Definition: protocol/Fees.h:36
A pair of SHAMap key and LedgerEntryType.
Definition: Keylet.h:39
uint256 key
Definition: Keylet.h:40
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:60
State information when preflighting a tx.
Definition: Transactor.h:32
beast::Journal const j
Definition: Transactor.h:38
A field with a type known at compile time.
Definition: SField.h:315