rippled
Loading...
Searching...
No Matches
AMMUtils.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2023 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpld/app/misc/AMMHelpers.h>
21#include <xrpld/app/misc/AMMUtils.h>
22#include <xrpld/ledger/Sandbox.h>
23
24#include <xrpl/basics/Log.h>
25#include <xrpl/protocol/AMMCore.h>
26#include <xrpl/protocol/STObject.h>
27
28namespace ripple {
29
32 ReadView const& view,
33 AccountID const& ammAccountID,
34 Issue const& issue1,
35 Issue const& issue2,
36 FreezeHandling freezeHandling,
37 beast::Journal const j)
38{
39 auto const assetInBalance =
40 accountHolds(view, ammAccountID, issue1, freezeHandling, j);
41 auto const assetOutBalance =
42 accountHolds(view, ammAccountID, issue2, freezeHandling, j);
43 return std::make_pair(assetInBalance, assetOutBalance);
44}
45
46Expected<std::tuple<STAmount, STAmount, STAmount>, TER>
48 ReadView const& view,
49 SLE const& ammSle,
50 std::optional<Issue> const& optIssue1,
51 std::optional<Issue> const& optIssue2,
52 FreezeHandling freezeHandling,
53 beast::Journal const j)
54{
55 auto const issues = [&]() -> std::optional<std::pair<Issue, Issue>> {
56 auto const issue1 = ammSle[sfAsset].get<Issue>();
57 auto const issue2 = ammSle[sfAsset2].get<Issue>();
58 if (optIssue1 && optIssue2)
59 {
61 *optIssue1,
62 *optIssue2,
63 std::make_optional(std::make_pair(issue1, issue2))))
64 {
65 // This error can only be hit if the AMM is corrupted
66 // LCOV_EXCL_START
67 JLOG(j.debug()) << "ammHolds: Invalid optIssue1 or optIssue2 "
68 << *optIssue1 << " " << *optIssue2;
69 return std::nullopt;
70 // LCOV_EXCL_STOP
71 }
72 return std::make_optional(std::make_pair(*optIssue1, *optIssue2));
73 }
74 auto const singleIssue =
75 [&issue1, &issue2, &j](
76 Issue checkIssue,
77 char const* label) -> std::optional<std::pair<Issue, Issue>> {
78 if (checkIssue == issue1)
79 return std::make_optional(std::make_pair(issue1, issue2));
80 else if (checkIssue == issue2)
81 return std::make_optional(std::make_pair(issue2, issue1));
82 // Unreachable unless AMM corrupted.
83 // LCOV_EXCL_START
84 JLOG(j.debug())
85 << "ammHolds: Invalid " << label << " " << checkIssue;
86 return std::nullopt;
87 // LCOV_EXCL_STOP
88 };
89 if (optIssue1)
90 {
91 return singleIssue(*optIssue1, "optIssue1");
92 }
93 else if (optIssue2)
94 {
95 // Cannot have Amount2 without Amount.
96 return singleIssue(*optIssue2, "optIssue2"); // LCOV_EXCL_LINE
97 }
98 return std::make_optional(std::make_pair(issue1, issue2));
99 }();
100 if (!issues)
102 auto const [asset1, asset2] = ammPoolHolds(
103 view,
104 ammSle.getAccountID(sfAccount),
105 issues->first,
106 issues->second,
107 freezeHandling,
108 j);
109 return std::make_tuple(asset1, asset2, ammSle[sfLPTokenBalance]);
110}
111
112STAmount
114 ReadView const& view,
115 Currency const& cur1,
116 Currency const& cur2,
117 AccountID const& ammAccount,
118 AccountID const& lpAccount,
119 beast::Journal const j)
120{
121 // This function looks similar to `accountHolds`. However, it only checks if
122 // a LPToken holder has enough balance. On the other hand, `accountHolds`
123 // checks if the underlying assets of LPToken are frozen with the
124 // fixFrozenLPTokenTransfer amendment
125
126 auto const currency = ammLPTCurrency(cur1, cur2);
127 STAmount amount;
128
129 auto const sle = view.read(keylet::line(lpAccount, ammAccount, currency));
130 if (!sle)
131 {
132 amount.clear(Issue{currency, ammAccount});
133 JLOG(j.trace()) << "ammLPHolds: no SLE "
134 << " lpAccount=" << to_string(lpAccount)
135 << " amount=" << amount.getFullText();
136 }
137 else if (isFrozen(view, lpAccount, currency, ammAccount))
138 {
139 amount.clear(Issue{currency, ammAccount});
140 JLOG(j.trace()) << "ammLPHolds: frozen currency "
141 << " lpAccount=" << to_string(lpAccount)
142 << " amount=" << amount.getFullText();
143 }
144 else
145 {
146 amount = sle->getFieldAmount(sfBalance);
147 if (lpAccount > ammAccount)
148 {
149 // Put balance in account terms.
150 amount.negate();
151 }
152 amount.setIssuer(ammAccount);
153
154 JLOG(j.trace()) << "ammLPHolds:"
155 << " lpAccount=" << to_string(lpAccount)
156 << " amount=" << amount.getFullText();
157 }
158
159 return view.balanceHook(lpAccount, ammAccount, amount);
160}
161
162STAmount
164 ReadView const& view,
165 SLE const& ammSle,
166 AccountID const& lpAccount,
167 beast::Journal const j)
168{
169 return ammLPHolds(
170 view,
171 ammSle[sfAsset].get<Issue>().currency,
172 ammSle[sfAsset2].get<Issue>().currency,
173 ammSle[sfAccount],
174 lpAccount,
175 j);
176}
177
179getTradingFee(ReadView const& view, SLE const& ammSle, AccountID const& account)
180{
181 using namespace std::chrono;
182 XRPL_ASSERT(
183 !view.rules().enabled(fixInnerObjTemplate) ||
184 ammSle.isFieldPresent(sfAuctionSlot),
185 "ripple::getTradingFee : auction present");
186 if (ammSle.isFieldPresent(sfAuctionSlot))
187 {
188 auto const& auctionSlot =
189 static_cast<STObject const&>(ammSle.peekAtField(sfAuctionSlot));
190 // Not expired
191 if (auto const expiration = auctionSlot[~sfExpiration];
192 duration_cast<seconds>(
194 .count() < expiration)
195 {
196 if (auctionSlot[~sfAccount] == account)
197 return auctionSlot[sfDiscountedFee];
198 if (auctionSlot.isFieldPresent(sfAuthAccounts))
199 {
200 for (auto const& acct :
201 auctionSlot.getFieldArray(sfAuthAccounts))
202 if (acct[~sfAccount] == account)
203 return auctionSlot[sfDiscountedFee];
204 }
205 }
206 }
207 return ammSle[sfTradingFee];
208}
209
210STAmount
212 ReadView const& view,
213 AccountID const& ammAccountID,
214 Issue const& issue)
215{
216 if (isXRP(issue))
217 {
218 if (auto const sle = view.read(keylet::account(ammAccountID)))
219 return (*sle)[sfBalance];
220 }
221 else if (auto const sle = view.read(
222 keylet::line(ammAccountID, issue.account, issue.currency));
223 sle &&
224 !isFrozen(view, ammAccountID, issue.currency, issue.account))
225 {
226 auto amount = (*sle)[sfBalance];
227 if (ammAccountID > issue.account)
228 amount.negate();
229 amount.setIssuer(issue.account);
230 return amount;
231 }
232
233 return STAmount{issue};
234}
235
236static TER
238 Sandbox& sb,
239 AccountID const& ammAccountID,
240 std::uint16_t maxTrustlinesToDelete,
242{
244 sb,
245 keylet::ownerDir(ammAccountID),
246 [&](LedgerEntryType nodeType,
247 uint256 const&,
249 // Skip AMM
250 if (nodeType == LedgerEntryType::ltAMM)
251 return {tesSUCCESS, SkipEntry::Yes};
252 // Should only have the trustlines
253 if (nodeType != LedgerEntryType::ltRIPPLE_STATE)
254 {
255 // LCOV_EXCL_START
256 JLOG(j.error())
257 << "deleteAMMTrustLines: deleting non-trustline "
258 << nodeType;
259 return {tecINTERNAL, SkipEntry::No};
260 // LCOV_EXCL_STOP
261 }
262
263 // Trustlines must have zero balance
264 if (sleItem->getFieldAmount(sfBalance) != beast::zero)
265 {
266 // LCOV_EXCL_START
267 JLOG(j.error())
268 << "deleteAMMTrustLines: deleting trustline with "
269 "non-zero balance.";
270 return {tecINTERNAL, SkipEntry::No};
271 // LCOV_EXCL_STOP
272 }
273
274 return {
275 deleteAMMTrustLine(sb, sleItem, ammAccountID, j),
277 },
278 j,
279 maxTrustlinesToDelete);
280}
281
282TER
284 Sandbox& sb,
285 Issue const& asset,
286 Issue const& asset2,
288{
289 auto ammSle = sb.peek(keylet::amm(asset, asset2));
290 if (!ammSle)
291 {
292 // LCOV_EXCL_START
293 JLOG(j.error()) << "deleteAMMAccount: AMM object does not exist "
294 << asset << " " << asset2;
295 return tecINTERNAL;
296 // LCOV_EXCL_STOP
297 }
298
299 auto const ammAccountID = (*ammSle)[sfAccount];
300 auto sleAMMRoot = sb.peek(keylet::account(ammAccountID));
301 if (!sleAMMRoot)
302 {
303 // LCOV_EXCL_START
304 JLOG(j.error()) << "deleteAMMAccount: AMM account does not exist "
305 << to_string(ammAccountID);
306 return tecINTERNAL;
307 // LCOV_EXCL_STOP
308 }
309
310 if (auto const ter =
312 ter != tesSUCCESS)
313 return ter;
314
315 auto const ownerDirKeylet = keylet::ownerDir(ammAccountID);
316 if (!sb.dirRemove(
317 ownerDirKeylet, (*ammSle)[sfOwnerNode], ammSle->key(), false))
318 {
319 // LCOV_EXCL_START
320 JLOG(j.error()) << "deleteAMMAccount: failed to remove dir link";
321 return tecINTERNAL;
322 // LCOV_EXCL_STOP
323 }
324 if (sb.exists(ownerDirKeylet) && !sb.emptyDirDelete(ownerDirKeylet))
325 {
326 // LCOV_EXCL_START
327 JLOG(j.error()) << "deleteAMMAccount: cannot delete root dir node of "
328 << toBase58(ammAccountID);
329 return tecINTERNAL;
330 // LCOV_EXCL_STOP
331 }
332
333 sb.erase(ammSle);
334 sb.erase(sleAMMRoot);
335
336 return tesSUCCESS;
337}
338
339void
341 ApplyView& view,
342 std::shared_ptr<SLE>& ammSle,
343 AccountID const& account,
344 Issue const& lptIssue,
345 std::uint16_t tfee)
346{
347 auto const& rules = view.rules();
348 // AMM creator gets the voting slot.
349 STArray voteSlots;
350 STObject voteEntry = STObject::makeInnerObject(sfVoteEntry);
351 if (tfee != 0)
352 voteEntry.setFieldU16(sfTradingFee, tfee);
353 voteEntry.setFieldU32(sfVoteWeight, VOTE_WEIGHT_SCALE_FACTOR);
354 voteEntry.setAccountID(sfAccount, account);
355 voteSlots.push_back(voteEntry);
356 ammSle->setFieldArray(sfVoteSlots, voteSlots);
357 // AMM creator gets the auction slot for free.
358 // AuctionSlot is created on AMMCreate and updated on AMMDeposit
359 // when AMM is in an empty state
360 if (rules.enabled(fixInnerObjTemplate) &&
361 !ammSle->isFieldPresent(sfAuctionSlot))
362 {
363 STObject auctionSlot = STObject::makeInnerObject(sfAuctionSlot);
364 ammSle->set(std::move(auctionSlot));
365 }
366 STObject& auctionSlot = ammSle->peekFieldObject(sfAuctionSlot);
367 auctionSlot.setAccountID(sfAccount, account);
368 // current + sec in 24h
369 auto const expiration = std::chrono::duration_cast<std::chrono::seconds>(
371 .count() +
373 auctionSlot.setFieldU32(sfExpiration, expiration);
374 auctionSlot.setFieldAmount(sfPrice, STAmount{lptIssue, 0});
375 // Set the fee
376 if (tfee != 0)
377 ammSle->setFieldU16(sfTradingFee, tfee);
378 else if (ammSle->isFieldPresent(sfTradingFee))
379 ammSle->makeFieldAbsent(sfTradingFee); // LCOV_EXCL_LINE
380 if (auto const dfee = tfee / AUCTION_SLOT_DISCOUNTED_FEE_FRACTION)
381 auctionSlot.setFieldU16(sfDiscountedFee, dfee);
382 else if (auctionSlot.isFieldPresent(sfDiscountedFee))
383 auctionSlot.makeFieldAbsent(sfDiscountedFee); // LCOV_EXCL_LINE
384}
385
386Expected<bool, TER>
388 ReadView const& view,
389 Issue const& ammIssue,
390 AccountID const& lpAccount)
391{
392 // Liquidity Provider (LP) must have one LPToken trustline
393 std::uint8_t nLPTokenTrustLines = 0;
394 // There are at most two IOU trustlines. One or both could be to the LP
395 // if LP is the issuer, or a different account if LP is not an issuer.
396 // For instance, if AMM has two tokens USD and EUR and LP is not the issuer
397 // of the tokens then the trustlines are between AMM account and the issuer.
398 std::uint8_t nIOUTrustLines = 0;
399 // There is only one AMM object
400 bool hasAMM = false;
401 // AMM LP has at most three trustlines and only one AMM object must exist.
402 // If there are more than five objects then it's either an error or
403 // there are more than one LP. Ten pages should be sufficient to include
404 // five objects.
405 std::uint8_t limit = 10;
406 auto const root = keylet::ownerDir(ammIssue.account);
407 auto currentIndex = root;
408
409 // Iterate over AMM owner directory objects.
410 while (limit-- >= 1)
411 {
412 auto const ownerDir = view.read(currentIndex);
413 if (!ownerDir)
414 return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
415 for (auto const& key : ownerDir->getFieldV256(sfIndexes))
416 {
417 auto const sle = view.read(keylet::child(key));
418 if (!sle)
419 return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
420 // Only one AMM object
421 if (sle->getFieldU16(sfLedgerEntryType) == ltAMM)
422 {
423 if (hasAMM)
424 return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
425 hasAMM = true;
426 continue;
427 }
428 if (sle->getFieldU16(sfLedgerEntryType) != ltRIPPLE_STATE)
429 return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
430 auto const lowLimit = sle->getFieldAmount(sfLowLimit);
431 auto const highLimit = sle->getFieldAmount(sfHighLimit);
432 auto const isLPTrustline = lowLimit.getIssuer() == lpAccount ||
433 highLimit.getIssuer() == lpAccount;
434 auto const isLPTokenTrustline =
435 lowLimit.issue() == ammIssue || highLimit.issue() == ammIssue;
436
437 // Liquidity Provider trustline
438 if (isLPTrustline)
439 {
440 // LPToken trustline
441 if (isLPTokenTrustline)
442 {
443 if (++nLPTokenTrustLines > 1)
444 return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
445 }
446 else if (++nIOUTrustLines > 2)
447 return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
448 }
449 // Another Liquidity Provider LPToken trustline
450 else if (isLPTokenTrustline)
451 return false;
452 else if (++nIOUTrustLines > 2)
453 return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
454 }
455 auto const uNodeNext = ownerDir->getFieldU64(sfIndexNext);
456 if (uNodeNext == 0)
457 {
458 if (nLPTokenTrustLines != 1 || nIOUTrustLines == 0 ||
459 nIOUTrustLines > 2)
460 return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
461 return true;
462 }
463 currentIndex = keylet::page(root, uNodeNext);
464 }
465 return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
466}
467
468Expected<bool, TER>
470 Sandbox& sb,
471 STAmount const& lpTokens,
472 std::shared_ptr<SLE>& ammSle,
473 AccountID const& account)
474{
475 if (auto const res = isOnlyLiquidityProvider(sb, lpTokens.issue(), account);
476 !res)
477 return Unexpected<TER>(res.error());
478 else if (res.value())
479 {
481 lpTokens,
482 ammSle->getFieldAmount(sfLPTokenBalance),
483 Number{1, -3}))
484 {
485 ammSle->setFieldAmount(sfLPTokenBalance, lpTokens);
486 sb.update(ammSle);
487 }
488 else
489 {
491 }
492 }
493 return true;
494}
495
496} // namespace ripple
A generic endpoint for log messages.
Definition: Journal.h:60
Stream error() const
Definition: Journal.h:346
Stream debug() const
Definition: Journal.h:328
Stream trace() const
Severity stream access functions.
Definition: Journal.h:322
Writeable view to a ledger, for applying a transaction.
Definition: ApplyView.h:144
bool dirRemove(Keylet const &directory, std::uint64_t page, uint256 const &key, bool keepRoot)
Remove an entry from a directory.
Definition: ApplyView.cpp:190
bool emptyDirDelete(Keylet const &directory)
Remove the specified directory, if it is empty.
Definition: ApplyView.cpp:126
A currency issued by an account.
Definition: Issue.h:33
AccountID account
Definition: Issue.h:36
Currency currency
Definition: Issue.h:35
A view into a ledger.
Definition: ReadView.h:52
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
virtual STAmount balanceHook(AccountID const &account, AccountID const &issuer, STAmount const &amount) const
Definition: ReadView.h:179
virtual LedgerInfo const & info() const =0
Returns information about the ledger.
virtual Rules const & rules() const =0
Returns the tx processing rules.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition: Rules.cpp:130
void setIssuer(AccountID const &uIssuer)
Definition: STAmount.h:588
Issue const & issue() const
Definition: STAmount.h:496
std::string getFullText() const override
Definition: STAmount.cpp:696
void push_back(STObject const &object)
Definition: STArray.h:212
AccountID getAccountID(SField const &field) const
Definition: STObject.cpp:651
void makeFieldAbsent(SField const &field)
Definition: STObject.cpp:570
void setFieldU16(SField const &field, std::uint16_t)
Definition: STObject.cpp:735
void setFieldAmount(SField const &field, STAmount const &)
Definition: STObject.cpp:789
bool isFieldPresent(SField const &field) const
Definition: STObject.cpp:484
static STObject makeInnerObject(SField const &name)
Definition: STObject.cpp:95
void setAccountID(SField const &field, AccountID const &)
Definition: STObject.cpp:771
void setFieldU32(SField const &field, std::uint32_t)
Definition: STObject.cpp:741
STBase const & peekAtField(SField const &field) const
Definition: STObject.cpp:429
Discardable, editable view to a ledger.
Definition: Sandbox.h:35
void erase(std::shared_ptr< SLE > const &sle) override
Remove a peeked SLE.
void update(std::shared_ptr< SLE > const &sle) override
Indicate changes to a peeked SLE.
bool exists(Keylet const &k) const override
Determine if a state item exists.
std::shared_ptr< SLE > peek(Keylet const &k) override
Prepare to modify the SLE associated with key.
T make_optional(T... args)
T make_pair(T... args)
T make_tuple(T... args)
Keylet child(uint256 const &key) noexcept
Any item that can be in an owner dir.
Definition: Indexes.cpp:190
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Definition: Indexes.cpp:446
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:244
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:184
Keylet page(uint256 const &root, std::uint64_t index=0) noexcept
A page in a directory.
Definition: Indexes.cpp:380
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition: Indexes.cpp:374
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:25
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:114
FreezeHandling
Controls the treatment of frozen account balances.
Definition: View.h:78
std::uint32_t constexpr TOTAL_TIME_SLOT_SECS
Definition: AMMCore.h:34
bool isXRP(AccountID const &c)
Definition: AccountID.h:90
TER deleteAMMTrustLine(ApplyView &view, std::shared_ptr< SLE > sleState, std::optional< AccountID > const &ammAccountID, beast::Journal j)
Delete trustline to AMM.
Definition: View.cpp:2620
Currency ammLPTCurrency(Currency const &cur1, Currency const &cur2)
Calculate Liquidity Provider Token (LPT) Currency.
Definition: AMMCore.cpp:43
std::uint16_t getTradingFee(ReadView const &view, SLE const &ammSle, AccountID const &account)
Get AMM trading fee for the given account.
Definition: AMMUtils.cpp:179
TER deleteAMMAccount(Sandbox &view, Issue const &asset, Issue const &asset2, beast::Journal j)
Delete trustlines to AMM.
Definition: AMMUtils.cpp:283
Expected< bool, TER > isOnlyLiquidityProvider(ReadView const &view, Issue const &ammIssue, AccountID const &lpAccount)
Return true if the Liquidity Provider is the only AMM provider, false otherwise.
Definition: AMMUtils.cpp:387
Expected< bool, TER > verifyAndAdjustLPTokenBalance(Sandbox &sb, STAmount const &lpTokens, std::shared_ptr< SLE > &ammSle, AccountID const &account)
Due to rounding, the LPTokenBalance of the last LP might not match the LP's trustline balance.
Definition: AMMUtils.cpp:469
bool isFrozen(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer)
Definition: View.cpp:249
void initializeFeeAuctionVote(ApplyView &view, std::shared_ptr< SLE > &ammSle, AccountID const &account, Issue const &lptIssue, std::uint16_t tfee)
Initialize Auction and Voting slots and set the trading/discounted fee.
Definition: AMMUtils.cpp:340
STAmount ammLPHolds(ReadView const &view, Currency const &cur1, Currency const &cur2, AccountID const &ammAccount, AccountID const &lpAccount, beast::Journal const j)
Get the balance of LP tokens.
Definition: AMMUtils.cpp:113
std::pair< STAmount, STAmount > ammPoolHolds(ReadView const &view, AccountID const &ammAccountID, Issue const &issue1, Issue const &issue2, FreezeHandling freezeHandling, beast::Journal const j)
Get AMM pool balances.
Definition: AMMUtils.cpp:31
static TER deleteAMMTrustLines(Sandbox &sb, AccountID const &ammAccountID, std::uint16_t maxTrustlinesToDelete, beast::Journal j)
Definition: AMMUtils.cpp:237
@ tecINTERNAL
Definition: TER.h:310
@ tecAMM_INVALID_TOKENS
Definition: TER.h:331
std::uint32_t constexpr VOTE_WEIGHT_SCALE_FACTOR
Definition: AMMCore.h:45
@ tesSUCCESS
Definition: TER.h:244
NotTEC invalidAMMAssetPair(Issue const &issue1, Issue const &issue2, std::optional< std::pair< Issue, Issue > > const &pair=std::nullopt)
Definition: AMMCore.cpp:80
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
Definition: View.cpp:386
Expected< std::tuple< STAmount, STAmount, STAmount >, TER > ammHolds(ReadView const &view, SLE const &ammSle, std::optional< Issue > const &optIssue1, std::optional< Issue > const &optIssue2, FreezeHandling freezeHandling, beast::Journal const j)
Get AMM pool and LP token balances.
Definition: AMMUtils.cpp:47
std::string to_string(base_uint< Bits, Tag > const &a)
Definition: base_uint.h:630
LedgerEntryType
Identifiers for on-ledger objects.
Definition: LedgerFormats.h:54
TER cleanupOnAccountDelete(ApplyView &view, Keylet const &ownerDirKeylet, EntryDeleter const &deleter, beast::Journal j, std::optional< uint16_t > maxNodesToDelete)
Definition: View.cpp:2542
STAmount ammAccountHolds(ReadView const &view, AccountID const &ammAccountID, Issue const &issue)
Returns total amount held by AMM for the given token.
Definition: AMMUtils.cpp:211
Number root(Number f, unsigned d)
Definition: Number.cpp:636
std::uint16_t constexpr maxDeletableAMMTrustLines
The maximum number of trustlines to delete as part of AMM account deletion cleanup.
Definition: Protocol.h:141
TERSubset< CanCvtToTER > TER
Definition: TER.h:645
bool withinRelativeDistance(Quality const &calcQuality, Quality const &reqQuality, Number const &dist)
Check if the relative distance between the qualities is within the requested distance.
Definition: AMMHelpers.h:129
std::uint32_t constexpr AUCTION_SLOT_DISCOUNTED_FEE_FRACTION
Definition: AMMCore.h:38
NetClock::time_point parentCloseTime
Definition: LedgerHeader.h:42
T time_since_epoch(T... args)