xrpld
Loading...
Searching...
No Matches
EscrowCreate.cpp
1#include <xrpl/tx/transactors/escrow/EscrowCreate.h>
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/chrono.h>
5#include <xrpl/beast/utility/Zero.h>
6#include <xrpl/conditions/Condition.h>
7#include <xrpl/core/ServiceRegistry.h>
8#include <xrpl/ledger/ApplyView.h>
9#include <xrpl/ledger/View.h>
10#include <xrpl/ledger/entries/EscrowEntry.h>
11#include <xrpl/ledger/helpers/AccountRootHelpers.h>
12#include <xrpl/ledger/helpers/DirectoryHelpers.h>
13#include <xrpl/ledger/helpers/MPTokenHelpers.h>
14#include <xrpl/ledger/helpers/RippleStateHelpers.h>
15#include <xrpl/ledger/helpers/SponsorHelpers.h>
16#include <xrpl/ledger/helpers/TokenHelpers.h>
17#include <xrpl/protocol/AccountID.h>
18#include <xrpl/protocol/Concepts.h>
19#include <xrpl/protocol/Feature.h>
20#include <xrpl/protocol/Indexes.h>
21#include <xrpl/protocol/Issue.h>
22#include <xrpl/protocol/LedgerFormats.h>
23#include <xrpl/protocol/MPTAmount.h>
24#include <xrpl/protocol/MPTIssue.h>
25#include <xrpl/protocol/Protocol.h>
26#include <xrpl/protocol/Rate.h>
27#include <xrpl/protocol/SField.h>
28#include <xrpl/protocol/STAmount.h>
29#include <xrpl/protocol/STLedgerEntry.h>
30#include <xrpl/protocol/STTx.h>
31#include <xrpl/protocol/TER.h>
32#include <xrpl/protocol/UintTypes.h>
33#include <xrpl/protocol/XRPAmount.h>
34#include <xrpl/tx/Transactor.h>
35#include <xrpl/tx/applySteps.h>
36
37#include <memory>
38#include <system_error>
39#include <variant>
40
41namespace xrpl {
42
43/*
44 Escrow
45 ======
46
47 Escrow is a feature of the XRP Ledger that allows you to send conditional
48 XRP payments. These conditional payments, called escrows, set aside XRP and
49 deliver it later when certain conditions are met. Conditions to successfully
50 finish an escrow include time-based unlocks and crypto-conditions. Escrows
51 can also be set to expire if not finished in time.
52
53 The XRP set aside in an escrow is locked up. No one can use or destroy the
54 XRP until the escrow has been successfully finished or canceled. Before the
55 expiration time, only the intended receiver can get the XRP. After the
56 expiration time, the XRP can only be returned to the sender.
57
58 For more details on escrow, including examples, diagrams and more please
59 visit https://xrpl.org/escrow.html
60
61 For details on specific transactions, including fields and validation rules
62 please see:
63
64 `EscrowCreate`
65 --------------
66 See: https://xrpl.org/escrowcreate.html
67
68 `EscrowFinish`
69 --------------
70 See: https://xrpl.org/escrowfinish.html
71
72 `EscrowCancel`
73 --------------
74 See: https://xrpl.org/escrowcancel.html
75*/
76
77//------------------------------------------------------------------------------
78
81{
82 auto const amount = ctx.tx[sfAmount];
83 return TxConsequences{ctx.tx, isXRP(amount) ? amount.xrp() : beast::kZero};
84}
85
86bool
88{
89 // Only require featureMPTokensV1 when the escrow amount is an MPT and
90 // fixCleanup3_2_0 is active; XRP/IOU escrows are unaffected by this gate.
91 if (ctx.rules.enabled(fixCleanup3_2_0) && ctx.tx[sfAmount].holds<MPTIssue>())
92 {
93 if (!ctx.rules.enabled(featureMPTokensV1))
94 return false;
95 }
96
97 return (!ctx.tx.isFieldPresent(sfBytecode) && !ctx.tx.isFieldPresent(sfData)) ||
98 ctx.rules.enabled(featureSmartEscrow);
99}
100
101template <ValidIssueType T>
102static NotTEC
104
105template <>
108{
109 STAmount const amount = ctx.tx[sfAmount];
110 if (amount.native() || amount <= beast::kZero)
111 return temBAD_AMOUNT;
112
113 if (badCurrency() == amount.get<Issue>().currency)
114 return temBAD_CURRENCY;
115
116 return tesSUCCESS;
117}
118
119template <>
122{
123 if (!ctx.rules.enabled(fixCleanup3_2_0) && !ctx.rules.enabled(featureMPTokensV1))
124 return temDISABLED;
125
126 auto const amount = ctx.tx[sfAmount];
127 if (amount.native() || amount.mpt() > MPTAmount{kMaxMpTokenAmount} || amount <= beast::kZero)
128 return temBAD_AMOUNT;
129
130 return tesSUCCESS;
131}
132
133NotTEC
135{
136 STAmount const amount{ctx.tx[sfAmount]};
137 if (!isXRP(amount))
138 {
139 if (!ctx.rules.enabled(featureTokenEscrow))
140 return temBAD_AMOUNT;
141
142 if (auto const ret = std::visit(
143 [&]<typename T>(T const&) { return escrowCreatePreflightHelper<T>(ctx); },
144 amount.asset().value());
145 !isTesSuccess(ret))
146 return ret;
147 }
148 else
149 {
150 if (amount <= beast::kZero)
151 return temBAD_AMOUNT;
152 }
153
154 // We must specify at least one timeout value
155 if (!ctx.tx[~sfCancelAfter] && !ctx.tx[~sfFinishAfter])
156 return temBAD_EXPIRATION;
157
158 // If both finish and cancel times are specified then the cancel time must
159 // be strictly after the finish time.
160 if (ctx.tx[~sfCancelAfter] && ctx.tx[~sfFinishAfter] &&
161 ctx.tx[sfCancelAfter] <= ctx.tx[sfFinishAfter])
162 return temBAD_EXPIRATION;
163
164 // In the absence of a FinishAfter, the escrow can be finished
165 // immediately, which can be confusing. When creating an escrow,
166 // we want to ensure that either a FinishAfter time is explicitly
167 // specified or a completion condition is attached.
168 if (!ctx.tx[~sfFinishAfter] && !ctx.tx[~sfCondition])
169 return temMALFORMED;
170
171 if (auto const cb = ctx.tx[~sfCondition])
172 {
173 using namespace xrpl::cryptoconditions;
174
176
177 auto condition = Condition::deserialize(*cb, ec);
178 if (!condition)
179 {
180 JLOG(ctx.j.debug()) << "Malformed condition during escrow creation: " << ec.message();
181 return temMALFORMED;
182 }
183 }
184
185 return tesSUCCESS;
186}
187
188template <ValidIssueType T>
189static TER
191 PreclaimContext const& ctx,
192 AccountID const& account,
193 AccountID const& dest,
194 STAmount const& amount);
195
196template <>
199 PreclaimContext const& ctx,
200 AccountID const& account,
201 AccountID const& dest,
202 STAmount const& amount)
203{
204 auto const& issue = amount.get<Issue>();
205 AccountID const& issuer = amount.getIssuer();
206 // If the issuer is the same as the account, return tecNO_PERMISSION
207 if (issuer == account)
208 return tecNO_PERMISSION;
209
210 // If the lsfAllowTrustLineLocking is not enabled, return tecNO_PERMISSION
211 auto const sleIssuer = ctx.view.read(keylet::account(issuer));
212 if (!sleIssuer)
213 return tecNO_ISSUER;
214 if (!sleIssuer->isFlag(lsfAllowTrustLineLocking))
215 return tecNO_PERMISSION;
216
217 // If the account does not have a trustline to the issuer, return tecNO_LINE
218 auto const sleRippleState = ctx.view.read(keylet::trustLine(account, issuer, issue.currency));
219 if (!sleRippleState)
220 return tecNO_LINE;
221
222 STAmount const balance = (*sleRippleState)[sfBalance];
223
224 // If balance is positive, issuer must have higher address than account
225 if (balance > beast::kZero && issuer < account)
226 return tecNO_PERMISSION; // LCOV_EXCL_LINE
227
228 // If balance is negative, issuer must have lower address than account
229 if (balance < beast::kZero && issuer > account)
230 return tecNO_PERMISSION; // LCOV_EXCL_LINE
231
232 // If the issuer has requireAuth set, check if the account is authorized
233 if (auto const ter = requireAuth(ctx.view, issue, account); !isTesSuccess(ter))
234 return ter;
235
236 // If the issuer has requireAuth set, check if the destination is authorized
237 if (auto const ter = requireAuth(ctx.view, issue, dest); !isTesSuccess(ter))
238 return ter;
239
240 // If the issuer has frozen the account, return tecFROZEN
241 if (isFrozen(ctx.view, account, issue))
242 return tecFROZEN;
243
244 // If the issuer has frozen the destination, return tecFROZEN
245 if (isFrozen(ctx.view, dest, issue))
246 return tecFROZEN;
247
248 STAmount const spendableAmount = accountHolds(
249 ctx.view, account, issue.currency, issuer, FreezeHandling::IgnoreFreeze, ctx.j);
250
251 // If the balance is less than or equal to 0, return tecINSUFFICIENT_FUNDS
252 if (spendableAmount <= beast::kZero)
254
255 // If the spendable amount is less than the amount, return
256 // tecINSUFFICIENT_FUNDS
257 if (spendableAmount < amount)
259
260 // If the amount is not addable to the balance, return tecPRECISION_LOSS
261 if (!canAdd(spendableAmount, amount))
262 return tecPRECISION_LOSS;
263
264 return tesSUCCESS;
265}
266
267template <>
270 PreclaimContext const& ctx,
271 AccountID const& account,
272 AccountID const& dest,
273 STAmount const& amount)
274{
275 AccountID const issuer = amount.getIssuer();
276 // If the issuer is the same as the account, return tecNO_PERMISSION
277 if (issuer == account)
278 return tecNO_PERMISSION;
279
280 // If the mpt does not exist, return tecOBJECT_NOT_FOUND
281 auto const issuanceKey = keylet::mptokenIssuance(amount.get<MPTIssue>().getMptID());
282 auto const sleIssuance = ctx.view.read(issuanceKey);
283 if (!sleIssuance)
284 return tecOBJECT_NOT_FOUND;
285
286 // If the lsfMPTCanEscrow is not enabled, return tecNO_PERMISSION
287 if (!sleIssuance->isFlag(lsfMPTCanEscrow))
288 return tecNO_PERMISSION;
289
290 // If the issuer is not the same as the issuer of the mpt, return
291 // tecNO_PERMISSION
292 if (sleIssuance->getAccountID(sfIssuer) != issuer)
293 return tecNO_PERMISSION; // LCOV_EXCL_LINE
294
295 // If the account does not have the mpt, return tecOBJECT_NOT_FOUND
296 if (!ctx.view.exists(keylet::mptoken(issuanceKey.key, account)))
297 return tecOBJECT_NOT_FOUND;
298
299 // If the issuer has requireAuth set, check if the account is
300 // authorized
301 auto const& mptIssue = amount.get<MPTIssue>();
302 if (auto const ter = requireAuth(ctx.view, mptIssue, account, AuthType::WeakAuth);
303 !isTesSuccess(ter))
304 return ter;
305
306 // If the issuer has requireAuth set, check if the destination is
307 // authorized
308 if (auto const ter = requireAuth(ctx.view, mptIssue, dest, AuthType::WeakAuth);
309 !isTesSuccess(ter))
310 return ter;
311
312 // If the issuer has frozen the account, return tecLOCKED
313 if (isFrozen(ctx.view, account, *sleIssuance))
314 return tecLOCKED;
315
316 // If the issuer has frozen the destination, return tecLOCKED
317 if (isFrozen(ctx.view, dest, *sleIssuance))
318 return tecLOCKED;
319
320 // If the mpt cannot be transferred, return tecNO_AUTH
321 if (auto const ter = canTransfer(ctx.view, mptIssue, account, dest); !isTesSuccess(ter))
322 return ter;
323
324 STAmount const spendableAmount = accountHolds(
325 ctx.view,
326 account,
327 amount.get<MPTIssue>(),
330 ctx.j);
331
332 // If the balance is less than or equal to 0, return tecINSUFFICIENT_FUNDS
333 if (spendableAmount <= beast::kZero)
335
336 // If the spendable amount is less than the amount, return
337 // tecINSUFFICIENT_FUNDS
338 if (spendableAmount < amount)
340
341 return tesSUCCESS;
342}
343
344TER
346{
347 STAmount const amount{ctx.tx[sfAmount]};
348 AccountID const account{ctx.tx[sfAccount]};
349 AccountID const dest{ctx.tx[sfDestination]};
350
351 auto const sled = ctx.view.read(keylet::account(dest));
352 if (!sled)
353 return tecNO_DST;
354
355 // Pseudo-accounts cannot receive escrow. Note, this is not amendment-gated
356 // because all writes to pseudo-account discriminator fields **are**
357 // amendment gated, hence the behaviour of this check will always match the
358 // currently active amendments.
359 if (isPseudoAccount(sled))
360 return tecNO_PERMISSION;
361
362 if (!isXRP(amount))
363 {
364 if (!ctx.view.rules().enabled(featureTokenEscrow))
365 return temDISABLED; // LCOV_EXCL_LINE
366
367 if (auto const ret = std::visit(
368 [&]<typename T>(T const&) {
369 return escrowCreatePreclaimHelper<T>(ctx, account, dest, amount);
370 },
371 amount.asset().value());
372 !isTesSuccess(ret))
373 return ret;
374 }
375 return tesSUCCESS;
376}
377
378template <ValidIssueType T>
379static TER
381 ApplyView& view,
382 AccountID const& issuer,
383 AccountID const& sender,
384 STAmount const& amount,
385 beast::Journal journal);
386
387template <>
390 ApplyView& view,
391 AccountID const& issuer,
392 AccountID const& sender,
393 STAmount const& amount,
394 beast::Journal journal)
395{
396 // Defensive: Issuer cannot create an escrow
397 if (issuer == sender)
398 return tecINTERNAL; // LCOV_EXCL_LINE
399
400 auto const ter =
401 directSendNoFee(view, sender, issuer, amount, !amount.holds<MPTIssue>(), journal);
402 if (!isTesSuccess(ter))
403 return ter; // LCOV_EXCL_LINE
404 return tesSUCCESS;
405}
406
407template <>
410 ApplyView& view,
411 AccountID const& issuer,
412 AccountID const& sender,
413 STAmount const& amount,
414 beast::Journal journal)
415{
416 // Defensive: Issuer cannot create an escrow
417 if (issuer == sender)
418 return tecINTERNAL; // LCOV_EXCL_LINE
419
420 auto const ter = lockEscrowMPT(view, sender, amount, journal);
421 if (!isTesSuccess(ter))
422 return ter; // LCOV_EXCL_LINE
423 return tesSUCCESS;
424}
425
426TER
428{
429 auto const closeTime = ctx_.view().header().parentCloseTime;
430
431 if (ctx_.tx[~sfCancelAfter] && after(closeTime, ctx_.tx[sfCancelAfter]))
432 return tecNO_PERMISSION;
433
434 if (ctx_.tx[~sfFinishAfter] && after(closeTime, ctx_.tx[sfFinishAfter]))
435 return tecNO_PERMISSION;
436
437 auto const sle = ctx_.view().peek(keylet::account(accountID_));
438 if (!sle)
439 return tefINTERNAL; // LCOV_EXCL_LINE
440
441 // Check reserve and funds availability
442 STAmount const amount{ctx_.tx[sfAmount]};
443
444 auto const balance = sle->getFieldAmount(sfBalance).xrp();
445 // First check: whoever is on the hook for the new owner increment
446 // can cover it. When sponsored this hits the sponsor branch and
447 // validates the sponsor's reserve + remaining credit. When
448 // unsponsored this hits the source branch and validates the
449 // source's pre-lock balance against base + (currentOC+1)*increment.
450 if (auto const ret =
451 checkReserve(ctx_.getApplyViewContext(), sle, balance, {.ownerCountDelta = 1}, j_);
452 !isTesSuccess(ret))
453 return ret;
454
455 if (isXRP(amount))
456 {
457 // Second check (XRP escrow only): after locking the escrowed
458 // amount, the source must still meet its own reserve floor. This is
459 // always the source's own balance against the source's own reserve —
460 // the sponsor's reserve was already validated above, and a sponsor
461 // never covers the locked funds. We compare directly (rather than via
462 // checkReserve) because that helper diverts to the sponsor's balance
463 // when a sponsor is present and would ignore the source's post-lock
464 // balance entirely. ownerCountDelta differs by case:
465 // - sponsored: 0 — sponsor covers the new owner increment, so the
466 // source only owes reserve for its current owners.
467 // - unsponsored: 1 — source owes reserve including the new increment.
468 auto const sourceReserve = accountReserve(
469 ctx_.view(), sle, j_, {.ownerCountDelta = getTxReserveSponsorID(ctx_.tx) ? 0 : 1});
470 if (balance - STAmount(amount).xrp() < sourceReserve)
471 return tecUNFUNDED;
472 }
473
474 // Check destination account
475 {
476 auto const sled = ctx_.view().read(keylet::account(ctx_.tx[sfDestination]));
477 if (!sled)
478 return tecNO_DST; // LCOV_EXCL_LINE
479 if (sled->isFlag(lsfRequireDestTag) && !ctx_.tx[~sfDestinationTag])
480 return tecDST_TAG_NEEDED;
481 }
482
483 // Create escrow in ledger. Note that we use the value from the
484 // sequence or ticket. For more explanation see comments in SeqProxy.h.
485 EscrowEntryW escrow(accountID_, ctx_.tx.getSeqProxy(), ctx_.view(), j_);
486 Keylet const escrowKeylet = escrow.keylet();
487 escrow.newSLE();
488 (*escrow)[sfAmount] = amount;
489 (*escrow)[sfAccount] = accountID_;
490 (*escrow)[~sfCondition] = ctx_.tx[~sfCondition];
491 (*escrow)[~sfSourceTag] = ctx_.tx[~sfSourceTag];
492 (*escrow)[sfDestination] = ctx_.tx[sfDestination];
493 (*escrow)[~sfCancelAfter] = ctx_.tx[~sfCancelAfter];
494 (*escrow)[~sfFinishAfter] = ctx_.tx[~sfFinishAfter];
495 (*escrow)[~sfDestinationTag] = ctx_.tx[~sfDestinationTag];
496
497 if (ctx_.view().rules().enabled(fixIncludeKeyletFields))
498 {
499 (*escrow)[sfSequence] = ctx_.tx.getSeqProxy().value();
500 }
501
502 if (ctx_.view().rules().enabled(featureTokenEscrow) && !isXRP(amount))
503 {
504 auto const xferRate = transferRate(ctx_.view(), amount);
505 if (xferRate != kParityRate)
506 (*escrow)[sfTransferRate] = xferRate.value;
507 }
508
509 escrow.insert();
510
511 // Add escrow to sender's owner directory
512 {
513 auto page = ctx_.view().dirInsert(
515 if (!page)
516 return tecDIR_FULL; // LCOV_EXCL_LINE
517 (*escrow)[sfOwnerNode] = *page;
518 }
519
520 // If it's not a self-send, add escrow to recipient's owner directory.
521 AccountID const dest = ctx_.tx[sfDestination];
522 if (dest != accountID_)
523 {
524 auto page =
525 ctx_.view().dirInsert(keylet::ownerDir(dest), escrowKeylet, describeOwnerDir(dest));
526 if (!page)
527 return tecDIR_FULL; // LCOV_EXCL_LINE
528 (*escrow)[sfDestinationNode] = *page;
529 }
530
531 // IOU escrow objects are added to the issuer's owner directory to help
532 // track the total locked balance. For MPT, this isn't necessary because the
533 // locked balance is already stored directly in the MPTokenIssuance object.
534 AccountID const issuer = amount.getIssuer();
535 if (!isXRP(amount) && issuer != accountID_ && issuer != dest && !amount.holds<MPTIssue>())
536 {
537 auto page =
538 ctx_.view().dirInsert(keylet::ownerDir(issuer), escrowKeylet, describeOwnerDir(issuer));
539 if (!page)
540 return tecDIR_FULL; // LCOV_EXCL_LINE
541 (*escrow)[sfIssuerNode] = *page;
542 }
543
544 // Deduct owner's balance
545 if (isXRP(amount))
546 {
547 (*sle)[sfBalance] = (*sle)[sfBalance] - amount;
548 }
549 else
550 {
551 if (auto const ret = std::visit(
552 [&]<typename T>(T const&) {
553 return escrowLockApplyHelper<T>(ctx_.view(), issuer, accountID_, amount, j_);
554 },
555 amount.asset().value());
556 !isTesSuccess(ret))
557 {
558 return ret; // LCOV_EXCL_LINE
559 }
560 }
561
562 // increment owner count
563 increaseOwnerCount(ctx_.getApplyViewContext(), sle, 1, ctx_.journal);
564 addSponsorToLedgerEntry(ctx_.getApplyViewContext(), escrow.mutableRawSle());
565 ctx_.view().update(sle);
566 return tesSUCCESS;
567}
568
569void
571{
572 // No transaction-specific invariants yet (future work).
573}
574
575bool
577 STTx const&,
578 TER,
579 XRPAmount,
580 ReadView const&,
581 beast::Journal const&)
582{
583 // No transaction-specific invariants yet (future work).
584 return true;
585}
586} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:44
Stream debug() const
Definition Journal.h:344
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:141
static bool checkExtraFeatures(PreflightContext const &ctx)
static NotTEC preflight(PreflightContext const &ctx)
void visitInvariantEntry(bool isDelete, SLE::ConstRef before, SLE::ConstRef after) override
Inspect a single ledger entry modified by this transaction.
TER doApply() override
static TER preclaim(PreclaimContext const &ctx)
bool finalizeInvariants(STTx const &tx, TER result, XRPAmount fee, ReadView const &view, beast::Journal const &j) override
Check transaction-specific post-conditions after all entries have been visited.
static TxConsequences makeTxConsequences(PreflightContext const &ctx)
A currency issued by an account.
Definition Issue.h:18
Currency currency
Definition Issue.h:20
constexpr MPTID const & getMptID() const
Definition MPTIssue.h:43
A view into a ledger.
Definition ReadView.h:41
virtual Rules const & rules() const =0
Returns the tx processing rules.
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
bool enabled(UInt256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:182
constexpr bool holds() const noexcept
Definition STAmount.h:478
constexpr TIss const & get() const
bool native() const noexcept
Definition STAmount.h:471
Asset const & asset() const
Definition STAmount.h:496
AccountID const & getIssuer() const
Definition STAmount.h:516
XRPAmount xrp() const
Definition STAmount.cpp:272
std::shared_ptr< STLedgerEntry const > const & ConstRef
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:464
beast::Journal const j_
Definition Transactor.h:164
AccountID const accountID_
Definition Transactor.h:166
ApplyContext & ctx_
Definition Transactor.h:162
Class describing the consequences to the account of applying a transaction if the transaction consume...
Definition applySteps.h:53
static std::unique_ptr< Condition > deserialize(Slice s, std::error_code &ec)
Load a condition from its binary form.
T message(T... args)
constexpr Zero kZero
Definition Zero.h:30
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:403
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Definition Indexes.cpp:573
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:220
Keylet mptokenIssuance(MPTID const &issuanceID) noexcept
Definition Indexes.cpp:567
Keylet trustLine(AccountID const &id0, AccountID const &id1, Currency const &currency) noexcept
The index of a trust line for a given currency.
Definition Indexes.cpp:275
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
bool isXRP(AccountID const &c)
Definition AccountID.h:84
NotTEC escrowCreatePreflightHelper< Issue >(PreflightContext const &ctx)
@ tefINTERNAL
Definition TER.h:168
TER lockEscrowMPT(ApplyView &view, AccountID const &uGrantorID, STAmount const &saAmount, beast::Journal j)
TER checkReserve(ApplyViewContext ctx, SLE::ConstRef accSle, XRPAmount accBalance, SLE::ConstRef sponsorSle, Adjustment adj, beast::Journal j, TER insufReserveCode=tecINSUFFICIENT_RESERVE)
Check if an account has sufficient reserve.
TER canTransfer(ReadView const &view, MPTIssue const &mptIssue, AccountID const &from, AccountID const &to, WaiveMPTCanTransfer waive=WaiveMPTCanTransfer::No, std::uint8_t depth=0)
Check whether to may receive the given MPT from from.
void increaseOwnerCount(ApplyView &view, SLE::Ref accountSle, SLE::Ref sponsorSle, std::uint32_t count, beast::Journal j)
Increase owner-count fields when the caller supplies the sponsor.
void addSponsorToLedgerEntry(SLE::Ref sle, SLE::ConstRef sponsorSle, SF_ACCOUNT const &field=sfSponsor)
Stamp a reserve sponsor onto a ledger entry using an explicit sponsor SLE.
TER escrowCreatePreclaimHelper< MPTIssue >(PreclaimContext const &ctx, AccountID const &account, AccountID const &dest, STAmount const &amount)
bool canAdd(STAmount const &amt1, STAmount const &amt2)
Safely checks if two STAmount values can be added without overflow, underflow, or precision loss.
Definition STAmount.cpp:465
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:614
TER escrowLockApplyHelper< MPTIssue >(ApplyView &view, AccountID const &issuer, AccountID const &sender, STAmount const &amount, beast::Journal journal)
Rate transferRate(ReadView const &view, AccountID const &issuer)
Returns IOU issuer transfer fee as Rate.
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition View.cpp:644
Rate const kParityRate
A transfer rate signifying a 1:1 exchange.
TER directSendNoFee(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, bool bCheckIssuer, beast::Journal j)
Calls static directSendNoFeeIOU if saAmount represents Issue.
static TER escrowLockApplyHelper(ApplyView &view, AccountID const &issuer, AccountID const &sender, STAmount const &amount, beast::Journal journal)
EscrowEntry< ApplyView > EscrowEntryW
Definition EscrowEntry.h:35
bool isFrozen(ReadView const &view, AccountID const &account, MPTIssue const &mptIssue, std::uint8_t depth=0)
Returns true if account cannot send or receive tokens of mptIssue because a freeze applies.
TER escrowCreatePreclaimHelper< Issue >(PreclaimContext const &ctx, AccountID const &account, AccountID const &dest, STAmount const &amount)
bool isPseudoAccount(SLE::const_pointer sleAcct)
Returns true if and only if sleAcct is a pseudo-account of any kind (i.e.
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:34
static NotTEC escrowCreatePreflightHelper(PreflightContext const &ctx)
@ temBAD_CURRENCY
Definition TER.h:78
@ temBAD_EXPIRATION
Definition TER.h:79
@ temMALFORMED
Definition TER.h:75
@ temDISABLED
Definition TER.h:102
@ temBAD_AMOUNT
Definition TER.h:77
bool isTesSuccess(TER x) noexcept
Definition TER.h:683
TERSubset< CanCvtToTER > TER
Definition TER.h:654
XRPAmount accountReserve(ReadView const &view, SLE::ConstRef sle, beast::Journal j, Adjustment adj={})
Returns the account reserve, in drops.
TER requireAuth(ReadView const &view, MPTIssue const &mptIssue, AccountID const &account, AuthType authType=AuthType::Legacy, std::uint8_t depth=0)
Check if the account lacks required authorization for MPT.
static TER escrowCreatePreclaimHelper(PreclaimContext const &ctx, AccountID const &account, AccountID const &dest, STAmount const &amount)
@ tecDIR_FULL
Definition TER.h:295
@ tecLOCKED
Definition TER.h:366
@ tecOBJECT_NOT_FOUND
Definition TER.h:334
@ tecINTERNAL
Definition TER.h:318
@ tecFROZEN
Definition TER.h:311
@ tecINSUFFICIENT_FUNDS
Definition TER.h:333
@ tecNO_LINE
Definition TER.h:309
@ tecPRECISION_LOSS
Definition TER.h:371
@ tecNO_PERMISSION
Definition TER.h:313
@ tecDST_TAG_NEEDED
Definition TER.h:317
@ tecNO_ISSUER
Definition TER.h:307
@ tecNO_DST
Definition TER.h:298
@ tecUNFUNDED
Definition TER.h:303
TER escrowLockApplyHelper< Issue >(ApplyView &view, AccountID const &issuer, AccountID const &sender, STAmount const &amount, beast::Journal journal)
NotTEC escrowCreatePreflightHelper< MPTIssue >(PreflightContext const &ctx)
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
std::function< void(SLE::Ref)> describeOwnerDir(AccountID const &account)
Returns a function that sets the owner on a directory SLE.
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j, SpendableHandling includeFullBalance=SpendableHandling::SimpleBalance)
@ tesSUCCESS
Definition TER.h:250
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:20
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:92
ReadView const & view
Definition Transactor.h:95
beast::Journal const j
Definition Transactor.h:100
State information when preflighting a tx.
Definition Transactor.h:39
beast::Journal const j
Definition Transactor.h:46
T visit(T... args)