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
23#include <xrpl/basics/Log.h>
24#include <xrpl/ledger/Sandbox.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:143
bool dirRemove(Keylet const &directory, std::uint64_t page, uint256 const &key, bool keepRoot)
Remove an entry from a directory.
bool emptyDirDelete(Keylet const &directory)
Remove the specified directory, if it is empty.
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:51
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:178
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:673
void push_back(STObject const &object)
Definition STArray.h:212
AccountID getAccountID(SField const &field) const
Definition STObject.cpp:657
void makeFieldAbsent(SField const &field)
Definition STObject.cpp:570
void setFieldU16(SField const &field, std::uint16_t)
Definition STObject.cpp:751
void setFieldAmount(SField const &field, STAmount const &)
Definition STObject.cpp:811
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:793
void setFieldU32(SField const &field, std::uint32_t)
Definition STObject.cpp:757
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 is_same_v
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.
FreezeHandling
Controls the treatment of frozen account balances.
Definition View.h:77
std::uint32_t constexpr TOTAL_TIME_SLOT_SECS
Definition AMMCore.h:34
bool isXRP(AccountID const &c)
Definition AccountID.h:90
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
TER cleanupOnAccountDelete(ApplyView &view, Keylet const &ownerDirKeylet, EntryDeleter const &deleter, beast::Journal j, std::optional< std::uint16_t > maxNodesToDelete=std::nullopt)
Cleanup owner directory entries on account delete.
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:247
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:311
@ tecAMM_INVALID_TOKENS
Definition TER.h:332
std::uint32_t constexpr VOTE_WEIGHT_SCALE_FACTOR
Definition AMMCore.h:45
@ tesSUCCESS
Definition TER.h:245
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:387
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.
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
TER deleteAMMTrustLine(ApplyView &view, std::shared_ptr< SLE > sleState, std::optional< AccountID > const &ammAccountID, beast::Journal j)
Delete trustline to AMM.
Definition View.cpp:2806
std::uint16_t constexpr maxDeletableAMMTrustLines
The maximum number of trustlines to delete as part of AMM account deletion cleanup.
Definition Protocol.h:150
TERSubset< CanCvtToTER > TER
Definition TER.h:649
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
T time_since_epoch(T... args)