xrpld
Loading...
Searching...
No Matches
EscrowCancel.cpp
1#include <xrpl/tx/transactors/escrow/EscrowCancel.h>
2
3#include <xrpl/basics/Log.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/EscrowHelpers.h>
8#include <xrpl/ledger/helpers/MPTokenHelpers.h>
9#include <xrpl/ledger/helpers/RippleStateHelpers.h>
10#include <xrpl/ledger/helpers/TokenHelpers.h>
11#include <xrpl/protocol/AccountID.h>
12#include <xrpl/protocol/Concepts.h>
13#include <xrpl/protocol/Feature.h>
14#include <xrpl/protocol/Indexes.h>
15#include <xrpl/protocol/Issue.h>
16#include <xrpl/protocol/MPTIssue.h>
17#include <xrpl/protocol/Rate.h>
18#include <xrpl/protocol/SField.h>
19#include <xrpl/protocol/STAmount.h>
20#include <xrpl/protocol/STLedgerEntry.h>
21#include <xrpl/protocol/STTx.h>
22#include <xrpl/protocol/SeqProxy.h>
23#include <xrpl/protocol/TER.h>
24#include <xrpl/protocol/XRPAmount.h>
25#include <xrpl/tx/Transactor.h>
26
27#include <variant>
28
29namespace xrpl {
30
36
37template <ValidIssueType T>
38static TER
40 PreclaimContext const& ctx,
41 AccountID const& account,
42 STAmount const& amount);
43
44template <>
47 PreclaimContext const& ctx,
48 AccountID const& account,
49 STAmount const& amount)
50{
51 AccountID const& issuer = amount.getIssuer();
52 // If the issuer is the same as the account, return tecINTERNAL
53 if (issuer == account)
54 return tecINTERNAL; // LCOV_EXCL_LINE
55
56 // If the issuer has requireAuth set, check if the account is authorized
57 if (auto const ter = requireAuth(ctx.view, amount.get<Issue>(), account); !isTesSuccess(ter))
58 return ter;
59
60 return tesSUCCESS;
61}
62
63template <>
66 PreclaimContext const& ctx,
67 AccountID const& account,
68 STAmount const& amount)
69{
70 AccountID const issuer = amount.getIssuer();
71 // If the issuer is the same as the account, return tecINTERNAL
72 if (issuer == account)
73 return tecINTERNAL; // LCOV_EXCL_LINE
74
75 // If the mpt does not exist, return tecOBJECT_NOT_FOUND
76 auto const issuanceKey = keylet::mptokenIssuance(amount.get<MPTIssue>().getMptID());
77 auto const sleIssuance = ctx.view.read(issuanceKey);
78 if (!sleIssuance)
80
81 // If the issuer has requireAuth set, check if the account is
82 // authorized
83 auto const& mptIssue = amount.get<MPTIssue>();
84 if (auto const ter = requireAuth(ctx.view, mptIssue, account, AuthType::WeakAuth);
85 !isTesSuccess(ter))
86 return ter;
87
88 return tesSUCCESS;
89}
90
91TER
93{
94 if (ctx.view.rules().enabled(featureTokenEscrow))
95 {
96 auto const seqProxy = SeqProxy::rawSequence(ctx.tx[sfOfferSequence]);
97 auto const k = keylet::escrow(ctx.tx[sfOwner], seqProxy);
98 auto const slep = ctx.view.read(k);
99 if (!slep)
100 return tecNO_TARGET;
101
102 AccountID const account = (*slep)[sfAccount];
103 STAmount const amount = (*slep)[sfAmount];
104
105 if (!isXRP(amount))
106 {
107 if (auto const ret = std::visit(
108 [&]<typename T>(T const&) {
109 return escrowCancelPreclaimHelper<T>(ctx, account, amount);
110 },
111 amount.asset().value());
112 !isTesSuccess(ret))
113 return ret;
114 }
115 }
116 return tesSUCCESS;
117}
118
119TER
121{
122 auto const seqProxy = SeqProxy::rawSequence(ctx_.tx[sfOfferSequence]);
123 auto const k = keylet::escrow(ctx_.tx[sfOwner], seqProxy);
124 auto const slep = ctx_.view().peek(k);
125 if (!slep)
126 {
127 if (ctx_.view().rules().enabled(featureTokenEscrow))
128 return tecINTERNAL; // LCOV_EXCL_LINE
129
130 return tecNO_TARGET;
131 }
132
133 auto const now = ctx_.view().header().parentCloseTime;
134
135 // No cancel time specified: can't execute at all.
136 if (!(*slep)[~sfCancelAfter])
137 return tecNO_PERMISSION;
138
139 // Too soon: can't execute before the cancel time.
140 if (!after(now, (*slep)[sfCancelAfter]))
141 return tecNO_PERMISSION;
142
143 AccountID const account = (*slep)[sfAccount];
144
145 // Remove escrow from owner directory
146 {
147 auto const page = (*slep)[sfOwnerNode];
148 if (!ctx_.view().dirRemove(keylet::ownerDir(account), page, k.key, true))
149 {
150 // LCOV_EXCL_START
151 JLOG(j_.fatal()) << "Unable to delete Escrow from owner.";
152 return tefBAD_LEDGER;
153 // LCOV_EXCL_STOP
154 }
155 }
156
157 // Remove escrow from recipient's owner directory, if present.
158 if (auto const optPage = (*slep)[~sfDestinationNode]; optPage)
159 {
160 if (!ctx_.view().dirRemove(keylet::ownerDir((*slep)[sfDestination]), *optPage, k.key, true))
161 {
162 // LCOV_EXCL_START
163 JLOG(j_.fatal()) << "Unable to delete Escrow from recipient.";
164 return tefBAD_LEDGER;
165 // LCOV_EXCL_STOP
166 }
167 }
168
169 auto const sle = ctx_.view().peek(keylet::account(account));
170 STAmount const amount = slep->getFieldAmount(sfAmount);
171
172 // Transfer amount back to the owner
173 if (isXRP(amount))
174 {
175 (*sle)[sfBalance] = (*sle)[sfBalance] + amount;
176 }
177 else
178 {
179 if (!ctx_.view().rules().enabled(featureTokenEscrow))
180 return temDISABLED; // LCOV_EXCL_LINE
181
182 auto const issuer = amount.getIssuer();
183 bool const createAsset = account == accountID_;
184 if (auto const ret = std::visit(
185 [&]<typename T>(T const&) {
187 ctx_.getApplyViewContext(),
189 ctx_.view().rules().enabled(fixCleanup3_2_0) ? sle : slep,
191 amount,
192 issuer,
193 account, // sender and receiver are the same
194 account,
195 createAsset,
196 j_);
197 },
198 amount.asset().value());
199 !isTesSuccess(ret))
200 return ret; // LCOV_EXCL_LINE
201
202 // Remove escrow from issuers owner directory, if present.
203 if (auto const optPage = (*slep)[~sfIssuerNode]; optPage)
204 {
205 if (!ctx_.view().dirRemove(keylet::ownerDir(issuer), *optPage, k.key, true))
206 {
207 // LCOV_EXCL_START
208 JLOG(j_.fatal()) << "Unable to delete Escrow from recipient.";
209 return tefBAD_LEDGER;
210 // LCOV_EXCL_STOP
211 }
212 }
213 }
214
215 decreaseOwnerCountForObject(ctx_.view(), sle, slep, 1, ctx_.journal);
216
217 // Remove escrow from ledger
218 ctx_.view().erase(slep);
219
220 return tesSUCCESS;
221}
222
223void
225{
226 // No transaction-specific invariants yet (future work).
227}
228
229bool
231 STTx const&,
232 TER,
233 XRPAmount,
234 ReadView const&,
235 beast::Journal const&)
236{
237 // No transaction-specific invariants yet (future work).
238 return true;
239}
240} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:44
static NotTEC preflight(PreflightContext const &ctx)
static TER preclaim(PreclaimContext const &ctx)
void visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override
Inspect a single ledger entry modified by this transaction.
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.
TER doApply() override
A currency issued by an account.
Definition Issue.h:18
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 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:180
constexpr TIss const & get() const
Asset const & asset() const
Definition STAmount.h:496
AccountID const & getIssuer() const
Definition STAmount.h:516
std::shared_ptr< STLedgerEntry const > const & const_ref
static constexpr SeqProxy rawSequence(std::uint32_t v)
Factory function to return a sequence-based SeqProxy.
Definition SeqProxy.h:62
beast::Journal const j_
Definition Transactor.h:155
AccountID const accountID_
Definition Transactor.h:157
XRPAmount preFeeBalance_
Definition Transactor.h:158
ApplyContext & ctx_
Definition Transactor.h:153
Keylet escrow(AccountID const &src, SeqProxy const &seq) noexcept
An escrow entry.
Definition Indexes.cpp:388
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:373
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:198
Keylet mptokenIssuance(MPTID const &issuanceID) noexcept
Definition Indexes.cpp:537
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
void decreaseOwnerCountForObject(ApplyView &view, SLE::ref accountSle, SLE::ref objectSle, std::uint32_t count, beast::Journal j)
Decrease owner-count fields for an existing ledger object.
bool isXRP(AccountID const &c)
Definition AccountID.h:84
TER escrowCancelPreclaimHelper< MPTIssue >(PreclaimContext const &ctx, AccountID const &account, STAmount const &amount)
TER escrowUnlockApplyHelper(ApplyViewContext ctx, Rate lockedRate, SLE::ref sleDest, XRPAmount xrpBalance, STAmount const &amount, AccountID const &issuer, AccountID const &sender, AccountID const &receiver, bool createAsset, beast::Journal journal)
@ tefBAD_LEDGER
Definition TER.h:162
TER escrowCancelPreclaimHelper< Issue >(PreclaimContext const &ctx, AccountID const &account, STAmount const &amount)
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:607
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition View.cpp:572
Rate const kParityRate
A transfer rate signifying a 1:1 exchange.
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:34
static TER escrowCancelPreclaimHelper(PreclaimContext const &ctx, AccountID const &account, STAmount const &amount)
@ temDISABLED
Definition TER.h:102
bool isTesSuccess(TER x) noexcept
Definition TER.h:676
TERSubset< CanCvtToTER > TER
Definition TER.h:647
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.
@ tecNO_TARGET
Definition TER.h:307
@ tecOBJECT_NOT_FOUND
Definition TER.h:329
@ tecINTERNAL
Definition TER.h:313
@ tecNO_PERMISSION
Definition TER.h:308
@ tesSUCCESS
Definition TER.h:245
uint256 key
Definition Keylet.h:21
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:83
ReadView const & view
Definition Transactor.h:86
State information when preflighting a tx.
Definition Transactor.h:38
T visit(T... args)