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/TER.h>
23#include <xrpl/protocol/XRPAmount.h>
24#include <xrpl/tx/Transactor.h>
25
26#include <variant>
27
28namespace xrpl {
29
35
36template <ValidIssueType T>
37static TER
39 PreclaimContext const& ctx,
40 AccountID const& account,
41 STAmount const& amount);
42
43template <>
46 PreclaimContext const& ctx,
47 AccountID const& account,
48 STAmount const& amount)
49{
50 AccountID const& issuer = amount.getIssuer();
51 // If the issuer is the same as the account, return tecINTERNAL
52 if (issuer == account)
53 return tecINTERNAL; // LCOV_EXCL_LINE
54
55 // If the issuer has requireAuth set, check if the account is authorized
56 if (auto const ter = requireAuth(ctx.view, amount.get<Issue>(), account); !isTesSuccess(ter))
57 return ter;
58
59 return tesSUCCESS;
60}
61
62template <>
65 PreclaimContext const& ctx,
66 AccountID const& account,
67 STAmount const& amount)
68{
69 AccountID const issuer = amount.getIssuer();
70 // If the issuer is the same as the account, return tecINTERNAL
71 if (issuer == account)
72 return tecINTERNAL; // LCOV_EXCL_LINE
73
74 // If the mpt does not exist, return tecOBJECT_NOT_FOUND
75 auto const issuanceKey = keylet::mptokenIssuance(amount.get<MPTIssue>().getMptID());
76 auto const sleIssuance = ctx.view.read(issuanceKey);
77 if (!sleIssuance)
79
80 // If the issuer has requireAuth set, check if the account is
81 // authorized
82 auto const& mptIssue = amount.get<MPTIssue>();
83 if (auto const ter = requireAuth(ctx.view, mptIssue, account, AuthType::WeakAuth);
84 !isTesSuccess(ter))
85 return ter;
86
87 return tesSUCCESS;
88}
89
90TER
92{
93 if (ctx.view.rules().enabled(featureTokenEscrow))
94 {
95 auto const k = keylet::escrow(ctx.tx[sfOwner], ctx.tx[sfOfferSequence]);
96 auto const slep = ctx.view.read(k);
97 if (!slep)
98 return tecNO_TARGET;
99
100 AccountID const account = (*slep)[sfAccount];
101 STAmount const amount = (*slep)[sfAmount];
102
103 if (!isXRP(amount))
104 {
105 if (auto const ret = std::visit(
106 [&]<typename T>(T const&) {
107 return escrowCancelPreclaimHelper<T>(ctx, account, amount);
108 },
109 amount.asset().value());
110 !isTesSuccess(ret))
111 return ret;
112 }
113 }
114 return tesSUCCESS;
115}
116
117TER
119{
120 auto const k = keylet::escrow(ctx_.tx[sfOwner], ctx_.tx[sfOfferSequence]);
121 auto const slep = ctx_.view().peek(k);
122 if (!slep)
123 {
124 if (ctx_.view().rules().enabled(featureTokenEscrow))
125 return tecINTERNAL; // LCOV_EXCL_LINE
126
127 return tecNO_TARGET;
128 }
129
130 auto const now = ctx_.view().header().parentCloseTime;
131
132 // No cancel time specified: can't execute at all.
133 if (!(*slep)[~sfCancelAfter])
134 return tecNO_PERMISSION;
135
136 // Too soon: can't execute before the cancel time.
137 if (!after(now, (*slep)[sfCancelAfter]))
138 return tecNO_PERMISSION;
139
140 AccountID const account = (*slep)[sfAccount];
141
142 // Remove escrow from owner directory
143 {
144 auto const page = (*slep)[sfOwnerNode];
145 if (!ctx_.view().dirRemove(keylet::ownerDir(account), page, k.key, true))
146 {
147 // LCOV_EXCL_START
148 JLOG(j_.fatal()) << "Unable to delete Escrow from owner.";
149 return tefBAD_LEDGER;
150 // LCOV_EXCL_STOP
151 }
152 }
153
154 // Remove escrow from recipient's owner directory, if present.
155 if (auto const optPage = (*slep)[~sfDestinationNode]; optPage)
156 {
157 if (!ctx_.view().dirRemove(keylet::ownerDir((*slep)[sfDestination]), *optPage, k.key, true))
158 {
159 // LCOV_EXCL_START
160 JLOG(j_.fatal()) << "Unable to delete Escrow from recipient.";
161 return tefBAD_LEDGER;
162 // LCOV_EXCL_STOP
163 }
164 }
165
166 auto const sle = ctx_.view().peek(keylet::account(account));
167 STAmount const amount = slep->getFieldAmount(sfAmount);
168
169 // Transfer amount back to the owner
170 if (isXRP(amount))
171 {
172 (*sle)[sfBalance] = (*sle)[sfBalance] + amount;
173 }
174 else
175 {
176 if (!ctx_.view().rules().enabled(featureTokenEscrow))
177 return temDISABLED; // LCOV_EXCL_LINE
178
179 auto const issuer = amount.getIssuer();
180 bool const createAsset = account == accountID_;
181 if (auto const ret = std::visit(
182 [&]<typename T>(T const&) {
184 ctx_.view(),
186 ctx_.view().rules().enabled(fixCleanup3_2_0) ? sle : slep,
188 amount,
189 issuer,
190 account, // sender and receiver are the same
191 account,
192 createAsset,
193 j_);
194 },
195 amount.asset().value());
196 !isTesSuccess(ret))
197 return ret; // LCOV_EXCL_LINE
198
199 // Remove escrow from issuers owner directory, if present.
200 if (auto const optPage = (*slep)[~sfIssuerNode]; optPage)
201 {
202 if (!ctx_.view().dirRemove(keylet::ownerDir(issuer), *optPage, k.key, true))
203 {
204 // LCOV_EXCL_START
205 JLOG(j_.fatal()) << "Unable to delete Escrow from recipient.";
206 return tefBAD_LEDGER;
207 // LCOV_EXCL_STOP
208 }
209 }
210 }
211
212 adjustOwnerCount(ctx_.view(), sle, -1, ctx_.journal);
213 ctx_.view().update(sle);
214
215 // Remove escrow from ledger
216 ctx_.view().erase(slep);
217
218 return tesSUCCESS;
219}
220
221void
223{
224 // No transaction-specific invariants yet (future work).
225}
226
227bool
229 STTx const&,
230 TER,
231 XRPAmount,
232 ReadView const&,
233 beast::Journal const&)
234{
235 // No transaction-specific invariants yet (future work).
236 return true;
237}
238} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:38
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:13
constexpr MPTID const & getMptID() const
Definition MPTIssue.h:33
A view into a ledger.
Definition ReadView.h:31
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:171
constexpr TIss const & get() const
Asset const & asset() const
Definition STAmount.h:478
AccountID const & getIssuer() const
Definition STAmount.h:498
std::shared_ptr< STLedgerEntry const > const & const_ref
beast::Journal const j_
Definition Transactor.h:118
AccountID const accountID_
Definition Transactor.h:120
XRPAmount preFeeBalance_
Definition Transactor.h:121
ApplyContext & ctx_
Definition Transactor.h:116
Keylet mptokenIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:521
Keylet escrow(AccountID const &src, std::uint32_t seq) noexcept
An escrow entry.
Definition Indexes.cpp:372
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:357
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:186
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
TER escrowUnlockApplyHelper(ApplyView &view, Rate lockedRate, SLE::ref sleDest, STAmount const &xrpBalance, STAmount const &amount, AccountID const &issuer, AccountID const &sender, AccountID const &receiver, bool createAsset, beast::Journal journal)
bool isXRP(AccountID const &c)
Definition AccountID.h:70
TER escrowCancelPreclaimHelper< MPTIssue >(PreclaimContext const &ctx, AccountID const &account, STAmount const &amount)
@ tefBAD_LEDGER
Definition TER.h:160
TER escrowCancelPreclaimHelper< Issue >(PreclaimContext const &ctx, AccountID const &account, STAmount const &amount)
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:594
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition View.cpp:554
Rate const kParityRate
A transfer rate signifying a 1:1 exchange.
void adjustOwnerCount(ApplyView &view, SLE::ref sle, std::int32_t amount, beast::Journal j)
Adjust the owner count up or down.
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:28
static TER escrowCancelPreclaimHelper(PreclaimContext const &ctx, AccountID const &account, STAmount const &amount)
@ temDISABLED
Definition TER.h:100
bool isTesSuccess(TER x) noexcept
Definition TER.h:663
TERSubset< CanCvtToTER > TER
Definition TER.h:634
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:302
@ tecOBJECT_NOT_FOUND
Definition TER.h:324
@ tecINTERNAL
Definition TER.h:308
@ tecNO_PERMISSION
Definition TER.h:303
@ tesSUCCESS
Definition TER.h:240
uint256 key
Definition Keylet.h:20
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:61
ReadView const & view
Definition Transactor.h:64
State information when preflighting a tx.
Definition Transactor.h:18
T visit(T... args)