2#include <test/jtx/Account.h>
3#include <test/jtx/Env.h>
4#include <test/jtx/amount.h>
5#include <test/jtx/balance.h>
6#include <test/jtx/flags.h>
7#include <test/jtx/pay.h>
8#include <test/jtx/require.h>
9#include <test/jtx/ter.h>
10#include <test/jtx/ticket.h>
11#include <test/jtx/trust.h>
12#include <test/jtx/txflags.h>
14#include <xrpl/beast/unit_test/suite.h>
15#include <xrpl/json/json_value.h>
16#include <xrpl/json/to_string.h>
17#include <xrpl/protocol/AccountID.h>
18#include <xrpl/protocol/Feature.h>
19#include <xrpl/protocol/TER.h>
20#include <xrpl/protocol/TxFlags.h>
21#include <xrpl/protocol/UintTypes.h>
22#include <xrpl/protocol/jss.h>
35 testcase(
"Test deletion of trust lines: revert trust line limit to zero");
43 env.
fund(
XRP(10000), becky, alice);
49 env(
trust(becky, alice[
"USD"](50)));
61 jv[
"account"] = becky.
human();
62 auto beckyLines = env.
rpc(
"json",
"account_lines",
to_string(jv));
64 jv[
"account"] = alice.
human();
65 auto aliceLines = env.
rpc(
"json",
"account_lines",
to_string(jv));
67 BEAST_EXPECT(aliceLines[jss::result][jss::lines].size() == 1);
68 BEAST_EXPECT(beckyLines[jss::result][jss::lines].size() == 1);
71 env(
trust(becky, alice[
"USD"](0)));
81 jv[
"account"] = becky.
human();
82 beckyLines = env.
rpc(
"json",
"account_lines",
to_string(jv));
84 jv[
"account"] = alice.
human();
85 aliceLines = env.
rpc(
"json",
"account_lines",
to_string(jv));
87 BEAST_EXPECT(aliceLines[jss::result][jss::lines].size() == 0);
88 BEAST_EXPECT(beckyLines[jss::result][jss::lines].size() == 0);
91 jv[
"account"] = becky.
human();
92 auto const beckyObj = env.
rpc(
"json",
"account_objects",
to_string(jv));
93 BEAST_EXPECT(beckyObj[jss::result][jss::account_objects].size() == 0);
95 jv[
"account"] = alice.
human();
96 auto const aliceObj = env.
rpc(
"json",
"account_objects",
to_string(jv));
97 BEAST_EXPECT(aliceObj[jss::result][jss::account_objects].size() == 0);
104 "Reset trust line limit with Authorised Lines: Verify "
105 "deletion of trust lines");
113 env.
fund(
XRP(10000), becky, alice);
117 env(
fset(alice, asfRequireAuth));
123 env(
trust(becky, alice[
"USD"](50)));
127 env(
trust(alice, alice[
"USD"](0), becky, tfSetfAuth));
139 jv[
"account"] = becky.
human();
140 auto beckyLines = env.
rpc(
"json",
"account_lines",
to_string(jv));
142 jv[
"account"] = alice.
human();
143 auto aliceLines = env.
rpc(
"json",
"account_lines",
to_string(jv));
145 BEAST_EXPECT(aliceLines[jss::result][jss::lines].size() == 1);
146 BEAST_EXPECT(beckyLines[jss::result][jss::lines].size() == 1);
149 env(
trust(becky, alice[
"USD"](0)));
159 jv[
"account"] = becky.
human();
160 beckyLines = env.
rpc(
"json",
"account_lines",
to_string(jv));
162 jv[
"account"] = alice.
human();
163 aliceLines = env.
rpc(
"json",
"account_lines",
to_string(jv));
165 BEAST_EXPECT(aliceLines[jss::result][jss::lines].size() == 0);
166 BEAST_EXPECT(beckyLines[jss::result][jss::lines].size() == 0);
172 if (thirdLineCreatesLE)
174 testcase(
"Allow two free trustlines");
178 testcase(
"Dynamic reserve for trustline");
182 Env env(*
this, features);
184 auto const gwA =
Account{
"gwA"};
185 auto const gwB =
Account{
"gwB"};
186 auto const acctC =
Account{
"acctC"};
187 auto const acctD =
Account{
"acctD"};
189 auto const& creator = createOnHighAcct ? acctD : acctC;
190 auto const& assistor = createOnHighAcct ? acctC : acctD;
193 auto const baseReserve = env.
current()->fees().reserve;
194 auto const threelineReserve = env.
current()->fees().accountReserve(3);
196 env.
fund(
XRP(10000), gwA, gwB, assistor);
207 if (thirdLineCreatesLE)
210 env(
trust(creator, assistor[
"USD"](100)),
227 if (thirdLineCreatesLE)
236 jv[
"account"] = creator.human();
239 BEAST_EXPECT(
lines[jss::result][jss::lines].isArray());
240 BEAST_EXPECT(
lines[jss::result][jss::lines].size() == 3);
241 for (
auto const& line :
lines[jss::result][jss::lines])
243 BEAST_EXPECT(line[jss::limit] ==
"100");
251 testcase(
"TrustSet using a ticket");
256 Env env{*
this, features};
257 auto const gw =
Account{
"gateway"};
258 auto const alice =
Account{
"alice"};
259 auto const usd = gw[
"USD"];
261 env.
fund(
XRP(10000), gw, alice);
278 env(
pay(gw, alice, usd(200)));
286 jv[jss::Account] = a.
human();
288 jv[jss::TransactionType] = jss::TrustSet;
296 testcase(
"TrustSet checks for malformed transactions");
299 Env env{*
this, features};
301 auto const gw =
Account{
"gateway"};
302 auto const alice =
Account{
"alice"};
303 env.
fund(
XRP(10000), gw, alice);
306 for (
std::uint64_t badFlag = 1u; badFlag <= std::numeric_limits<std::uint32_t>::max();
309 if ((badFlag & tfTrustSetMask) != 0u)
340 "Ensure that trust line limits are respected in payment "
346 auto const gw =
Account{
"gateway"};
347 auto const alice =
Account{
"alice"};
348 env.
fund(
XRP(10000), gw, alice);
351 env(
trust(alice, gw[
"USD"](100)));
359 env(
pay(gw, alice, gw[
"USD"](20)));
367 "Ensure that authorised trust lines do not allow payments "
368 "from unauthorised counter-parties");
373 auto const bob =
Account{
"bob"};
374 auto const alice =
Account{
"alice"};
375 env.
fund(
XRP(10000), bob, alice);
378 env(
fset(alice, asfRequireAuth));
384 env(
trust(bob, alice[
"USD"](100)));
396 "Check that trust line limits are respected in conjunction "
397 "with rippling feature");
402 auto const bob =
Account{
"bob"};
403 auto const alice =
Account{
"alice"};
404 env.
fund(
XRP(10000), bob, alice);
408 env(
trust(bob, alice[
"USD"](100)));
433 testcase <<
"TrustSet " << (createQuality ?
"creates" :
"removes")
434 <<
" quality of trustline for " << (createOnHighAcct ?
"high" :
"low")
438 Env env{*
this, features};
440 auto const alice =
Account{
"alice"};
441 auto const bob =
Account{
"bob"};
443 auto const& fromAcct = createOnHighAcct ? alice : bob;
444 auto const& toAcct = createOnHighAcct ? bob : alice;
446 env.
fund(
XRP(10000), fromAcct, toAcct);
448 auto txWithoutQuality =
trust(toAcct, fromAcct[
"USD"](100));
449 txWithoutQuality[
"QualityIn"] =
"0";
450 txWithoutQuality[
"QualityOut"] =
"0";
452 auto txWithQuality = txWithoutQuality;
453 txWithQuality[
"QualityIn"] =
"1000";
454 txWithQuality[
"QualityOut"] =
"1000";
456 auto& tx1 = createQuality ? txWithQuality : txWithoutQuality;
457 auto& tx2 = createQuality ? txWithoutQuality : txWithQuality;
459 auto checkQuality = [&](
bool const exists) {
461 jv[
"account"] = toAcct.human();
463 auto quality = exists ? 1000 : 0;
464 BEAST_EXPECT(
lines[jss::result][jss::lines].isArray());
465 BEAST_EXPECT(
lines[jss::result][jss::lines].size() == 1);
466 BEAST_EXPECT(
lines[jss::result][jss::lines][0u][jss::quality_in] == quality);
467 BEAST_EXPECT(
lines[jss::result][jss::lines][0u][jss::quality_out] == quality);
471 checkQuality(createQuality);
474 checkQuality(!createQuality);
480 testcase(
"Create trustline with disallow incoming");
486 for (
bool const withFix : {
true,
false})
488 auto const amend = withFix ? features : features - fixDisallowIncomingV1;
490 Env env{*
this, amend};
491 auto const dist =
Account(
"dist");
493 auto const usd = gw[
"USD"];
494 auto const distUSD = dist[
"USD"];
499 env(
fset(gw, asfRequireAuth));
502 env(
fset(dist, asfDisallowIncomingTrustline));
505 env(
trust(dist, usd(10000)));
511 env(
trust(gw, distUSD(10000)),
Txflags(tfSetfAuth), trustResult);
515 env(
pay(gw, dist, usd(1000)), txResult);
520 Env env{*
this, features};
522 auto const gw =
Account{
"gateway"};
523 auto const alice =
Account{
"alice"};
524 auto const bob =
Account{
"bob"};
525 auto const usd = gw[
"USD"];
527 env.
fund(
XRP(10000), gw, alice, bob);
531 env(
fset(gw, asfDisallowIncomingTrustline));
539 env(
fclear(gw, asfDisallowIncomingTrustline));
543 env(
trust(alice, usd(1000)));
547 env(
pay(gw, alice, usd(200)));
551 env(
fset(gw, asfDisallowIncomingTrustline));
555 env(
pay(gw, alice, usd(200)));
560 env(
pay(gw, alice, usd(200)));
564 env(
fset(bob, asfDisallowIncomingTrustline));
577 env(
fclear(gw, asfDisallowIncomingTrustline));
581 env(
trust(bob, usd(1000)));
585 env(
pay(gw, bob, usd(200)));
TestcaseT testcase
Memberspace for declaring test cases.
A currency issued by an account.
json::Value getJson(JsonOptions=JsonOptions::Values::None) const override
void run() override
Runs the suite.
void testMalformedTransaction(FeatureBitset features)
void testTrustLineLimitsWithRippling()
void testExceedTrustLineLimit()
void testTrustLineResetWithAuthFlag()
void testTicketTrustSet(FeatureBitset features)
void testDisallowIncoming(FeatureBitset features)
void testFreeTrustlines(FeatureBitset features, bool thirdLineCreatesLE, bool createOnHighAcct)
void testTrustLineDelete()
void testModifyQualityOfTrustline(FeatureBitset features, bool createQuality, bool createOnHighAcct)
void testWithFeats(FeatureBitset features)
static json::Value trustExplicitAmt(jtx::Account const &a, STAmount const &amt)
void testAuthFlagTrustLines()
Immutable cryptographic account descriptor.
std::string const & human() const
Returns the human readable public key.
A transaction testing environment.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
void require(Args const &... args)
Check a set of requirements.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Check a set of conditions.
Set the expected result code for a JTx The test will fail if the code doesn't match.
Set a ticket sequence on a JTx.
json::Value create(Account const &account, std::uint32_t count)
Create one of more tickets.
json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
XrpT const XRP
Converts to XRP Issue or STAmount.
OwnerCount< ltRIPPLE_STATE > lines
Match the number of trust lines in the account's owner directory.
XRPAmount txFee(Env const &env, std::uint16_t n)
json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
FeatureBitset testableAmendments()
json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
bool toCurrency(Currency &, std::string const &)
Tries to convert a string to a Currency, returns true on success.
std::string to_string(BaseUInt< Bits, Tag > const &a)
AccountID const & noAccount()
A placeholder for empty accounts.
@ tecNO_LINE_INSUF_RESERVE
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...