1#include <xrpl/basics/Log.h>
2#include <xrpl/basics/safe_cast.h>
3#include <xrpl/ledger/Sandbox.h>
4#include <xrpl/protocol/AMMCore.h>
5#include <xrpl/protocol/STObject.h>
6#include <xrpl/tx/transactors/dex/AMMHelpers.h>
7#include <xrpl/tx/transactors/dex/AMMUtils.h>
20 auto const assetInBalance =
accountHolds(view, ammAccountID, issue1, freezeHandling, j);
21 auto const assetOutBalance =
accountHolds(view, ammAccountID, issue2, freezeHandling, j);
25Expected<std::tuple<STAmount, STAmount, STAmount>,
TER>
35 auto const issue1 = ammSle[sfAsset].get<
Issue>();
36 auto const issue2 = ammSle[sfAsset2].get<
Issue>();
37 if (optIssue1 && optIssue2)
44 JLOG(j.
debug()) <<
"ammHolds: Invalid optIssue1 or optIssue2 " << *optIssue1 <<
" "
51 auto const singleIssue = [&issue1, &issue2, &j](
54 if (checkIssue == issue1)
58 if (checkIssue == issue2)
64 JLOG(j.
debug()) <<
"ammHolds: Invalid " << label <<
" " << checkIssue;
70 return singleIssue(*optIssue1,
"optIssue1");
75 return singleIssue(*optIssue2,
"optIssue2");
106 amount.clear(
Issue{currency, ammAccount});
107 JLOG(j.
trace()) <<
"ammLPHolds: no SLE "
109 <<
" amount=" << amount.getFullText();
111 else if (
isFrozen(view, lpAccount, currency, ammAccount))
113 amount.clear(
Issue{currency, ammAccount});
114 JLOG(j.
trace()) <<
"ammLPHolds: frozen currency "
116 <<
" amount=" << amount.getFullText();
120 amount = sle->getFieldAmount(sfBalance);
121 if (lpAccount > ammAccount)
126 amount.setIssuer(ammAccount);
128 JLOG(j.
trace()) <<
"ammLPHolds:"
130 <<
" amount=" << amount.getFullText();
133 return view.
balanceHook(lpAccount, ammAccount, amount);
145 ammSle[sfAsset].get<Issue>().currency,
146 ammSle[sfAsset2].get<Issue>().currency,
158 "xrpl::getTradingFee : auction present");
161 auto const& auctionSlot = safe_downcast<STObject const&>(ammSle.
peekAtField(sfAuctionSlot));
163 if (
auto const expiration = auctionSlot[~sfExpiration];
167 if (auctionSlot[~sfAccount] == account)
168 return auctionSlot[sfDiscountedFee];
169 if (auctionSlot.isFieldPresent(sfAuthAccounts))
171 for (
auto const& acct : auctionSlot.getFieldArray(sfAuthAccounts))
173 if (acct[~sfAccount] == account)
174 return auctionSlot[sfDiscountedFee];
179 return ammSle[sfTradingFee];
188 return (*sle)[sfBalance];
194 auto amount = (*sle)[sfBalance];
195 if (ammAccountID > issue.
account)
197 amount.setIssuer(issue.
account);
218 if (nodeType == LedgerEntryType::ltAMM)
221 if (nodeType != LedgerEntryType::ltRIPPLE_STATE)
224 JLOG(j.
error()) <<
"deleteAMMTrustLines: deleting non-trustline " << nodeType;
230 if (sleItem->getFieldAmount(sfBalance) != beast::zero)
233 JLOG(j.
error()) <<
"deleteAMMTrustLines: deleting trustline with "
242 maxTrustlinesToDelete);
252 JLOG(j.
error()) <<
"deleteAMMAccount: AMM object does not exist " << asset <<
" " << asset2;
257 auto const ammAccountID = (*ammSle)[sfAccount];
262 JLOG(j.
error()) <<
"deleteAMMAccount: AMM account does not exist "
273 if (!sb.
dirRemove(ownerDirKeylet, (*ammSle)[sfOwnerNode], ammSle->key(),
false))
276 JLOG(j.
error()) <<
"deleteAMMAccount: failed to remove dir link";
283 JLOG(j.
error()) <<
"deleteAMMAccount: cannot delete root dir node of "
290 sb.
erase(sleAMMRoot);
300 Issue const& lptIssue,
303 auto const& rules = view.
rules();
312 ammSle->setFieldArray(sfVoteSlots, voteSlots);
316 if (rules.enabled(fixInnerObjTemplate) && !ammSle->isFieldPresent(sfAuctionSlot))
319 ammSle->set(std::move(auctionSlot));
321 STObject& auctionSlot = ammSle->peekFieldObject(sfAuctionSlot);
324 auto const expiration = std::chrono::duration_cast<std::chrono::seconds>(
333 ammSle->setFieldU16(sfTradingFee, tfee);
335 else if (ammSle->isFieldPresent(sfTradingFee))
337 ammSle->makeFieldAbsent(sfTradingFee);
367 auto currentIndex =
root;
372 auto const ownerDir = view.
read(currentIndex);
375 for (
auto const& key : ownerDir->getFieldV256(sfIndexes))
381 if (sle->getFieldU16(sfLedgerEntryType) == ltAMM)
388 if (sle->getFieldU16(sfLedgerEntryType) != ltRIPPLE_STATE)
390 auto const lowLimit = sle->getFieldAmount(sfLowLimit);
391 auto const highLimit = sle->getFieldAmount(sfHighLimit);
392 auto const isLPTrustline =
393 lowLimit.getIssuer() == lpAccount || highLimit.getIssuer() == lpAccount;
394 auto const isLPTokenTrustline =
395 lowLimit.issue() == ammIssue || highLimit.issue() == ammIssue;
401 if (isLPTokenTrustline)
403 if (++nLPTokenTrustLines > 1)
406 else if (++nIOUTrustLines > 2)
412 else if (isLPTokenTrustline)
416 else if (++nIOUTrustLines > 2)
421 auto const uNodeNext = ownerDir->getFieldU64(sfIndexNext);
424 if (nLPTokenTrustLines != 1 || nIOUTrustLines == 0 || nIOUTrustLines > 2)
441 if (!res.has_value())
449 lpTokens, ammSle->getFieldAmount(sfLPTokenBalance),
Number{1, -3}))
451 ammSle->setFieldAmount(sfLPTokenBalance, lpTokens);
A generic endpoint for log messages.
Stream trace() const
Severity stream access functions.
Writeable view to a ledger, for applying a transaction.
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.
Number is a floating point type that can represent a wide range of values.
virtual Rules const & rules() const =0
Returns the tx processing rules.
virtual LedgerHeader const & header() const =0
Returns information about the ledger.
virtual STAmount balanceHook(AccountID const &account, AccountID const &issuer, STAmount const &amount) const
virtual std::shared_ptr< SLE const > 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.
Issue const & issue() const
void push_back(STObject const &object)
void setFieldU32(SField const &field, std::uint32_t)
void setFieldAmount(SField const &field, STAmount const &)
bool isFieldPresent(SField const &field) const
void setFieldU16(SField const &field, std::uint16_t)
static STObject makeInnerObject(SField const &name)
STBase const & peekAtField(SField const &field) const
void setAccountID(SField const &field, AccountID const &)
AccountID getAccountID(SField const &field) const
void makeFieldAbsent(SField const &field)
Discardable, editable view to a ledger.
void update(std::shared_ptr< SLE > const &sle) override
Indicate changes to a peeked SLE.
void erase(std::shared_ptr< SLE > const &sle) override
Remove a peeked SLE.
std::shared_ptr< SLE > peek(Keylet const &k) override
Prepare to modify the SLE associated with key.
bool exists(Keylet const &k) const override
Determine if a state item exists.
T make_optional(T... args)
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Keylet child(uint256 const &key) noexcept
Any item that can be in an owner dir.
Keylet line(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet page(uint256 const &root, std::uint64_t index=0) noexcept
A page in a directory.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
static TER deleteAMMTrustLines(Sandbox &sb, AccountID const &ammAccountID, std::uint16_t maxTrustlinesToDelete, beast::Journal j)
STAmount ammAccountHolds(ReadView const &view, AccountID const &ammAccountID, Issue const &issue)
Returns total amount held by AMM for the given token.
FreezeHandling
Controls the treatment of frozen account balances.
TER deleteAMMAccount(Sandbox &view, Issue const &asset, Issue const &asset2, beast::Journal j)
Delete trustlines to AMM.
bool isXRP(AccountID const &c)
std::uint32_t constexpr VOTE_WEIGHT_SCALE_FACTOR
std::string to_string(base_uint< Bits, Tag > const &a)
std::uint32_t constexpr TOTAL_TIME_SLOT_SECS
NotTEC invalidAMMAssetPair(Issue const &issue1, Issue const &issue2, std::optional< std::pair< Issue, Issue > > const &pair=std::nullopt)
std::uint32_t constexpr AUCTION_SLOT_DISCOUNTED_FEE_FRACTION
std::uint16_t constexpr maxDeletableAMMTrustLines
The maximum number of trustlines to delete as part of AMM account deletion cleanup.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j, SpendableHandling includeFullBalance=shSIMPLE_BALANCE)
Number root(Number f, unsigned d)
TER deleteAMMTrustLine(ApplyView &view, std::shared_ptr< SLE > sleState, std::optional< AccountID > const &ammAccountID, beast::Journal j)
Delete trustline to AMM.
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.
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.
bool isFrozen(ReadView const &view, AccountID const &account, MPTIssue const &mptIssue, int depth=0)
TERSubset< CanCvtToTER > TER
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.
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.
bool isTesSuccess(TER x) noexcept
LedgerEntryType
Identifiers for on-ledger objects.
bool withinRelativeDistance(Quality const &calcQuality, Quality const &reqQuality, Number const &dist)
Check if the relative distance between the qualities is within the requested distance.
std::uint16_t getTradingFee(ReadView const &view, SLE const &ammSle, AccountID const &account)
Get AMM trading fee for the given account.
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.
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.
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.
Currency ammLPTCurrency(Currency const &cur1, Currency const &cur2)
Calculate Liquidity Provider Token (LPT) Currency.
T time_since_epoch(T... args)