rippled
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 #include <ripple/app/misc/AMMUtils.h>
20 #include <ripple/basics/Log.h>
21 #include <ripple/ledger/Sandbox.h>
22 #include <ripple/protocol/AMMCore.h>
23 #include <ripple/protocol/STAccount.h>
24 #include <ripple/protocol/STObject.h>
25 
26 namespace ripple {
27 
30  ReadView const& view,
31  AccountID const& ammAccountID,
32  Issue const& issue1,
33  Issue const& issue2,
34  FreezeHandling freezeHandling,
35  beast::Journal const j)
36 {
37  auto const assetInBalance =
38  accountHolds(view, ammAccountID, issue1, freezeHandling, j);
39  auto const assetOutBalance =
40  accountHolds(view, ammAccountID, issue2, freezeHandling, j);
41  return std::make_pair(assetInBalance, assetOutBalance);
42 }
43 
44 Expected<std::tuple<STAmount, STAmount, STAmount>, TER>
46  ReadView const& view,
47  SLE const& ammSle,
48  std::optional<Issue> const& optIssue1,
49  std::optional<Issue> const& optIssue2,
50  FreezeHandling freezeHandling,
51  beast::Journal const j)
52 {
53  auto const issues = [&]() -> std::optional<std::pair<Issue, Issue>> {
54  auto const issue1 = ammSle[sfAsset];
55  auto const issue2 = ammSle[sfAsset2];
56  if (optIssue1 && optIssue2)
57  {
59  *optIssue1,
60  *optIssue2,
61  std::make_optional(std::make_pair(issue1, issue2))))
62  {
63  JLOG(j.debug()) << "ammHolds: Invalid optIssue1 or optIssue2 "
64  << *optIssue1 << " " << *optIssue2;
65  return std::nullopt;
66  }
67  return std::make_optional(std::make_pair(*optIssue1, *optIssue2));
68  }
69  auto const singleIssue =
70  [&issue1, &issue2, &j](
71  Issue checkIssue,
72  const char* label) -> std::optional<std::pair<Issue, Issue>> {
73  if (checkIssue == issue1)
74  return std::make_optional(std::make_pair(issue1, issue2));
75  else if (checkIssue == issue2)
76  return std::make_optional(std::make_pair(issue2, issue1));
77  JLOG(j.debug())
78  << "ammHolds: Invalid " << label << " " << checkIssue;
79  return std::nullopt;
80  };
81  if (optIssue1)
82  {
83  return singleIssue(*optIssue1, "optIssue1");
84  }
85  else if (optIssue2)
86  {
87  return singleIssue(*optIssue2, "optIssue2");
88  }
89  return std::make_optional(std::make_pair(issue1, issue2));
90  }();
91  if (!issues)
93  auto const [asset1, asset2] = ammPoolHolds(
94  view,
95  ammSle.getAccountID(sfAccount),
96  issues->first,
97  issues->second,
98  freezeHandling,
99  j);
100  return std::make_tuple(asset1, asset2, ammSle[sfLPTokenBalance]);
101 }
102 
103 STAmount
105  ReadView const& view,
106  Currency const& cur1,
107  Currency const& cur2,
108  AccountID const& ammAccount,
109  AccountID const& lpAccount,
110  beast::Journal const j)
111 {
112  return accountHolds(
113  view,
114  lpAccount,
115  ammLPTCurrency(cur1, cur2),
116  ammAccount,
117  FreezeHandling::fhZERO_IF_FROZEN,
118  j);
119 }
120 
121 STAmount
123  ReadView const& view,
124  SLE const& ammSle,
125  AccountID const& lpAccount,
126  beast::Journal const j)
127 {
128  return ammLPHolds(
129  view,
130  ammSle[sfAsset].currency,
131  ammSle[sfAsset2].currency,
132  ammSle[sfAccount],
133  lpAccount,
134  j);
135 }
136 
138 getTradingFee(ReadView const& view, SLE const& ammSle, AccountID const& account)
139 {
140  using namespace std::chrono;
141  if (ammSle.isFieldPresent(sfAuctionSlot))
142  {
143  auto const& auctionSlot =
144  static_cast<STObject const&>(ammSle.peekAtField(sfAuctionSlot));
145  // Not expired
146  if (auto const expiration = auctionSlot[~sfExpiration];
147  duration_cast<seconds>(
149  .count() < expiration)
150  {
151  if (auctionSlot[~sfAccount] == account)
152  return auctionSlot[sfDiscountedFee];
153  if (auctionSlot.isFieldPresent(sfAuthAccounts))
154  {
155  for (auto const& acct :
156  auctionSlot.getFieldArray(sfAuthAccounts))
157  if (acct[~sfAccount] == account)
158  return auctionSlot[sfDiscountedFee];
159  }
160  }
161  }
162  return ammSle[sfTradingFee];
163 }
164 
165 STAmount
167  ReadView const& view,
168  AccountID const& ammAccountID,
169  Issue const& issue)
170 {
171  if (isXRP(issue))
172  {
173  if (auto const sle = view.read(keylet::account(ammAccountID)))
174  return (*sle)[sfBalance];
175  }
176  else if (auto const sle = view.read(
177  keylet::line(ammAccountID, issue.account, issue.currency));
178  sle &&
179  !isFrozen(view, ammAccountID, issue.currency, issue.account))
180  {
181  auto amount = (*sle)[sfBalance];
182  if (ammAccountID > issue.account)
183  amount.negate();
184  amount.setIssuer(issue.account);
185  return amount;
186  }
187 
188  return STAmount{issue};
189 }
190 
191 } // namespace ripple
ripple::ReadView::info
virtual LedgerInfo const & info() const =0
Returns information about the ledger.
ripple::STObject::peekAtField
const STBase & peekAtField(SField const &field) const
Definition: STObject.cpp:373
ripple::STAmount::negate
void negate()
Definition: STAmount.h:402
ripple::issues
bool issues(DebtDirection dir)
Definition: Steps.h:50
std::make_tuple
T make_tuple(T... args)
ripple::sfDiscountedFee
const SF_UINT16 sfDiscountedFee
ripple::STLedgerEntry
Definition: STLedgerEntry.h:30
ripple::Issue
A currency issued by an account.
Definition: Issue.h:35
ripple::sfAsset
const SF_ISSUE sfAsset
ripple::ammHolds
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:45
std::pair
ripple::sfLPTokenBalance
const SF_AMOUNT sfLPTokenBalance
ripple::accountHolds
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
Definition: View.cpp:243
std::make_optional
T make_optional(T... args)
ripple::Unexpected
Unexpected(E(&)[N]) -> Unexpected< E const * >
ripple::Issue::currency
Currency currency
Definition: Issue.h:38
ripple::FreezeHandling
FreezeHandling
Controls the treatment of frozen account balances.
Definition: View.h:78
ripple::ammAccountID
AccountID ammAccountID(std::uint16_t prefix, uint256 const &parentHash, uint256 const &ammID)
Calculate AMM account ID.
Definition: AMMCore.cpp:30
ripple::sfTradingFee
const SF_UINT16 sfTradingFee
ripple::ammPoolHolds
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:29
ripple::sfExpiration
const SF_UINT32 sfExpiration
ripple::base_uint
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:82
std::chrono::time_point::time_since_epoch
T time_since_epoch(T... args)
ripple::sfAsset2
const SF_ISSUE sfAsset2
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:134
ripple::STObject::getAccountID
AccountID getAccountID(SField const &field) const
Definition: STObject.cpp:589
ripple::tecAMM_INVALID_TOKENS
@ tecAMM_INVALID_TOKENS
Definition: TER.h:301
ripple::sfAuthAccounts
const SField sfAuthAccounts
ripple::getTradingFee
std::uint16_t getTradingFee(ReadView const &view, SLE const &ammSle, AccountID const &account)
Get AMM trading fee for the given account.
Definition: AMMUtils.cpp:138
ripple::TER
TERSubset< CanCvtToTER > TER
Definition: TER.h:575
ripple::STAmount
Definition: STAmount.h:45
ripple::isXRP
bool isXRP(AccountID const &c)
Definition: AccountID.h:89
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::uint16_t
ripple::invalidAMMAssetPair
NotTEC invalidAMMAssetPair(Issue const &issue1, Issue const &issue2, std::optional< std::pair< Issue, Issue >> const &pair=std::nullopt)
Definition: AMMCore.cpp:79
ripple::keylet::line
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:194
ripple::ReadView::read
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
ripple::STObject
Definition: STObject.h:52
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:125
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::STObject::isFieldPresent
bool isFieldPresent(SField const &field) const
Definition: STObject.cpp:428
ripple::ammLPHolds
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:104
ripple::sfBalance
const SF_AMOUNT sfBalance
std::optional
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
std::make_pair
T make_pair(T... args)
ripple::sfAccount
const SF_ACCOUNT sfAccount
ripple::ammLPTCurrency
Currency ammLPTCurrency(Currency const &cur1, Currency const &cur2)
Calculate Liquidity Provider Token (LPT) Currency.
Definition: AMMCore.cpp:42
ripple::sfAuctionSlot
const SField sfAuctionSlot
ripple::ammAccountHolds
STAmount ammAccountHolds(ReadView const &view, AccountID const &ammAccountID, Issue const &issue)
Returns total amount held by AMM for the given token.
Definition: AMMUtils.cpp:166
ripple::isFrozen
bool isFrozen(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer)
Definition: View.cpp:220
ripple::Issue::account
AccountID account
Definition: Issue.h:39
ripple::LedgerInfo::parentCloseTime
NetClock::time_point parentCloseTime
Definition: ReadView.h:84
std::chrono