20 #include <ripple/app/tx/impl/AMMCreate.h>
22 #include <ripple/app/ledger/OrderBookDB.h>
23 #include <ripple/app/misc/AMMHelpers.h>
24 #include <ripple/app/misc/AMMUtils.h>
25 #include <ripple/ledger/Sandbox.h>
26 #include <ripple/ledger/View.h>
27 #include <ripple/protocol/AMMCore.h>
28 #include <ripple/protocol/Feature.h>
29 #include <ripple/protocol/STAccount.h>
30 #include <ripple/protocol/STIssue.h>
31 #include <ripple/protocol/TxFlags.h>
46 JLOG(ctx.
j.
debug()) <<
"AMM Instance: invalid flags.";
53 if (amount.issue() == amount2.issue())
56 <<
"AMM Instance: tokens can not have the same currency/issuer.";
62 JLOG(ctx.
j.
debug()) <<
"AMM Instance: invalid asset1 amount.";
68 JLOG(ctx.
j.
debug()) <<
"AMM Instance: invalid asset2 amount.";
74 JLOG(ctx.
j.
debug()) <<
"AMM Instance: invalid trading fee.";
96 if (
auto const ammKeylet =
keylet::amm(amount.issue(), amount2.issue());
99 JLOG(ctx.
j.
debug()) <<
"AMM Instance: ltAMM already exists.";
107 <<
"AMM Instance: account is not authorized, " << amount.issue();
111 if (
auto const ter =
requireAuth(ctx.
view, amount2.issue(), accountID);
115 <<
"AMM Instance: account is not authorized, " << amount2.issue();
123 JLOG(ctx.
j.
debug()) <<
"AMM Instance: involves frozen asset.";
131 if (
auto const issuerAccount =
138 if (noDefaultRipple(ctx.
view, amount.issue()) ||
139 noDefaultRipple(ctx.
view, amount2.issue()))
141 JLOG(ctx.
j.
debug()) <<
"AMM Instance: DefaultRipple not set";
148 if (xrpBalance <= beast::zero)
150 JLOG(ctx.
j.
debug()) <<
"AMM Instance: insufficient reserves";
154 auto insufficientBalance = [&](
STAmount const& asset) {
156 return xrpBalance < asset;
162 FreezeHandling::fhZERO_IF_FROZEN,
166 if (insufficientBalance(amount) || insufficientBalance(amount2))
169 <<
"AMM Instance: insufficient funds, " << amount <<
" " << amount2;
173 auto isLPToken = [&](
STAmount const& amount) ->
bool {
176 return sle->isFieldPresent(
sfAMMID);
180 if (isLPToken(amount) || isLPToken(amount2))
182 JLOG(ctx.
j.
debug()) <<
"AMM Instance: can't create with LPTokens "
183 << amount <<
" " << amount2;
188 auto clawbackDisabled = [&](
Issue const& issue) ->
TER {
199 if (
auto const ter = clawbackDisabled(amount.issue()); ter !=
tesSUCCESS)
201 return clawbackDisabled(amount2.issue());
214 auto const ammKeylet =
keylet::amm(amount.issue(), amount2.issue());
219 for (
auto p = 0; p < maxAccountAttempts; ++p)
221 auto const ammAccount =
232 JLOG(j_.
error()) <<
"AMM Instance: AMM already exists.";
233 return {ammAccount.error(),
false};
238 amount.issue().currency, amount2.issue().currency, *ammAccount);
241 JLOG(j_.
error()) <<
"AMM Instance: LP Token already exists.";
247 sleAMMRoot->setAccountID(
sfAccount, *ammAccount);
263 sleAMMRoot->setFieldU32(
266 sleAMMRoot->setFieldH256(
sfAMMID, ammKeylet.key);
270 auto const lpTokens =
ammLPTokens(amount, amount2, lptIss);
273 auto ammSle = std::make_shared<SLE>(ammKeylet);
274 ammSle->setAccountID(
sfAccount, *ammAccount);
276 auto const& [issue1, issue2] =
std::minmax(amount.issue(), amount2.issue());
288 JLOG(j_.
debug()) <<
"AMM Instance: failed to send LPT " << lpTokens;
292 auto sendAndTrustSet = [&](
STAmount const& amount) ->
TER {
310 auto const flags = sleRippleState->getFlags();
312 sb.
update(sleRippleState);
319 res = sendAndTrustSet(amount);
322 JLOG(j_.
debug()) <<
"AMM Instance: failed to send " << amount;
327 res = sendAndTrustSet(amount2);
330 JLOG(j_.
debug()) <<
"AMM Instance: failed to send " << amount2;
334 JLOG(j_.
debug()) <<
"AMM Instance: success " << *ammAccount <<
" "
335 << ammKeylet.key <<
" " << lpTokens <<
" " << amount <<
" "
339 Book const book{issueIn, issueOut};
341 if (
auto const bookExisted =
static_cast<bool>(sb.
read(dir));
345 addOrderBook(amount.issue(), amount2.issue(),
getRate(amount2, amount));
346 addOrderBook(amount2.issue(), amount.issue(),
getRate(amount, amount2));
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.
virtual OrderBookDB & getOrderBookDB()=0
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
A currency issued by an account.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
TER accountSend(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee)
static std::pair< TER, bool > applyCreate(ApplyContext &ctx_, Sandbox &sb, AccountID const &account_, beast::Journal j_)
Issue const & issue() const
const SF_AMOUNT sfAmount2
Issue ammLPTIssue(Currency const &cur1, Currency const &cur2, AccountID const &ammAccountID)
Calculate LPT Issue from AMM asset pair.
static NotTEC preflight(PreflightContext const &ctx)
const SF_UINT32 sfSequence
const SF_AMOUNT sfLPTokenBalance
virtual Fees const & fees() const =0
Returns the fees for the base ledger.
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
bool ammEnabled(Rules const &)
Return true if required AMM amendments are enabled.
Keylet amm(Issue const &issue1, Issue const &issue2) noexcept
AMM entry.
Unexpected(E(&)[N]) -> Unexpected< E const * >
void update(std::shared_ptr< SLE > const &sle) override
Indicate changes to a peeked SLE.
const beast::Journal journal
@ lsfAllowTrustLineClawback
AccountID ammAccountID(std::uint16_t prefix, uint256 const &parentHash, uint256 const &ammID)
Calculate AMM account ID.
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
const SF_UINT16 sfTradingFee
TER requireAuth(ReadView const &view, Issue const &issue, AccountID const &account)
Check if the account requires authorization.
NotTEC invalidAMMAmount(STAmount const &amount, std::optional< std::pair< Issue, Issue >> const &pair=std::nullopt, bool validZero=false)
Validate the amount.
const uint256 featureDeletableAccounts
std::uint64_t getRate(STAmount const &offerOut, STAmount const &offerIn)
static TER preclaim(PreclaimContext const &ctx)
Integers of any length that is a multiple of 32-bits.
LedgerInfo const & info() const override
Returns information about the ledger.
Keylet account(AccountID const &id) noexcept
AccountID root.
Discardable, editable view to a ledger.
TER doApply() override
Attempt to create the AMM instance.
TERSubset< CanCvtToTER > TER
XRPAmount xrpLiquid(ReadView const &view, AccountID const &id, std::int32_t ownerCountAdj, beast::Journal j)
std::uint32_t getFlags() const
bool isXRP(AccountID const &c)
State information when applying a tx.
A generic endpoint for log messages.
Keylet line(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
State information when determining if a tx is likely to claim a fee.
void insert(std::shared_ptr< SLE > const &sle) override
Insert a new state SLE.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
constexpr std::uint16_t TRADING_FEE_THRESHOLD
LedgerIndex seq() const
Returns the sequence number of the base ledger.
virtual Rules const & rules() const =0
Returns the tx processing rules.
STAmount ammLPTokens(STAmount const &asset1, STAmount const &asset2, Issue const &lptIssue)
const SF_AMOUNT sfBalance
std::shared_ptr< SLE const > read(Keylet const &k) const override
Return the state item associated with a key.
const SF_ACCOUNT sfAccount
std::shared_ptr< SLE > peek(Keylet const &k) override
Prepare to modify the SLE associated with key.
Keylet quality(Keylet const &k, std::uint64_t q) noexcept
The initial directory page for a specific quality.
State information when preflighting a tx.
constexpr std::uint32_t tfUniversalMask
bool isFrozen(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer)
TERSubset< CanCvtToNotTEC > NotTEC
void addOrderBook(Book const &)