xrpld
Loading...
Searching...
No Matches
AMMTest.cpp
1#include <test/jtx/AMMTest.h>
2
3#include <test/jtx/AMM.h>
4#include <test/jtx/Account.h>
5#include <test/jtx/CaptureLogs.h>
6#include <test/jtx/Env.h>
7#include <test/jtx/amount.h>
8#include <test/jtx/envconfig.h>
9#include <test/jtx/mpt.h>
10#include <test/jtx/pay.h>
11#include <test/jtx/ter.h>
12
13#include <xrpld/core/Config.h>
14
15#include <xrpl/basics/Number.h>
16#include <xrpl/beast/unit_test/suite.h>
17#include <xrpl/protocol/Feature.h>
18#include <xrpl/protocol/Issue.h>
19#include <xrpl/protocol/MPTIssue.h>
20#include <xrpl/protocol/STAmount.h>
21#include <xrpl/protocol/UintTypes.h>
22#include <xrpl/protocol/XRPAmount.h>
23
24#include <cstdint>
25#include <functional>
26#include <memory>
27#include <optional>
28#include <utility>
29#include <vector>
30
31namespace xrpl::test::jtx {
32
33[[maybe_unused]] std::vector<STAmount>
35 jtx::Env& env,
36 jtx::Account const& gw,
37 std::vector<jtx::Account> const& accounts,
38 std::vector<STAmount> const& amts,
39 Fund how)
40{
41 return fund(env, gw, accounts, XRP(30000), amts, how);
42}
43
44[[maybe_unused]] std::vector<STAmount>
46 jtx::Env& env,
47 std::vector<jtx::Account> const& accounts,
48 STAmount const& xrp,
49 std::vector<STAmount> const& amts,
50 Fund how,
51 std::optional<Account> const& mptIssuer)
52{
53 for (auto const& account : accounts)
54 {
55 if (how == Fund::All || how == Fund::Acct)
56 {
57 env.fund(xrp, account);
58 }
59 }
60 env.close();
61
63 for (auto const& account : accounts)
64 {
65 int i = 0;
66 for (auto const& amt : amts)
67 {
68 auto amount = [&]() {
69 if (amtsOut.size() == amts.size())
70 {
71 return amtsOut[i++];
72 }
73 if (amt.holds<MPTIssue>() && mptIssuer)
74 {
75 MPTTester const mpt({.env = env, .issuer = *mptIssuer, .holders = accounts});
76 return STAmount{mpt.issuanceID(), amt.mpt().value()};
77 }
78 return amt;
79 }();
80 if (amount.holds<Issue>())
81 env.trust(amount + amount, account);
82 if (amtsOut.size() != amts.size())
83 amtsOut.push_back(amount);
84 env(pay(amount.getIssuer(), account, amount));
85 }
86 }
87 env.close();
88 return amtsOut;
89}
90
91[[maybe_unused]] std::vector<STAmount>
93 jtx::Env& env,
94 jtx::Account const& gw,
95 std::vector<jtx::Account> const& accounts,
96 STAmount const& xrp,
97 std::vector<STAmount> const& amts,
98 Fund how)
99{
100 if (how == Fund::All || how == Fund::Gw)
101 env.fund(xrp, gw);
102 env.close();
103 return fund(env, accounts, xrp, amts, how, gw);
104}
105
107 : gw_("gateway")
108 , carol_("carol")
109 , alice_("alice")
110 , bob_("bob")
111 , USD(gw_["USD"])
112 , EUR(gw_["EUR"])
113 , GBP(gw_["GBP"])
114 , BTC(gw_["BTC"])
115 , BAD(jtx::IOU(gw_, badCurrency()))
116{
117}
118
119void
121 std::function<void(jtx::AMM&, jtx::Env&)> const& cb,
123 std::uint16_t tfee,
124 std::optional<jtx::Ter> const& ter,
125 std::vector<FeatureBitset> const& vfeatures)
126{
127 testAMM(cb, TestAMMArg{.pool = pool, .tfee = tfee, .ter = ter, .features = vfeatures});
128}
129
130void
132{
133 using namespace jtx;
134
135 std::string logs;
136
137 for (auto const& features : arg.features)
138 {
139 // Use small Number mantissas for the life of this test.
141
142 // For now, just disable SAV entirely, which locks in the small Number
143 // mantissas
144 Env env{
145 *this,
146 features - featureSingleAssetVault - featureLendingProtocol,
147 arg.noLog ? std::make_unique<CaptureLogs>(&logs) : nullptr};
148
149 auto const [asset1, asset2] = arg.pool ? *arg.pool : std::make_pair(XRP(10000), USD(10000));
150 auto toFund = [&](STAmount const& a) -> STAmount {
151 if (a.native())
152 {
153 auto const defXRP = XRP(30000);
154 if (a <= defXRP)
155 return defXRP;
156 return a + XRP(1000);
157 }
158 auto defAmt = STAmount{a.asset(), 30000};
159 if (a <= defAmt)
160 return defAmt;
161 return a + STAmount{a.asset(), 1000};
162 };
163 auto const toFund1 = toFund(asset1);
164 auto const toFund2 = toFund(asset2);
165 BEAST_EXPECT(asset1 <= toFund1 && asset2 <= toFund2);
166
167 // asset1/asset2 could be dummy MPT. In this case real MPT
168 // is created by fund(), which returns the funded amounts.
169 // The amounts then can be used to figure out the created
170 // MPT if any.
172 if (!asset1.native() && !asset2.native())
173 {
174 funded = fund(env, gw_, {alice_, carol_}, {toFund1, toFund2}, Fund::All);
175 }
176 else if (asset1.native())
177 {
178 funded = fund(env, gw_, {alice_, carol_}, toFund1, {toFund2}, Fund::All);
179 funded.insert(funded.begin(), toFund1);
180 }
181 else if (asset2.native())
182 {
183 funded = fund(env, gw_, {alice_, carol_}, toFund2, {toFund1}, Fund::All);
184 funded.push_back(toFund2);
185 }
186
187 auto const pool1 = STAmount{funded[0].asset(), static_cast<Number>(asset1)};
188 auto const pool2 = STAmount{funded[1].asset(), static_cast<Number>(asset2)};
189
190 AMM ammAlice(
191 env, alice_, pool1, pool2, CreateArg{.log = false, .tfee = arg.tfee, .err = arg.ter});
192 if (BEAST_EXPECT(ammAlice.expectBalances(pool1, pool2, ammAlice.tokens())))
193 cb(ammAlice, env);
194 }
195}
196
199{
200 return env.current()->fees().accountReserve(count);
201}
202
205{
206 return env.current()->fees().increment;
207}
208
211{
212 // These tests were originally written with search parameters that are
213 // different from the current defaults. This function creates an env
214 // with the search parameters that the tests were written for.
215 return Env(*this, envconfig([](std::unique_ptr<Config> cfg) {
216 cfg->pathSearchOld = 7;
217 cfg->pathSearch = 7;
218 cfg->pathSearchMax = 10;
219 return cfg;
220 }));
221}
222
223} // namespace xrpl::test::jtx
T begin(T... args)
std::string const & arg() const
Return the argument associated with the runner.
Definition suite.h:278
A currency issued by an account.
Definition Issue.h:13
Sets the new scale and restores the old scale when it leaves scope.
Definition Number.h:920
Number is a floating point type that can represent a wide range of values.
Definition Number.h:306
jtx::Account const alice_
Definition AMMTest.h:74
void testAMM(std::function< void(jtx::AMM &, jtx::Env &)> const &cb, std::optional< std::pair< STAmount, STAmount > > const &pool=std::nullopt, std::uint16_t tfee=0, std::optional< jtx::Ter > const &ter=std::nullopt, std::vector< FeatureBitset > const &features={testableAmendments()})
testAMM() funds 30,000XRP and 30,000IOU for each non-XRP asset to Alice and Carol
Definition AMMTest.cpp:120
jtx::Account const gw_
Definition AMMTest.h:72
jtx::Account const carol_
Definition AMMTest.h:73
jtx::Account const bob_
Definition AMMTest.h:75
static XRPAmount reserve(jtx::Env &env, std::uint32_t count)
Definition AMMTest.cpp:198
static XRPAmount ammCrtFee(jtx::Env &env)
Definition AMMTest.cpp:204
Convenience class to test AMM functionality.
Immutable cryptographic account descriptor.
Definition jtx/Account.h:17
A transaction testing environment.
Definition Env.h:143
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:133
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition Env.cpp:296
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
Definition Env.cpp:327
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition Env.h:353
Converts to IOU Issue or STAmount.
Test helper for creating, mutating, and asserting MPT and confidential MPT ledger state.
Definition mpt.h:385
T insert(T... args)
T make_pair(T... args)
T make_unique(T... args)
json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Definition pay.cpp:14
std::vector< STAmount > fund(jtx::Env &env, jtx::Account const &gw, std::vector< jtx::Account > const &accounts, std::vector< STAmount > const &amts, Fund how)
Definition AMMTest.cpp:34
XrpT const XRP
Converts to XRP Issue or STAmount.
Definition amount.cpp:92
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition envconfig.h:28
constexpr XRPAmount
Convert XRP to drops (integral types).
Definition TxTest.h:48
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
T push_back(T... args)
T size(T... args)