xrpld
Loading...
Searching...
No Matches
SponsorshipSet.cpp
1#include <xrpl/tx/transactors/sponsor/SponsorshipSet.h>
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/beast/utility/Journal.h>
5#include <xrpl/beast/utility/Zero.h>
6#include <xrpl/beast/utility/instrumentation.h>
7#include <xrpl/core/ServiceRegistry.h>
8#include <xrpl/ledger/ApplyView.h>
9#include <xrpl/ledger/ReadView.h>
10#include <xrpl/ledger/helpers/AccountRootHelpers.h>
11#include <xrpl/ledger/helpers/DirectoryHelpers.h>
12#include <xrpl/ledger/helpers/SponsorHelpers.h>
13#include <xrpl/protocol/AccountID.h>
14#include <xrpl/protocol/Indexes.h>
15#include <xrpl/protocol/Keylet.h>
16#include <xrpl/protocol/LedgerFormats.h>
17#include <xrpl/protocol/SField.h>
18#include <xrpl/protocol/STAmount.h>
19#include <xrpl/protocol/TER.h>
20#include <xrpl/protocol/TxFlags.h>
21#include <xrpl/tx/Transactor.h>
22
23#include <algorithm>
24#include <cstdint>
25#include <limits>
26#include <memory>
27#include <optional>
28
29namespace xrpl {
30
31// Compute the resulting RemainingOwnerCount using signed 64-bit arithmetic to
32// avoid unsigned wraparound. A missing SLE (object creation) or absent field
33// counts as zero. Callers handle the out-of-range results: a negative value is
34// clamped to zero (field absent) and overflow is rejected in preclaim.
35static std::int64_t
37 SLE::const_ref sponsorshipSle,
38 std::optional<std::int32_t> const& remainingOwnerCountDelta)
39{
40 std::uint32_t const currentCount =
41 sponsorshipSle ? (*sponsorshipSle)[~sfRemainingOwnerCount].value_or(0u) : 0u;
42 return static_cast<std::int64_t>(currentCount) + remainingOwnerCountDelta.value_or(0);
43}
44
45static bool
47 SLE::const_ref sponsorshipSle,
48 std::optional<STAmount> const& feeAmountDelta,
49 std::optional<std::int32_t> const& remainingOwnerCountDelta)
50{
51 // sfFeeAmountDelta and sfRemainingOwnerCountDelta must be non-negative when creating a new
52 // Sponsorship object.
53 if (!sponsorshipSle)
54 {
55 if (feeAmountDelta.has_value() && *feeAmountDelta <= beast::kZero)
56 return false;
57
58 if (remainingOwnerCountDelta.has_value() && *remainingOwnerCountDelta <= 0)
59 return false;
60 }
61 // If the transaction omits a field, it keeps whatever the existing object holds,
62 // so fall back to the current SLE value when the tx does not set it.
63 STAmount const currentFee =
64 sponsorshipSle ? (*sponsorshipSle)[~sfFeeAmount].value_or(STAmount{0}) : STAmount{0};
65 STAmount const newFee = currentFee + feeAmountDelta.value_or(STAmount{0});
66
67 std::int64_t const newCount =
68 totalRemainingOwnerCount(sponsorshipSle, remainingOwnerCountDelta);
69
70 return newFee > beast::kZero || newCount > 0;
71}
72
73TxConsequences
75{
76 auto const feeAmount = ctx.tx[~sfFeeAmountDelta];
77 auto const feeAmountDelta = std::max(STAmount{0}, feeAmount.value_or(STAmount{0}));
78 return TxConsequences{ctx.tx, feeAmountDelta.xrp()};
79}
80
83{
84 return tfSponsorshipSetMask;
85}
86
89{
90 if (ctx.tx.isFlag(tfSponsorshipSetRequireSignForFee) &&
91 ctx.tx.isFlag(tfSponsorshipClearRequireSignForFee))
92 return temINVALID_FLAG;
93 if (ctx.tx.isFlag(tfSponsorshipSetRequireSignForReserve) &&
94 ctx.tx.isFlag(tfSponsorshipClearRequireSignForReserve))
95 return temINVALID_FLAG;
96
97 auto const account = ctx.tx.getAccountID(sfAccount);
98 bool const hasSponsor = ctx.tx.isFieldPresent(sfCounterpartySponsor);
99 bool const hasSponsee = ctx.tx.isFieldPresent(sfSponsee);
100
101 // The transaction must specify either Sponsor or Sponsee, but not both.
102 if (hasSponsor == hasSponsee)
103 return temMALFORMED;
104
105 auto const sponsorID = ctx.tx[~sfCounterpartySponsor].value_or(account);
106 auto const sponseeID = ctx.tx[~sfSponsee].value_or(account);
107
108 if (sponsorID == sponseeID)
109 return temMALFORMED;
110
111 if (ctx.tx.isFlag(tfDeleteObject))
112 {
113 // Transactions deleting `Sponsorship` cannot set modification flags.
114 constexpr std::uint32_t kModifyFlags = tfSponsorshipSetRequireSignForFee |
115 tfSponsorshipSetRequireSignForReserve | tfSponsorshipClearRequireSignForFee |
116 tfSponsorshipClearRequireSignForReserve;
117
118 if ((ctx.tx.getFlags() & kModifyFlags) != 0u)
119 return temINVALID_FLAG;
120
121 // Transactions deleting `Sponsorship` cannot include modification fields.
122 if (ctx.tx.isFieldPresent(sfFeeAmountDelta) ||
123 ctx.tx.isFieldPresent(sfRemainingOwnerCountDelta) || ctx.tx.isFieldPresent(sfMaxFee))
124 return temMALFORMED;
125 }
126 else
127 {
128 // Both sponsor and sponsee can delete a Sponsorship object, but only
129 // the sponsor can create or update one.
130 if (account != sponsorID)
131 return temMALFORMED;
132
133 // FeeAmountDelta must be a non-zero XRP amount when present.
134 if (auto const feeAmt = ctx.tx[~sfFeeAmountDelta];
135 feeAmt && (!isXRP(*feeAmt) || *feeAmt == beast::kZero))
136 return temBAD_AMOUNT;
137
138 // MaxFee must be a non-negative XRP amount when present.
139 if (auto const maxFee = ctx.tx[~sfMaxFee];
140 maxFee && (!isXRP(*maxFee) || *maxFee < beast::kZero))
141 return temBAD_AMOUNT;
142
143 // RemainingOwnerCountDelta must be a non-zero integer when present.
144 if (auto const remainingOwnerCountDelta = ctx.tx[~sfRemainingOwnerCountDelta];
145 remainingOwnerCountDelta && *remainingOwnerCountDelta == 0)
146 return temINVALID;
147
148 // nothing specified in the tx
149 if (!ctx.tx.isFieldPresent(sfRemainingOwnerCountDelta) &&
150 !ctx.tx.isFieldPresent(sfFeeAmountDelta) && !ctx.tx.isFieldPresent(sfMaxFee) &&
151 ((ctx.tx.getFlags() & tfUniversalMask) == 0))
152 return temREDUNDANT;
153 }
154
155 return tesSUCCESS;
156}
157
158TER
160{
161 auto const sponsorID = ctx.tx[~sfCounterpartySponsor].value_or(ctx.tx[sfAccount]);
162 auto const sponseeID = ctx.tx[~sfSponsee].value_or(ctx.tx[sfAccount]);
163
164 if (sponseeID == sponsorID)
165 return tecINTERNAL; // LCOV_EXCL_LINE
166
167 auto const sponsorAccSle = ctx.view.read(keylet::account(sponsorID));
168 if (!sponsorAccSle)
169 return tecNO_DST;
170
171 auto const sponseeSle = ctx.view.read(keylet::account(sponseeID));
172 if (!sponseeSle)
173 return tecNO_DST;
174
175 // Pseudo-accounts cannot participate in sponsorship.
176 if (isPseudoAccount(sponsorAccSle) || isPseudoAccount(sponseeSle))
177 return tecPSEUDO_ACCOUNT;
178
179 auto const sponsorshipSle = ctx.view.read(keylet::sponsorship(sponsorID, sponseeID));
180
181 // Deleting a Sponsorship object requires the object to already exist.
182 if (ctx.tx.isFlag(tfDeleteObject) && !sponsorshipSle)
183 return tecNO_ENTRY;
184
185 if (!ctx.tx.isFlag(tfDeleteObject))
186 {
187 // Reject if applying the delta would overflow uint32_t. A negative delta
188 // that underflows is clamped to zero (field absent) rather than erroring.
189 if (totalRemainingOwnerCount(sponsorshipSle, ctx.tx[~sfRemainingOwnerCountDelta]) >
191 return tecLIMIT_EXCEEDED;
192
193 // Reject creating or updating a Sponsorship that would be left with no
194 // budget (neither a positive FeeAmount nor a positive RemainingOwnerCount).
195 // Such an object is unusable yet still consumes the sponsor's reserve.
197 sponsorshipSle, ctx.tx[~sfFeeAmountDelta], ctx.tx[~sfRemainingOwnerCountDelta]))
198 return tecNO_PERMISSION;
199 }
200
201 return tesSUCCESS;
202}
203
204static TER
206{
207 if (!sle)
208 return tecINTERNAL; // LCOV_EXCL_LINE
209
210 auto const sponsorID = (*sle)[sfOwner];
211 auto const sponseeID = (*sle)[sfSponsee];
212
213 // The sponsor owns the Sponsorship object, so deletion releases the
214 // sponsor's owner reserve.
215 auto sponsorAccSle = view.peek(keylet::account(sponsorID));
216 if (!sponsorAccSle)
217 return tecINTERNAL; // LCOV_EXCL_LINE
218
219 if (!view.dirRemove(keylet::ownerDir(sponsorID), (*sle)[sfOwnerNode], sle->key(), false))
220 {
221 // LCOV_EXCL_START
222 JLOG(j.fatal()) << "Unable to delete Sponsorship from sponsor.";
223 return tefBAD_LEDGER;
224 // LCOV_EXCL_STOP
225 }
226 if (!view.dirRemove(keylet::ownerDir(sponseeID), (*sle)[sfSponseeNode], sle->key(), false))
227 {
228 // LCOV_EXCL_START
229 JLOG(j.fatal()) << "Unable to delete Sponsorship from sponsee.";
230 return tefBAD_LEDGER;
231 // LCOV_EXCL_STOP
232 }
233
234 decreaseOwnerCountForObject(view, sponsorAccSle, sle, 1, j);
235
236 // Return any prefunded fee amount to the sponsor before erasing the object.
237 if (sle->isFieldPresent(sfFeeAmount))
238 {
239 (*sponsorAccSle)[sfBalance] += sle->getFieldAmount(sfFeeAmount);
240 view.update(sponsorAccSle);
241 }
242
243 view.erase(sle);
244
245 return tesSUCCESS;
246}
247
248TER
250 Keylet const& sponsorshipKeylet,
251 AccountID const& sponsorID,
252 AccountID const& sponseeID,
253 SLE::ref sponsorAccSle,
254 SLE::ref reserveSponsorAccSle)
255{
256 auto const feeAmountDelta = ctx_.tx[~sfFeeAmountDelta];
257 auto const maxFee = ctx_.tx[~sfMaxFee];
258 auto const remainingOwnerCountDelta = ctx_.tx[~sfRemainingOwnerCountDelta];
259
260 bool const hasPositiveFeeAmount = feeAmountDelta.has_value() && *feeAmountDelta > beast::kZero;
261
262 // Create a new Sponsorship object between the sponsor and sponsee.
263 auto newSle = std::make_shared<SLE>(sponsorshipKeylet);
264 STAmount sponsorBalanceAfterFee = (*sponsorAccSle)[sfBalance];
265 // sfFeeAmountDelta must be positive if the sponsorship object doesn't exist. This is
266 // checked in preclaim.
267 XRPL_ASSERT(
268 !feeAmountDelta.has_value() || *feeAmountDelta > beast::kZero,
269 "xrpl::SponsorshipSet::doApply : new sponsorship has positive fee amount");
270
271 (*newSle)[sfOwner] = sponsorID;
272 (*newSle)[sfSponsee] = sponseeID;
273 if (feeAmountDelta && feeAmountDelta->xrp() > sponsorBalanceAfterFee.xrp())
274 return tecUNFUNDED;
275
276 if (hasPositiveFeeAmount)
277 sponsorBalanceAfterFee -= *feeAmountDelta;
278
279 if (auto const ret = checkReserve(
280 ctx_.getApplyViewContext(),
281 sponsorAccSle,
282 sponsorBalanceAfterFee.xrp(),
283 reserveSponsorAccSle,
284 {.ownerCountDelta = 1},
285 ctx_.journal,
287 !isTesSuccess(ret))
288 {
289 return ret;
290 }
291
292 if (hasPositiveFeeAmount)
293 {
294 // New object: FeeAmount starts absent, so deduct and record the full amount
295 (*newSle)[sfFeeAmount] = *feeAmountDelta;
296 (*sponsorAccSle)[sfBalance] -= *feeAmountDelta;
297 }
298
299 if (maxFee && *maxFee > beast::kZero)
300 (*newSle)[sfMaxFee] = *maxFee;
301 if (remainingOwnerCountDelta && *remainingOwnerCountDelta > 0)
302 (*newSle)[sfRemainingOwnerCount] = *remainingOwnerCountDelta;
303
304 std::uint32_t flags = 0;
305 if (ctx_.tx.isFlag(tfSponsorshipSetRequireSignForFee))
306 flags |= lsfSponsorshipRequireSignForFee;
307
308 if (ctx_.tx.isFlag(tfSponsorshipSetRequireSignForReserve))
309 flags |= lsfSponsorshipRequireSignForReserve;
310
311 (*newSle)[sfFlags] = flags;
312
313 auto const sponsorPage = view().dirInsert(
314 keylet::ownerDir(sponsorID), sponsorshipKeylet, describeOwnerDir(sponsorID));
315 if (!sponsorPage)
316 return tecDIR_FULL; // LCOV_EXCL_LINE
317 (*newSle)[sfOwnerNode] = *sponsorPage;
318
319 auto const sponseePage = view().dirInsert(
320 keylet::ownerDir(sponseeID), sponsorshipKeylet, describeOwnerDir(sponseeID));
321 if (!sponseePage)
322 return tecDIR_FULL; // LCOV_EXCL_LINE
323 (*newSle)[sfSponseeNode] = *sponseePage;
324
325 // NOLINTNEXTLINE(readability-suspicious-call-argument)
326 increaseOwnerCount(view(), sponsorAccSle, reserveSponsorAccSle, 1, ctx_.journal);
327 addSponsorToLedgerEntry(newSle, reserveSponsorAccSle);
328
329 ctx_.view().insert(newSle);
330 return tesSUCCESS;
331}
332
333TER
335{
336 auto const sponsorID = ctx_.tx[~sfCounterpartySponsor].value_or(accountID_);
337 auto const sponseeID = ctx_.tx[~sfSponsee].value_or(accountID_);
338
339 if (sponseeID == sponsorID)
340 return tecINTERNAL; // LCOV_EXCL_LINE
341
342 auto const sponsorAccSle = ctx_.view().peek(keylet::account(sponsorID));
343 if (!sponsorAccSle)
344 return tecINTERNAL; // LCOV_EXCL_LINE
345
346 if (!ctx_.view().exists(keylet::account(sponseeID)))
347 return tecINTERNAL; // LCOV_EXCL_LINE
348
349 auto const sponsorshipKeylet = keylet::sponsorship(sponsorID, sponseeID);
350 auto const sponsorshipSle = ctx_.view().peek(sponsorshipKeylet);
351
352 if (ctx_.tx.isFlag(tfDeleteObject))
353 {
354 if (!sponsorshipSle)
355 return tecINTERNAL; // LCOV_EXCL_LINE
356
357 return deleteSponsorship(ctx_.view(), sponsorshipSle, ctx_.journal);
358 }
359
360 auto const feeAmountDelta = ctx_.tx[~sfFeeAmountDelta];
361 auto const maxFee = ctx_.tx[~sfMaxFee];
362 auto const remainingOwnerCountDelta = ctx_.tx[~sfRemainingOwnerCountDelta];
363
364 auto reserveSponsorAccSle = getTxReserveSponsor(ctx_.getApplyViewContext());
365 if (!reserveSponsorAccSle)
366 return reserveSponsorAccSle.error(); // LCOV_EXCL_LINE
367
368 if (!sponsorshipSle)
369 {
370 return createSponsorship(
371 sponsorshipKeylet, sponsorID, sponseeID, sponsorAccSle, *reserveSponsorAccSle);
372 }
373
374 // Update the existing Sponsorship object.
375 if (feeAmountDelta)
376 {
377 auto actualDelta = feeAmountDelta.value();
378 auto const currentFee = (*sponsorshipSle)[~sfFeeAmount].valueOr(XRPAmount{0});
379
380 // Clamp negative delta to avoid underflow.
381 if (actualDelta < beast::kZero && -actualDelta > currentFee)
382 actualDelta = -currentFee;
383 // Reject if the sponsor cannot afford the (positive) delta.
384 if (actualDelta > beast::kZero && actualDelta > (*sponsorAccSle)[sfBalance])
385 return tecUNFUNDED;
386
387 // Move the FeeAmount delta between the sponsor balance and Sponsorship
388 // object.
389 (*sponsorAccSle)[sfBalance] -= actualDelta;
390
391 if (auto const ret = checkReserve(
392 ctx_.getApplyViewContext(),
393 sponsorAccSle,
394 (*sponsorAccSle)[sfBalance]->xrp(),
395 *reserveSponsorAccSle,
396 {},
397 ctx_.journal,
399 !isTesSuccess(ret))
400 {
401 return ret;
402 }
403
404 STAmount const newFee = currentFee + actualDelta;
405 // checked in preclaim
406 XRPL_ASSERT(
407 newFee >= beast::kZero, "xrpl::SponsorshipSet::doApply : new fee is non-negative");
408 if (newFee == beast::kZero)
409 {
410 sponsorshipSle->makeFieldAbsent(sfFeeAmount);
411 }
412 else
413 {
414 (*sponsorshipSle)[sfFeeAmount] = newFee;
415 }
416 ctx_.view().update(sponsorAccSle);
417 }
418
419 if (maxFee)
420 {
421 if (*maxFee == beast::kZero)
422 {
423 (*sponsorshipSle).makeFieldAbsent(sfMaxFee);
424 }
425 else
426 {
427 (*sponsorshipSle)[sfMaxFee] = *maxFee;
428 }
429 }
430
431 if (remainingOwnerCountDelta)
432 {
433 std::int64_t const newCount =
434 totalRemainingOwnerCount(sponsorshipSle, remainingOwnerCountDelta);
435 // Overflow is rejected in preclaim; underflow clamps to zero (field absent).
436 XRPL_ASSERT(
437 newCount <= static_cast<std::int64_t>(std::numeric_limits<std::uint32_t>::max()),
438 "xrpl::SponsorshipSet::doApply : RemainingOwnerCount does not overflow");
439 if (newCount <= 0)
440 {
441 sponsorshipSle->makeFieldAbsent(sfRemainingOwnerCount);
442 }
443 else
444 {
445 sponsorshipSle->at(sfRemainingOwnerCount) = static_cast<std::uint32_t>(newCount);
446 }
447 }
448
449 // Apply requested flag changes.
450 auto flags = sponsorshipSle->getFieldU32(sfFlags);
451 if (ctx_.tx.isFlag(tfSponsorshipSetRequireSignForFee))
452 flags |= lsfSponsorshipRequireSignForFee;
453
454 if (ctx_.tx.isFlag(tfSponsorshipClearRequireSignForFee))
455 flags &= ~lsfSponsorshipRequireSignForFee;
456
457 if (ctx_.tx.isFlag(tfSponsorshipSetRequireSignForReserve))
458 flags |= lsfSponsorshipRequireSignForReserve;
459
460 if (ctx_.tx.isFlag(tfSponsorshipClearRequireSignForReserve))
461 flags &= ~lsfSponsorshipRequireSignForReserve;
462
463 if (flags != (*sponsorshipSle)[sfFlags])
464 (*sponsorshipSle)[sfFlags] = flags;
465
466 view().update(sponsorshipSle);
467
468 return tesSUCCESS;
469}
470
471void
475
476bool
478 STTx const&,
479 TER,
480 XRPAmount,
481 ReadView const&,
482 beast::Journal const&)
483{
484 return true;
485}
486
487} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:44
Stream fatal() const
Definition Journal.h:368
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:134
virtual SLE::pointer peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
bool dirRemove(Keylet const &directory, std::uint64_t page, uint256 const &key, bool keepRoot)
Remove an entry from a directory.
virtual void erase(SLE::ref sle)=0
Remove a peeked SLE.
std::optional< std::uint64_t > dirInsert(Keylet const &directory, uint256 const &key, std::function< void(SLE::ref)> const &describe)
Insert an entry to a directory.
Definition ApplyView.h:366
virtual void update(SLE::ref sle)=0
Indicate changes to a peeked SLE.
A view into a ledger.
Definition ReadView.h:41
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
XRPAmount xrp() const
Definition STAmount.cpp:271
std::shared_ptr< STLedgerEntry > const & ref
std::shared_ptr< STLedgerEntry const > const & const_ref
bool isFlag(std::uint32_t) const
Definition STObject.cpp:511
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:464
AccountID getAccountID(SField const &field) const
Definition STObject.cpp:643
std::uint32_t getFlags() const
Definition STObject.cpp:517
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.
void visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override
Inspect a single ledger entry modified by this transaction.
TER createSponsorship(Keylet const &sponsorshipKeylet, AccountID const &sponsorID, AccountID const &sponseeID, SLE::ref sponsorAccSle, SLE::ref reserveSponsorAccSle)
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
static TER preclaim(PreclaimContext const &ctx)
static TxConsequences makeTxConsequences(PreflightContext const &ctx)
static NotTEC preflight(PreflightContext const &ctx)
ApplyView & view()
Definition Transactor.h:175
AccountID const accountID_
Definition Transactor.h:157
ApplyContext & ctx_
Definition Transactor.h:153
Class describing the consequences to the account of applying a transaction if the transaction consume...
Definition applySteps.h:52
T make_shared(T... args)
T max(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:373
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:198
Keylet sponsorship(AccountID const &sponsor, AccountID const &sponsee) noexcept
A Sponsorship.
Definition Indexes.cpp:332
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
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.
static bool hasSponsorshipBudget(SLE::const_ref sponsorshipSle, std::optional< STAmount > const &feeAmountDelta, std::optional< std::int32_t > const &remainingOwnerCountDelta)
@ tefBAD_LEDGER
Definition TER.h:162
static std::int64_t totalRemainingOwnerCount(SLE::const_ref sponsorshipSle, std::optional< std::int32_t > const &remainingOwnerCountDelta)
std::expected< SLE::pointer, TER > getTxReserveSponsor(ApplyViewContext ctx)
Return a mutable SLE for the transaction's reserve sponsor account.
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.
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:607
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Returns a function that sets the owner on a directory SLE.
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:34
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.
@ temINVALID
Definition TER.h:98
@ temINVALID_FLAG
Definition TER.h:99
@ temMALFORMED
Definition TER.h:75
@ temBAD_AMOUNT
Definition TER.h:77
@ temREDUNDANT
Definition TER.h:100
bool isTesSuccess(TER x) noexcept
Definition TER.h:676
TERSubset< CanCvtToTER > TER
Definition TER.h:647
@ tecDIR_FULL
Definition TER.h:290
@ tecPSEUDO_ACCOUNT
Definition TER.h:365
@ tecNO_ENTRY
Definition TER.h:309
@ tecINTERNAL
Definition TER.h:313
@ tecLIMIT_EXCEEDED
Definition TER.h:364
@ tecNO_PERMISSION
Definition TER.h:308
@ tecNO_DST
Definition TER.h:293
@ tecUNFUNDED
Definition TER.h:298
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...
static TER deleteSponsorship(ApplyView &view, SLE::ref sle, beast::Journal j)
constexpr FlagValue tfUniversalMask
Definition TxFlags.h:46
@ tesSUCCESS
Definition TER.h:245
T has_value(T... args)
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:83
ReadView const & view
Definition Transactor.h:86
State information when preflighting a tx.
Definition Transactor.h:38
T value_or(T... args)