rippled
Loading...
Searching...
No Matches
EscrowCreate.cpp
1#include <xrpl/basics/Log.h>
2#include <xrpl/basics/chrono.h>
3#include <xrpl/conditions/Condition.h>
4#include <xrpl/ledger/ApplyView.h>
5#include <xrpl/ledger/View.h>
6#include <xrpl/ledger/helpers/AccountRootHelpers.h>
7#include <xrpl/ledger/helpers/DirectoryHelpers.h>
8#include <xrpl/ledger/helpers/MPTokenHelpers.h>
9#include <xrpl/ledger/helpers/RippleStateHelpers.h>
10#include <xrpl/protocol/Feature.h>
11#include <xrpl/protocol/Indexes.h>
12#include <xrpl/protocol/MPTAmount.h>
13#include <xrpl/protocol/Rate.h>
14#include <xrpl/protocol/TxFlags.h>
15#include <xrpl/protocol/XRPAmount.h>
16#include <xrpl/tx/transactors/escrow/EscrowCreate.h>
17
18namespace xrpl {
19
20/*
21 Escrow
22 ======
23
24 Escrow is a feature of the XRP Ledger that allows you to send conditional
25 XRP payments. These conditional payments, called escrows, set aside XRP and
26 deliver it later when certain conditions are met. Conditions to successfully
27 finish an escrow include time-based unlocks and crypto-conditions. Escrows
28 can also be set to expire if not finished in time.
29
30 The XRP set aside in an escrow is locked up. No one can use or destroy the
31 XRP until the escrow has been successfully finished or canceled. Before the
32 expiration time, only the intended receiver can get the XRP. After the
33 expiration time, the XRP can only be returned to the sender.
34
35 For more details on escrow, including examples, diagrams and more please
36 visit https://xrpl.org/escrow.html
37
38 For details on specific transactions, including fields and validation rules
39 please see:
40
41 `EscrowCreate`
42 --------------
43 See: https://xrpl.org/escrowcreate.html
44
45 `EscrowFinish`
46 --------------
47 See: https://xrpl.org/escrowfinish.html
48
49 `EscrowCancel`
50 --------------
51 See: https://xrpl.org/escrowcancel.html
52*/
53
54//------------------------------------------------------------------------------
55
56TxConsequences
58{
59 auto const amount = ctx.tx[sfAmount];
60 return TxConsequences{ctx.tx, isXRP(amount) ? amount.xrp() : beast::zero};
61}
62
63template <ValidIssueType T>
64static NotTEC
66
67template <>
70{
71 STAmount const amount = ctx.tx[sfAmount];
72 if (amount.native() || amount <= beast::zero)
73 return temBAD_AMOUNT;
74
75 if (badCurrency() == amount.getCurrency())
76 return temBAD_CURRENCY;
77
78 return tesSUCCESS;
79}
80
81template <>
84{
85 if (!ctx.rules.enabled(featureMPTokensV1))
86 return temDISABLED;
87
88 auto const amount = ctx.tx[sfAmount];
89 if (amount.native() || amount.mpt() > MPTAmount{maxMPTokenAmount} || amount <= beast::zero)
90 return temBAD_AMOUNT;
91
92 return tesSUCCESS;
93}
94
97{
98 STAmount const amount{ctx.tx[sfAmount]};
99 if (!isXRP(amount))
100 {
101 if (!ctx.rules.enabled(featureTokenEscrow))
102 return temBAD_AMOUNT;
103
104 if (auto const ret = std::visit(
105 [&]<typename T>(T const&) { return escrowCreatePreflightHelper<T>(ctx); },
106 amount.asset().value());
107 !isTesSuccess(ret))
108 return ret;
109 }
110 else
111 {
112 if (amount <= beast::zero)
113 return temBAD_AMOUNT;
114 }
115
116 // We must specify at least one timeout value
117 if (!ctx.tx[~sfCancelAfter] && !ctx.tx[~sfFinishAfter])
118 return temBAD_EXPIRATION;
119
120 // If both finish and cancel times are specified then the cancel time must
121 // be strictly after the finish time.
122 if (ctx.tx[~sfCancelAfter] && ctx.tx[~sfFinishAfter] &&
123 ctx.tx[sfCancelAfter] <= ctx.tx[sfFinishAfter])
124 return temBAD_EXPIRATION;
125
126 // In the absence of a FinishAfter, the escrow can be finished
127 // immediately, which can be confusing. When creating an escrow,
128 // we want to ensure that either a FinishAfter time is explicitly
129 // specified or a completion condition is attached.
130 if (!ctx.tx[~sfFinishAfter] && !ctx.tx[~sfCondition])
131 return temMALFORMED;
132
133 if (auto const cb = ctx.tx[~sfCondition])
134 {
135 using namespace xrpl::cryptoconditions;
136
138
139 auto condition = Condition::deserialize(*cb, ec);
140 if (!condition)
141 {
142 JLOG(ctx.j.debug()) << "Malformed condition during escrow creation: " << ec.message();
143 return temMALFORMED;
144 }
145 }
146
147 return tesSUCCESS;
148}
149
150template <ValidIssueType T>
151static TER
153 PreclaimContext const& ctx,
154 AccountID const& account,
155 AccountID const& dest,
156 STAmount const& amount);
157
158template <>
161 PreclaimContext const& ctx,
162 AccountID const& account,
163 AccountID const& dest,
164 STAmount const& amount)
165{
166 AccountID const issuer = amount.getIssuer();
167 // If the issuer is the same as the account, return tecNO_PERMISSION
168 if (issuer == account)
169 return tecNO_PERMISSION;
170
171 // If the lsfAllowTrustLineLocking is not enabled, return tecNO_PERMISSION
172 auto const sleIssuer = ctx.view.read(keylet::account(issuer));
173 if (!sleIssuer)
174 return tecNO_ISSUER;
175 if (!sleIssuer->isFlag(lsfAllowTrustLineLocking))
176 return tecNO_PERMISSION;
177
178 // If the account does not have a trustline to the issuer, return tecNO_LINE
179 auto const sleRippleState = ctx.view.read(keylet::line(account, issuer, amount.getCurrency()));
180 if (!sleRippleState)
181 return tecNO_LINE;
182
183 STAmount const balance = (*sleRippleState)[sfBalance];
184
185 // If balance is positive, issuer must have higher address than account
186 if (balance > beast::zero && issuer < account)
187 return tecNO_PERMISSION; // LCOV_EXCL_LINE
188
189 // If balance is negative, issuer must have lower address than account
190 if (balance < beast::zero && issuer > account)
191 return tecNO_PERMISSION; // LCOV_EXCL_LINE
192
193 // If the issuer has requireAuth set, check if the account is authorized
194 if (auto const ter = requireAuth(ctx.view, amount.issue(), account); !isTesSuccess(ter))
195 return ter;
196
197 // If the issuer has requireAuth set, check if the destination is authorized
198 if (auto const ter = requireAuth(ctx.view, amount.issue(), dest); !isTesSuccess(ter))
199 return ter;
200
201 // If the issuer has frozen the account, return tecFROZEN
202 if (isFrozen(ctx.view, account, amount.issue()))
203 return tecFROZEN;
204
205 // If the issuer has frozen the destination, return tecFROZEN
206 if (isFrozen(ctx.view, dest, amount.issue()))
207 return tecFROZEN;
208
209 STAmount const spendableAmount =
210 accountHolds(ctx.view, account, amount.getCurrency(), issuer, fhIGNORE_FREEZE, ctx.j);
211
212 // If the balance is less than or equal to 0, return tecINSUFFICIENT_FUNDS
213 if (spendableAmount <= beast::zero)
215
216 // If the spendable amount is less than the amount, return
217 // tecINSUFFICIENT_FUNDS
218 if (spendableAmount < amount)
220
221 // If the amount is not addable to the balance, return tecPRECISION_LOSS
222 if (!canAdd(spendableAmount, amount))
223 return tecPRECISION_LOSS;
224
225 return tesSUCCESS;
226}
227
228template <>
231 PreclaimContext const& ctx,
232 AccountID const& account,
233 AccountID const& dest,
234 STAmount const& amount)
235{
236 AccountID const issuer = amount.getIssuer();
237 // If the issuer is the same as the account, return tecNO_PERMISSION
238 if (issuer == account)
239 return tecNO_PERMISSION;
240
241 // If the mpt does not exist, return tecOBJECT_NOT_FOUND
242 auto const issuanceKey = keylet::mptIssuance(amount.get<MPTIssue>().getMptID());
243 auto const sleIssuance = ctx.view.read(issuanceKey);
244 if (!sleIssuance)
245 return tecOBJECT_NOT_FOUND;
246
247 // If the lsfMPTCanEscrow is not enabled, return tecNO_PERMISSION
248 if (!sleIssuance->isFlag(lsfMPTCanEscrow))
249 return tecNO_PERMISSION;
250
251 // If the issuer is not the same as the issuer of the mpt, return
252 // tecNO_PERMISSION
253 if (sleIssuance->getAccountID(sfIssuer) != issuer)
254 return tecNO_PERMISSION; // LCOV_EXCL_LINE
255
256 // If the account does not have the mpt, return tecOBJECT_NOT_FOUND
257 if (!ctx.view.exists(keylet::mptoken(issuanceKey.key, account)))
258 return tecOBJECT_NOT_FOUND;
259
260 // If the issuer has requireAuth set, check if the account is
261 // authorized
262 auto const& mptIssue = amount.get<MPTIssue>();
263 if (auto const ter = requireAuth(ctx.view, mptIssue, account, AuthType::WeakAuth);
264 !isTesSuccess(ter))
265 return ter;
266
267 // If the issuer has requireAuth set, check if the destination is
268 // authorized
269 if (auto const ter = requireAuth(ctx.view, mptIssue, dest, AuthType::WeakAuth);
270 !isTesSuccess(ter))
271 return ter;
272
273 // If the issuer has frozen the account, return tecLOCKED
274 if (isFrozen(ctx.view, account, mptIssue))
275 return tecLOCKED;
276
277 // If the issuer has frozen the destination, return tecLOCKED
278 if (isFrozen(ctx.view, dest, mptIssue))
279 return tecLOCKED;
280
281 // If the mpt cannot be transferred, return tecNO_AUTH
282 if (auto const ter = canTransfer(ctx.view, mptIssue, account, dest); !isTesSuccess(ter))
283 return ter;
284
285 STAmount const spendableAmount = accountHolds(
286 ctx.view, account, amount.get<MPTIssue>(), fhIGNORE_FREEZE, ahIGNORE_AUTH, ctx.j);
287
288 // If the balance is less than or equal to 0, return tecINSUFFICIENT_FUNDS
289 if (spendableAmount <= beast::zero)
291
292 // If the spendable amount is less than the amount, return
293 // tecINSUFFICIENT_FUNDS
294 if (spendableAmount < amount)
296
297 return tesSUCCESS;
298}
299
300TER
302{
303 STAmount const amount{ctx.tx[sfAmount]};
304 AccountID const account{ctx.tx[sfAccount]};
305 AccountID const dest{ctx.tx[sfDestination]};
306
307 auto const sled = ctx.view.read(keylet::account(dest));
308 if (!sled)
309 return tecNO_DST;
310
311 // Pseudo-accounts cannot receive escrow. Note, this is not amendment-gated
312 // because all writes to pseudo-account discriminator fields **are**
313 // amendment gated, hence the behaviour of this check will always match the
314 // currently active amendments.
315 if (isPseudoAccount(sled))
316 return tecNO_PERMISSION;
317
318 if (!isXRP(amount))
319 {
320 if (!ctx.view.rules().enabled(featureTokenEscrow))
321 return temDISABLED; // LCOV_EXCL_LINE
322
323 if (auto const ret = std::visit(
324 [&]<typename T>(T const&) {
325 return escrowCreatePreclaimHelper<T>(ctx, account, dest, amount);
326 },
327 amount.asset().value());
328 !isTesSuccess(ret))
329 return ret;
330 }
331 return tesSUCCESS;
332}
333
334template <ValidIssueType T>
335static TER
337 ApplyView& view,
338 AccountID const& issuer,
339 AccountID const& sender,
340 STAmount const& amount,
341 beast::Journal journal);
342
343template <>
346 ApplyView& view,
347 AccountID const& issuer,
348 AccountID const& sender,
349 STAmount const& amount,
350 beast::Journal journal)
351{
352 // Defensive: Issuer cannot create an escrow
353 if (issuer == sender)
354 return tecINTERNAL; // LCOV_EXCL_LINE
355
356 auto const ter = rippleCredit(view, sender, issuer, amount, !amount.holds<MPTIssue>(), journal);
357 if (!isTesSuccess(ter))
358 return ter; // LCOV_EXCL_LINE
359 return tesSUCCESS;
360}
361
362template <>
365 ApplyView& view,
366 AccountID const& issuer,
367 AccountID const& sender,
368 STAmount const& amount,
369 beast::Journal journal)
370{
371 // Defensive: Issuer cannot create an escrow
372 if (issuer == sender)
373 return tecINTERNAL; // LCOV_EXCL_LINE
374
375 auto const ter = rippleLockEscrowMPT(view, sender, amount, journal);
376 if (!isTesSuccess(ter))
377 return ter; // LCOV_EXCL_LINE
378 return tesSUCCESS;
379}
380
381TER
383{
384 auto const closeTime = ctx_.view().header().parentCloseTime;
385
386 if (ctx_.tx[~sfCancelAfter] && after(closeTime, ctx_.tx[sfCancelAfter]))
387 return tecNO_PERMISSION;
388
389 if (ctx_.tx[~sfFinishAfter] && after(closeTime, ctx_.tx[sfFinishAfter]))
390 return tecNO_PERMISSION;
391
392 auto const sle = ctx_.view().peek(keylet::account(account_));
393 if (!sle)
394 return tefINTERNAL; // LCOV_EXCL_LINE
395
396 // Check reserve and funds availability
397 STAmount const amount{ctx_.tx[sfAmount]};
398
399 auto const reserve = ctx_.view().fees().accountReserve((*sle)[sfOwnerCount] + 1);
400
401 auto const balance = sle->getFieldAmount(sfBalance).xrp();
402 if (balance < reserve)
404
405 // Check reserve and funds availability
406 if (isXRP(amount))
407 {
408 if (balance < reserve + STAmount(amount).xrp())
409 return tecUNFUNDED;
410 }
411
412 // Check destination account
413 {
414 auto const sled = ctx_.view().read(keylet::account(ctx_.tx[sfDestination]));
415 if (!sled)
416 return tecNO_DST; // LCOV_EXCL_LINE
417 if ((((*sled)[sfFlags] & lsfRequireDestTag) != 0u) && !ctx_.tx[~sfDestinationTag])
418 return tecDST_TAG_NEEDED;
419 }
420
421 // Create escrow in ledger. Note that we we use the value from the
422 // sequence or ticket. For more explanation see comments in SeqProxy.h.
423 Keylet const escrowKeylet = keylet::escrow(account_, ctx_.tx.getSeqValue());
424 auto const slep = std::make_shared<SLE>(escrowKeylet);
425 (*slep)[sfAmount] = amount;
426 (*slep)[sfAccount] = account_;
427 (*slep)[~sfCondition] = ctx_.tx[~sfCondition];
428 (*slep)[~sfSourceTag] = ctx_.tx[~sfSourceTag];
429 (*slep)[sfDestination] = ctx_.tx[sfDestination];
430 (*slep)[~sfCancelAfter] = ctx_.tx[~sfCancelAfter];
431 (*slep)[~sfFinishAfter] = ctx_.tx[~sfFinishAfter];
432 (*slep)[~sfDestinationTag] = ctx_.tx[~sfDestinationTag];
433
434 if (ctx_.view().rules().enabled(fixIncludeKeyletFields))
435 {
436 (*slep)[sfSequence] = ctx_.tx.getSeqValue();
437 }
438
439 if (ctx_.view().rules().enabled(featureTokenEscrow) && !isXRP(amount))
440 {
441 auto const xferRate = transferRate(ctx_.view(), amount);
442 if (xferRate != parityRate)
443 (*slep)[sfTransferRate] = xferRate.value;
444 }
445
446 ctx_.view().insert(slep);
447
448 // Add escrow to sender's owner directory
449 {
450 auto page = ctx_.view().dirInsert(
452 if (!page)
453 return tecDIR_FULL; // LCOV_EXCL_LINE
454 (*slep)[sfOwnerNode] = *page;
455 }
456
457 // If it's not a self-send, add escrow to recipient's owner directory.
458 AccountID const dest = ctx_.tx[sfDestination];
459 if (dest != account_)
460 {
461 auto page =
462 ctx_.view().dirInsert(keylet::ownerDir(dest), escrowKeylet, describeOwnerDir(dest));
463 if (!page)
464 return tecDIR_FULL; // LCOV_EXCL_LINE
465 (*slep)[sfDestinationNode] = *page;
466 }
467
468 // IOU escrow objects are added to the issuer's owner directory to help
469 // track the total locked balance. For MPT, this isn't necessary because the
470 // locked balance is already stored directly in the MPTokenIssuance object.
471 AccountID const issuer = amount.getIssuer();
472 if (!isXRP(amount) && issuer != account_ && issuer != dest && !amount.holds<MPTIssue>())
473 {
474 auto page =
475 ctx_.view().dirInsert(keylet::ownerDir(issuer), escrowKeylet, describeOwnerDir(issuer));
476 if (!page)
477 return tecDIR_FULL; // LCOV_EXCL_LINE
478 (*slep)[sfIssuerNode] = *page;
479 }
480
481 // Deduct owner's balance
482 if (isXRP(amount))
483 {
484 (*sle)[sfBalance] = (*sle)[sfBalance] - amount;
485 }
486 else
487 {
488 if (auto const ret = std::visit(
489 [&]<typename T>(T const&) {
490 return escrowLockApplyHelper<T>(ctx_.view(), issuer, account_, amount, j_);
491 },
492 amount.asset().value());
493 !isTesSuccess(ret))
494 {
495 return ret; // LCOV_EXCL_LINE
496 }
497 }
498
499 // increment owner count
501 ctx_.view().update(sle);
502 return tesSUCCESS;
503}
504
505} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:40
Stream debug() const
Definition Journal.h:301
STTx const & tx
beast::Journal const journal
ApplyView & view()
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:116
virtual void update(std::shared_ptr< SLE > const &sle)=0
Indicate changes to a peeked SLE.
virtual void insert(std::shared_ptr< SLE > const &sle)=0
Insert a new state SLE.
std::optional< std::uint64_t > dirInsert(Keylet const &directory, uint256 const &key, std::function< void(std::shared_ptr< SLE > const &)> const &describe)
Insert an entry to a directory.
Definition ApplyView.h:289
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
static NotTEC preflight(PreflightContext const &ctx)
TER doApply() override
static TER preclaim(PreclaimContext const &ctx)
static TxConsequences makeTxConsequences(PreflightContext const &ctx)
constexpr MPTID const & getMptID() const
Definition MPTIssue.h:26
virtual Rules const & rules() const =0
Returns the tx processing rules.
virtual Fees const & fees() const =0
Returns the fees for the base ledger.
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
virtual LedgerHeader const & header() const =0
Returns information about the ledger.
virtual std::shared_ptr< SLE const > 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:120
std::uint32_t getSeqValue() const
Returns the first non-zero value of (Sequence, TicketSequence).
Definition STTx.cpp:211
AccountID const account_
Definition Transactor.h:116
beast::Journal const j_
Definition Transactor.h:114
ApplyContext & ctx_
Definition Transactor.h:112
Class describing the consequences to the account of applying a transaction if the transaction consume...
Definition applySteps.h:38
T is_same_v
T message(T... args)
Keylet escrow(AccountID const &src, std::uint32_t seq) noexcept
An escrow entry.
Definition Indexes.cpp:351
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:336
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:474
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 mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Definition Indexes.cpp:486
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:165
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
@ fhIGNORE_FREEZE
bool isXRP(AccountID const &c)
Definition AccountID.h:70
NotTEC escrowCreatePreflightHelper< Issue >(PreflightContext const &ctx)
@ tefINTERNAL
Definition TER.h:153
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j, SpendableHandling includeFullBalance=shSIMPLE_BALANCE)
bool isPseudoAccount(std::shared_ptr< SLE const > sleAcct, std::set< SField const * > const &pseudoFieldFilter={})
Returns true if and only if sleAcct is a pseudo-account or specific pseudo-accounts in pseudoFieldFil...
TER escrowCreatePreclaimHelper< MPTIssue >(PreclaimContext const &ctx, AccountID const &account, AccountID const &dest, STAmount const &amount)
bool isFrozen(ReadView const &view, AccountID const &account, MPTIssue const &mptIssue, int depth=0)
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:492
void adjustOwnerCount(ApplyView &view, std::shared_ptr< SLE > const &sle, std::int32_t amount, beast::Journal j)
Adjust the owner count up or down.
TER escrowLockApplyHelper< MPTIssue >(ApplyView &view, AccountID const &issuer, AccountID const &sender, STAmount const &amount, beast::Journal journal)
@ ahIGNORE_AUTH
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:523
static TER escrowLockApplyHelper(ApplyView &view, AccountID const &issuer, AccountID const &sender, STAmount const &amount, beast::Journal journal)
TER canTransfer(ReadView const &view, MPTIssue const &mptIssue, AccountID const &from, AccountID const &to)
Check if the destination account is allowed to receive MPT.
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Returns a function that sets the owner on a directory SLE.
TER escrowCreatePreclaimHelper< Issue >(PreclaimContext const &ctx, AccountID const &account, AccountID const &dest, STAmount const &amount)
static NotTEC escrowCreatePreflightHelper(PreflightContext const &ctx)
@ temBAD_CURRENCY
Definition TER.h:70
@ temBAD_EXPIRATION
Definition TER.h:71
@ temMALFORMED
Definition TER.h:67
@ temDISABLED
Definition TER.h:94
@ temBAD_AMOUNT
Definition TER.h:69
bool isTesSuccess(TER x) noexcept
Definition TER.h:651
static TER escrowCreatePreclaimHelper(PreclaimContext const &ctx, AccountID const &account, AccountID const &dest, STAmount const &amount)
TER rippleLockEscrowMPT(ApplyView &view, AccountID const &uGrantorID, STAmount const &saAmount, beast::Journal j)
@ tecDIR_FULL
Definition TER.h:268
@ tecLOCKED
Definition TER.h:339
@ tecOBJECT_NOT_FOUND
Definition TER.h:307
@ tecINTERNAL
Definition TER.h:291
@ tecFROZEN
Definition TER.h:284
@ tecINSUFFICIENT_FUNDS
Definition TER.h:306
@ tecNO_LINE
Definition TER.h:282
@ tecPRECISION_LOSS
Definition TER.h:344
@ tecINSUFFICIENT_RESERVE
Definition TER.h:288
@ tecNO_PERMISSION
Definition TER.h:286
@ tecDST_TAG_NEEDED
Definition TER.h:290
@ tecNO_ISSUER
Definition TER.h:280
@ tecNO_DST
Definition TER.h:271
@ tecUNFUNDED
Definition TER.h:276
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...
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:582
@ tesSUCCESS
Definition TER.h:225
Rate const parityRate
A transfer rate signifying a 1:1 exchange.
TER requireAuth(ReadView const &view, MPTIssue const &mptIssue, AccountID const &account, AuthType authType=AuthType::Legacy, int depth=0)
Check if the account lacks required authorization for MPT.
TER rippleCredit(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, bool bCheckIssuer, beast::Journal j)
Calls static rippleCreditIOU if saAmount represents Issue.
XRPAmount accountReserve(std::size_t ownerCount) const
Returns the account reserve given the owner count, in drops.
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:19
NetClock::time_point parentCloseTime
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:57
ReadView const & view
Definition Transactor.h:60
beast::Journal const j
Definition Transactor.h:65
State information when preflighting a tx.
Definition Transactor.h:14
beast::Journal const j
Definition Transactor.h:21
T visit(T... args)