1#include <xrpl/tx/transactors/escrow/EscrowCreate.h>
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/helpers/AccountRootHelpers.h>
11#include <xrpl/ledger/helpers/DirectoryHelpers.h>
12#include <xrpl/ledger/helpers/MPTokenHelpers.h>
13#include <xrpl/ledger/helpers/RippleStateHelpers.h>
14#include <xrpl/ledger/helpers/SponsorHelpers.h>
15#include <xrpl/ledger/helpers/TokenHelpers.h>
16#include <xrpl/protocol/AccountID.h>
17#include <xrpl/protocol/Concepts.h>
18#include <xrpl/protocol/Feature.h>
19#include <xrpl/protocol/Indexes.h>
20#include <xrpl/protocol/Issue.h>
21#include <xrpl/protocol/LedgerFormats.h>
22#include <xrpl/protocol/MPTAmount.h>
23#include <xrpl/protocol/MPTIssue.h>
24#include <xrpl/protocol/Protocol.h>
25#include <xrpl/protocol/Rate.h>
26#include <xrpl/protocol/SField.h>
27#include <xrpl/protocol/STAmount.h>
28#include <xrpl/protocol/STLedgerEntry.h>
29#include <xrpl/protocol/STTx.h>
30#include <xrpl/protocol/TER.h>
31#include <xrpl/protocol/UintTypes.h>
32#include <xrpl/protocol/XRPAmount.h>
33#include <xrpl/tx/Transactor.h>
34#include <xrpl/tx/applySteps.h>
81 auto const amount = ctx.
tx[sfAmount];
95template <Val
idIssueType T>
120 auto const amount = ctx.
tx[sfAmount];
138 amount.
asset().value());
149 if (!ctx.
tx[~sfCancelAfter] && !ctx.
tx[~sfFinishAfter])
154 if (ctx.
tx[~sfCancelAfter] && ctx.
tx[~sfFinishAfter] &&
155 ctx.
tx[sfCancelAfter] <= ctx.
tx[sfFinishAfter])
162 if (!ctx.
tx[~sfFinishAfter] && !ctx.
tx[~sfCondition])
165 if (
auto const cb = ctx.
tx[~sfCondition])
174 JLOG(ctx.
j.
debug()) <<
"Malformed condition during escrow creation: " << ec.
message();
182template <Val
idIssueType T>
198 auto const& issue = amount.
get<
Issue>();
201 if (issuer == account)
208 if (!sleIssuer->isFlag(lsfAllowTrustLineLocking))
216 STAmount const balance = (*sleRippleState)[sfBalance];
223 if (balance < beast::kZero && issuer > account)
251 if (spendableAmount < amount)
255 if (!
canAdd(spendableAmount, amount))
271 if (issuer == account)
276 auto const sleIssuance = ctx.
view.
read(issuanceKey);
281 if (!sleIssuance->isFlag(lsfMPTCanEscrow))
286 if (sleIssuance->getAccountID(sfIssuer) != issuer)
332 if (spendableAmount < amount)
362 [&]<
typename T>(T
const&) {
365 amount.
asset().value());
372template <Val
idIssueType T>
391 if (issuer == sender)
411 if (issuer == sender)
414 auto const ter =
lockEscrowMPT(view, sender, amount, journal);
423 auto const closeTime =
ctx_.view().header().parentCloseTime;
425 if (
ctx_.tx[~sfCancelAfter] &&
after(closeTime,
ctx_.tx[sfCancelAfter]))
428 if (
ctx_.tx[~sfFinishAfter] &&
after(closeTime,
ctx_.tx[sfFinishAfter]))
438 auto const balance = sle->getFieldAmount(sfBalance).
xrp();
463 ctx_.view(), sle,
j_, {.ownerCountDelta = getTxReserveSponsorID(ctx_.tx) ? 0 : 1});
464 if (balance -
STAmount(amount).xrp() < sourceReserve)
473 if (sled->isFlag(lsfRequireDestTag) && !
ctx_.tx[~sfDestinationTag])
481 (*slep)[sfAmount] = amount;
483 (*slep)[~sfCondition] =
ctx_.tx[~sfCondition];
484 (*slep)[~sfSourceTag] =
ctx_.tx[~sfSourceTag];
485 (*slep)[sfDestination] =
ctx_.tx[sfDestination];
486 (*slep)[~sfCancelAfter] =
ctx_.tx[~sfCancelAfter];
487 (*slep)[~sfFinishAfter] =
ctx_.tx[~sfFinishAfter];
488 (*slep)[~sfDestinationTag] =
ctx_.tx[~sfDestinationTag];
490 if (
ctx_.view().rules().enabled(fixIncludeKeyletFields))
492 (*slep)[sfSequence] =
ctx_.tx.getSeqProxy().value();
495 if (
ctx_.view().rules().enabled(featureTokenEscrow) && !
isXRP(amount))
499 (*slep)[sfTransferRate] = xferRate.value;
502 ctx_.view().insert(slep);
506 auto page =
ctx_.view().dirInsert(
510 (*slep)[sfOwnerNode] = *page;
521 (*slep)[sfDestinationNode] = *page;
534 (*slep)[sfIssuerNode] = *page;
540 (*sle)[sfBalance] = (*sle)[sfBalance] - amount;
545 [&]<
typename T>(T
const&) {
548 amount.
asset().value());
558 ctx_.view().update(sle);
A generic endpoint for log messages.
Writeable view to a ledger, for applying a transaction.
static bool checkExtraFeatures(PreflightContext const &ctx)
static NotTEC preflight(PreflightContext const &ctx)
void visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override
Inspect a single ledger entry modified by this transaction.
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.
constexpr MPTID const & getMptID() const
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.
constexpr bool holds() const noexcept
constexpr TIss const & get() const
bool native() const noexcept
Asset const & asset() const
AccountID const & getIssuer() const
std::shared_ptr< STLedgerEntry const > const & const_ref
AccountID const accountID_
Class describing the consequences to the account of applying a transaction if the transaction consume...
static std::unique_ptr< Condition > deserialize(Slice s, std::error_code &ec)
Load a condition from its binary form.
Keylet escrow(AccountID const &src, SeqProxy const &seq) noexcept
An escrow entry.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet mptokenIssuance(MPTID const &issuanceID) noexcept
Keylet trustLine(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
bool isXRP(AccountID const &c)
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.
NotTEC escrowCreatePreflightHelper< Issue >(PreflightContext const &ctx)
TER lockEscrowMPT(ApplyView &view, AccountID const &uGrantorID, STAmount const &saAmount, beast::Journal j)
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.
TER escrowCreatePreclaimHelper< MPTIssue >(PreclaimContext const &ctx, AccountID const &account, AccountID const &dest, STAmount const &amount)
void addSponsorToLedgerEntry(SLE::ref sle, SLE::const_ref sponsorSle, SF_ACCOUNT const &field=sfSponsor)
Stamp a reserve sponsor onto a ledger entry using an explicit sponsor SLE.
bool canAdd(STAmount const &amt1, STAmount const &amt2)
Safely checks if two STAmount values can be added without overflow, underflow, or precision loss.
TERSubset< CanCvtToNotTEC > NotTEC
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?
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)
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Returns a function that sets the owner on a directory SLE.
bool isFrozen(ReadView const &view, AccountID const &account, MPTIssue const &mptIssue, std::uint8_t depth=0)
TER escrowCreatePreclaimHelper< Issue >(PreclaimContext const &ctx, AccountID const &account, AccountID const &dest, STAmount const &amount)
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
static NotTEC escrowCreatePreflightHelper(PreflightContext const &ctx)
TER checkReserve(ApplyViewContext ctx, SLE::const_ref accSle, XRPAmount accBalance, SLE::const_ref sponsorSle, Adjustment adj, beast::Journal j, TER insufReserveCode=tecINSUFFICIENT_RESERVE)
Check if an account has sufficient reserve.
bool isTesSuccess(TER x) noexcept
TERSubset< CanCvtToTER > TER
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)
TER escrowLockApplyHelper< Issue >(ApplyView &view, AccountID const &issuer, AccountID const &sender, STAmount const &amount, beast::Journal journal)
NotTEC escrowCreatePreflightHelper< MPTIssue >(PreflightContext const &ctx)
bool isPseudoAccount(SLE::const_pointer sleAcct, std::set< SField const * > const &pseudoFieldFilter={})
Returns true if and only if sleAcct is a pseudo-account or specific pseudo-accounts in pseudoFieldFil...
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
XRPAmount accountReserve(ReadView const &view, SLE::const_ref sle, beast::Journal j, Adjustment adj={})
Returns the account reserve, in drops.
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j, SpendableHandling includeFullBalance=SpendableHandling::SimpleBalance)
A pair of SHAMap key and LedgerEntryType.
State information when determining if a tx is likely to claim a fee.
State information when preflighting a tx.