20 #include <ripple/protocol/Feature.h>
21 #include <ripple/protocol/Quality.h>
22 #include <ripple/protocol/jss.h>
24 #include <test/jtx/PathSet.h>
25 #include <test/jtx/WSClient.h>
35 return env.
current()->fees().accountReserve(count);
41 return env.
current()->info().parentCloseTime.time_since_epoch().count();
49 auto feeDrops = env.current()->fees().base;
61 jvParams[jss::ledger_index] =
"current";
62 jvParams[jss::ripple_state][jss::currency] = currency;
64 jvParams[jss::ripple_state][jss::accounts].
append(acct_a.
human());
65 jvParams[jss::ripple_state][jss::accounts].
append(acct_b.
human());
67 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
74 jvParams[jss::ledger_index] =
"current";
75 jvParams[jss::account_root] = acct.
human();
77 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
87 jvParams[jss::offer][jss::account] = acct.
human();
88 jvParams[jss::offer][jss::seq] = offer_seq;
90 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
96 Issue const& taker_pays,
97 Issue const& taker_gets)
100 jvbp[jss::ledger_index] =
"current";
105 return env.
rpc(
"json",
"book_offers",
to_string(jvbp))[jss::result];
112 testcase(
"Incorrect Removal of Funded Offers");
124 Env env{*
this, features};
126 auto const gw =
Account{
"gateway"};
127 auto const USD = gw[
"USD"];
128 auto const BTC = gw[
"BTC"];
133 env.fund(
XRP(10000), alice, bob, carol, gw);
134 env.trust(USD(1000), alice, bob, carol);
135 env.trust(BTC(1000), alice, bob, carol);
137 env(
pay(gw, alice, BTC(1000)));
139 env(
pay(gw, carol, USD(1000)));
140 env(
pay(gw, carol, BTC(1000)));
145 env(offer(carol, BTC(49),
XRP(49)));
146 env(offer(carol, BTC(51),
XRP(51)));
150 env(offer(carol,
XRP(50), USD(50)));
151 env(offer(carol,
XRP(50), USD(50)));
154 env(offer(carol, BTC(1), USD(100)));
158 env(
pay(alice, bob, USD(100)),
163 env.require(
balance(bob, USD(100)));
165 !
isOffer(env, carol, BTC(1), USD(100)) &&
172 testcase(
"Removing Canceled Offers");
175 Env env{*
this, features};
177 auto const gw =
Account{
"gateway"};
178 auto const alice =
Account{
"alice"};
179 auto const USD = gw[
"USD"];
181 env.fund(
XRP(10000), alice, gw);
183 env.trust(USD(100), alice);
186 env(
pay(gw, alice, USD(50)));
189 auto const offer1Seq = env.seq(alice);
194 BEAST_EXPECT(
isOffer(env, alice,
XRP(500), USD(100)));
197 auto const offer2Seq = env.seq(alice);
199 env(offer(alice,
XRP(300), USD(100)),
200 json(jss::OfferSequence, offer1Seq),
211 env(offer(alice,
XRP(400), USD(200)),
212 json(jss::OfferSequence, offer1Seq),
221 auto const offer4Seq = env.seq(alice);
225 BEAST_EXPECT(
isOffer(env, alice,
XRP(222), USD(111)));
228 cancelOffer[jss::Account] = alice.human();
229 cancelOffer[jss::OfferSequence] = offer4Seq;
230 cancelOffer[jss::TransactionType] = jss::OfferCancel;
234 BEAST_EXPECT(env.seq(alice) == offer4Seq + 2);
236 BEAST_EXPECT(!
isOffer(env, alice,
XRP(222), USD(111)));
240 env.require(
offers(alice, 2));
245 env(offer(alice,
XRP(5), USD(2)),
247 json(jss::OfferSequence, offer2Seq),
251 env.require(
offers(alice, 2));
252 BEAST_EXPECT(
isOffer(env, alice,
XRP(300), USD(100)));
253 BEAST_EXPECT(!
isOffer(env, alice,
XRP(5), USD(2)));
259 testcase(
"Tiny payments");
263 using namespace std::chrono_literals;
264 auto const alice =
Account{
"alice"};
265 auto const bob =
Account{
"bob"};
266 auto const carol =
Account{
"carol"};
269 auto const USD = gw[
"USD"];
270 auto const EUR = gw[
"EUR"];
272 Env env{*
this, features};
274 env.fund(
XRP(10000), alice, bob, carol, gw);
275 env.trust(USD(1000), alice, bob, carol);
276 env.trust(EUR(1000), alice, bob, carol);
277 env(
pay(gw, alice, USD(100)));
278 env(
pay(gw, carol, EUR(100)));
284 for (
int i = 0; i < 101; ++i)
285 env(offer(carol, USD(1), EUR(2)));
287 env(
pay(alice, bob, EUR(epsilon)),
path(~EUR),
sendmax(USD(100)));
293 testcase(
"XRP Tiny payments");
311 using namespace std::chrono_literals;
312 auto const alice =
Account{
"alice"};
313 auto const bob =
Account{
"bob"};
314 auto const carol =
Account{
"carol"};
315 auto const dan =
Account{
"dan"};
316 auto const erin =
Account{
"erin"};
319 auto const USD = gw[
"USD"];
320 Env env{*
this, features};
322 env.fund(
XRP(10000), alice, bob, carol, dan, erin, gw);
323 env.trust(USD(1000), alice, bob, carol, dan, erin);
324 env(
pay(gw, carol, USD(0.99999)));
325 env(
pay(gw, dan, USD(1)));
326 env(
pay(gw, erin, USD(1)));
333 env(offer(carol,
drops(1), USD(1)));
336 env(offer(dan,
XRP(100), USD(1)));
345 env(offer(erin,
drops(2), USD(2)));
347 env(
pay(alice, bob, USD(1)),
362 testcase(
"Enforce No Ripple");
366 auto const gw =
Account{
"gateway"};
367 auto const USD = gw[
"USD"];
368 auto const BTC = gw[
"BTC"];
369 auto const EUR = gw[
"EUR"];
377 Env env{*
this, features};
379 auto const gw1 =
Account{
"gw1"};
380 auto const USD1 = gw1[
"USD"];
381 auto const gw2 =
Account{
"gw2"};
382 auto const USD2 = gw2[
"USD"];
384 env.fund(
XRP(10000), alice,
noripple(bob), carol, dan, gw1, gw2);
385 env.trust(USD1(1000), alice, carol, dan);
387 env.trust(USD2(1000), alice, carol, dan);
390 env(
pay(gw1, dan, USD1(50)));
391 env(
pay(gw1, bob, USD1(50)));
392 env(
pay(gw2, bob, USD2(50)));
394 env(offer(dan,
XRP(50), USD1(50)));
396 env(
pay(alice, carol, USD2(50)),
404 Env env{*
this, features};
406 auto const gw1 =
Account{
"gw1"};
407 auto const USD1 = gw1[
"USD"];
408 auto const gw2 =
Account{
"gw2"};
409 auto const USD2 = gw2[
"USD"];
411 env.fund(
XRP(10000), alice, bob, carol, dan, gw1, gw2);
412 env.trust(USD1(1000), alice, bob, carol, dan);
413 env.trust(USD2(1000), alice, bob, carol, dan);
415 env(
pay(gw1, dan, USD1(50)));
416 env(
pay(gw1, bob, USD1(50)));
417 env(
pay(gw2, bob, USD2(50)));
419 env(offer(dan,
XRP(50), USD1(50)));
421 env(
pay(alice, carol, USD2(50)),
427 env.require(
balance(bob, USD1(100)));
428 env.require(
balance(bob, USD2(0)));
429 env.require(
balance(carol, USD2(50)));
436 testcase(
"Insufficient Reserve");
446 auto const gw =
Account{
"gateway"};
447 auto const alice =
Account{
"alice"};
448 auto const bob =
Account{
"bob"};
449 auto const carol =
Account{
"carol"};
450 auto const USD = gw[
"USD"];
452 auto const usdOffer = USD(1000);
453 auto const xrpOffer =
XRP(1000);
457 Env env{*
this, features};
459 env.fund(
XRP(1000000), gw);
461 auto const f = env.current()->fees().
base;
462 auto const r =
reserve(env, 0);
464 env.fund(r + f, alice);
475 Env env{*
this, features};
477 env.fund(
XRP(1000000), gw);
479 auto const f = env.current()->fees().
base;
480 auto const r =
reserve(env, 0);
482 auto const usdOffer2 = USD(500);
483 auto const xrpOffer2 =
XRP(500);
485 env.fund(r + f + xrpOffer, bob);
487 env.fund(r + f, alice);
493 balance(alice, r - f + xrpOffer2),
505 Env env{*
this, features};
507 env.fund(
XRP(1000000), gw);
509 auto const f = env.current()->fees().
base;
510 auto const r =
reserve(env, 0);
512 auto const usdOffer2 = USD(500);
513 auto const xrpOffer2 =
XRP(500);
515 env.fund(r + f + xrpOffer, bob, carol);
519 env.fund(r + f, alice);
525 balance(alice, r - f + xrpOffer),
546 if (sle->getType() == ltOFFER)
547 result.push_back(sle);
555 testcase(
"Fill Modes");
559 auto const startBalance =
XRP(1000000);
560 auto const gw =
Account{
"gateway"};
561 auto const alice =
Account{
"alice"};
562 auto const bob =
Account{
"bob"};
563 auto const USD = gw[
"USD"];
571 for (
auto const tweakedFeatures :
574 Env env{*
this, tweakedFeatures};
576 auto const f = env.
current()->fees().base;
578 env.fund(startBalance, gw, alice, bob);
581 env(offer(bob, USD(500),
XRP(500)),
599 TER const killedCode{
602 env(offer(alice,
XRP(1000), USD(1000)),
607 balance(alice, startBalance - (f * 2)),
611 balance(bob, startBalance - (f * 2)),
617 env(offer(alice,
XRP(500), USD(500)),
622 balance(alice, startBalance - (f * 3) +
XRP(500)),
626 balance(bob, startBalance - (f * 2) -
XRP(500)),
635 Env env{*
this, features};
637 auto const f = env.current()->fees().
base;
639 env.fund(startBalance, gw, alice, bob);
645 env(offer(alice,
XRP(1000), USD(1000)),
650 balance(alice, startBalance - f - f),
657 env(offer(alice,
XRP(1000), USD(1000)),
662 balance(alice, startBalance - f - f - f +
XRP(50)),
673 env(offer(alice,
XRP(50), USD(50)),
678 balance(alice, startBalance - f - f - f - f +
XRP(100)),
682 balance(bob, startBalance - f - f -
XRP(100)),
690 Env env(*
this, features);
692 env.
fund(startBalance, gw, alice, bob);
695 env(
trust(bob, USD(1000)));
698 env(
pay(gw, bob, USD(1000)));
701 env(offer(alice, USD(1000),
XRP(2000)));
705 BEAST_EXPECT(aliceOffers.size() == 1);
706 for (
auto offerPtr : aliceOffers)
708 auto const& offer = *offerPtr;
720 BEAST_EXPECT(bobOffers.size() == 1);
721 for (
auto offerPtr : bobOffers)
723 auto const& offer = *offerPtr;
729 env(offer(gw,
XRP(2000), USD(1000)));
735 env(offer(gw, USD(1000),
XRP(2000)));
743 Env env(*
this, features);
745 env.
fund(startBalance, gw,
"alice",
"bob");
748 env(
trust(
"bob", USD(1000)));
751 env(
pay(gw,
"bob", USD(1000)));
752 env(offer(
"alice", USD(500),
XRP(1001)));
755 env(offer(
"alice", USD(500),
XRP(1000)));
759 BEAST_EXPECT(aliceOffers.size() == 2);
769 BEAST_EXPECT(bobOffers.size() == 1);
770 for (
auto offerPtr : bobOffers)
772 auto const& offer = *offerPtr;
782 testcase(
"Malformed Detection");
786 auto const startBalance =
XRP(1000000);
787 auto const gw =
Account{
"gateway"};
788 auto const alice =
Account{
"alice"};
789 auto const USD = gw[
"USD"];
791 Env env{*
this, features};
793 env.fund(startBalance, gw, alice);
796 env(offer(alice, USD(1000),
XRP(1000)),
803 env(offer(alice, USD(1000),
XRP(1000)),
833 env(offer(alice, USD(1000),
XRP(1000)),
841 env(offer(alice, USD(1000),
XRP(1000)),
859 testcase(
"Offer Expiration");
863 auto const gw =
Account{
"gateway"};
864 auto const alice =
Account{
"alice"};
865 auto const bob =
Account{
"bob"};
866 auto const USD = gw[
"USD"];
868 auto const startBalance =
XRP(1000000);
869 auto const usdOffer = USD(1000);
870 auto const xrpOffer =
XRP(1000);
872 Env env{*
this, features};
874 env.fund(startBalance, gw, alice, bob);
877 auto const f = env.current()->fees().
base;
883 balance(alice, startBalance - f),
892 env(offer(alice, xrpOffer, usdOffer),
897 balance(alice, startBalance - f - f),
904 env(offer(alice, xrpOffer, usdOffer),
908 balance(alice, startBalance - f - f - f),
916 balance(alice, startBalance - f - f - f),
924 balance(alice, startBalance - f - f - f),
928 balance(bob, startBalance - f),
937 testcase(
"Unfunded Crossing");
941 auto const gw =
Account{
"gateway"};
942 auto const USD = gw[
"USD"];
944 auto const usdOffer = USD(1000);
945 auto const xrpOffer =
XRP(1000);
947 Env env{*
this, features};
949 env.fund(
XRP(1000000), gw);
952 auto const f = env.current()->fees().
base;
956 env.fund(
reserve(env, 0),
"alice");
962 env.fund(
reserve(env, 0) + f,
"bob");
969 env.fund(
reserve(env, 0) + f +
XRP(1),
"carol");
976 env.fund(
reserve(env, 1) + f,
"dan");
982 env.fund(
reserve(env, 1) + f + xrpOffer,
"eve");
993 (use_partner ?
", with partner account" :
""));
997 auto const gw =
Account{
"gateway"};
998 auto const partner =
Account{
"partner"};
999 auto const USD = gw[
"USD"];
1000 auto const BTC = gw[
"BTC"];
1002 Env env{*
this, features};
1005 env.fund(
XRP(10000), gw);
1008 env.fund(
XRP(10000), partner);
1009 env(
trust(partner, USD(100)));
1010 env(
trust(partner, BTC(500)));
1011 env(
pay(gw, partner, USD(100)));
1012 env(
pay(gw, partner, BTC(500)));
1014 auto const& account_to_test = use_partner ? partner : gw;
1017 env.require(
offers(account_to_test, 0));
1022 env(offer(account_to_test, BTC(250),
XRP(1000)));
1023 env.require(
offers(account_to_test, 1));
1026 BEAST_EXPECT(
isOffer(env, account_to_test, BTC(250),
XRP(1000)));
1028 auto const secondLegSeq = env.seq(account_to_test);
1029 env(offer(account_to_test,
XRP(1000), USD(50)));
1030 env.require(
offers(account_to_test, 2));
1033 BEAST_EXPECT(
isOffer(env, account_to_test,
XRP(1000), USD(50)));
1037 env(offer(account_to_test, USD(50), BTC(250)));
1040 BEAST_EXPECT(jrr[jss::offers].isArray());
1041 BEAST_EXPECT(jrr[jss::offers].size() == 0);
1044 BEAST_EXPECT(jrr[jss::offers].isArray());
1045 BEAST_EXPECT(jrr[jss::offers].size() == 0);
1056 bool const noStaleOffers{
1060 BEAST_EXPECT(acctOffers.size() == (noStaleOffers ? 0 : 1));
1061 for (
auto const& offerPtr : acctOffers)
1063 auto const& offer = *offerPtr;
1074 cancelOffer[jss::Account] = account_to_test.human();
1075 cancelOffer[jss::OfferSequence] = secondLegSeq;
1076 cancelOffer[jss::TransactionType] = jss::OfferCancel;
1078 env.require(
offers(account_to_test, 0));
1083 env(offer(account_to_test, BTC(250), USD(50)));
1084 env.require(
offers(account_to_test, 1));
1088 BEAST_EXPECT(
isOffer(env, account_to_test, BTC(250), USD(50)));
1091 BEAST_EXPECT(jrr[jss::offers].isArray());
1092 BEAST_EXPECT(jrr[jss::offers].size() == 0);
1096 env(offer(account_to_test, USD(50), BTC(250)));
1097 env.require(
offers(account_to_test, 1));
1102 BEAST_EXPECT(jrr[jss::offers].isArray());
1103 BEAST_EXPECT(jrr[jss::offers].size() == 0);
1105 BEAST_EXPECT(
isOffer(env, account_to_test, USD(50), BTC(250)));
1113 testcase(
"Negative Balance");
1115 using namespace jtx;
1117 Env env{*
this, features};
1119 auto const gw =
Account{
"gateway"};
1120 auto const alice =
Account{
"alice"};
1121 auto const bob =
Account{
"bob"};
1122 auto const USD = gw[
"USD"];
1123 auto const BTC = gw[
"BTC"];
1127 auto const gw_initial_balance =
drops(1149999730);
1128 auto const alice_initial_balance =
drops(499946999680);
1129 auto const bob_initial_balance =
drops(10199999920);
1130 auto const small_amount =
1131 STAmount{bob[
"USD"].
issue(), UINT64_C(2710505431213761), -33};
1133 env.fund(gw_initial_balance, gw);
1134 env.fund(alice_initial_balance, alice);
1135 env.fund(bob_initial_balance, bob);
1137 env(
rate(gw, 1.005));
1139 env(
trust(alice, USD(500)));
1140 env(
trust(bob, USD(50)));
1141 env(
trust(gw, alice[
"USD"](100)));
1143 env(
pay(gw, alice, alice[
"USD"](50)));
1144 env(
pay(gw, bob, small_amount));
1146 env(offer(alice, USD(50),
XRP(150000)));
1149 env(
pay(alice, gw, USD(100)));
1152 env(
trust(gw, alice[
"USD"](0)));
1161 "-2710505431213761e-33");
1164 env(offer(bob,
XRP(2000), USD(1)));
1173 auto const crossingDelta =
1180 alice_initial_balance - env.current()->fees().base * 3 -
1187 bob_initial_balance - env.current()->fees().base * 2 +
1196 (reverse_order ?
"Reverse" :
"Normal") +
" order");
1198 using namespace jtx;
1200 Env env{*
this, features};
1202 auto const gw =
Account{
"gateway"};
1203 auto const alice =
Account{
"alice"};
1204 auto const bob =
Account{
"bob"};
1205 auto const USD = gw[
"USD"];
1207 env.fund(
XRP(10000), gw, alice, bob);
1209 env(
trust(alice, USD(1000)));
1210 env(
trust(bob, USD(1000)));
1212 env(
pay(gw, alice, alice[
"USD"](500)));
1215 env(offer(bob, USD(1),
XRP(4000)));
1217 env(offer(alice,
XRP(150000), USD(50)));
1220 env(offer(bob, USD(1),
XRP(4000)));
1232 env.current()->fees().base * 2)
1241 env.current()->fees().base * 2)
1248 testcase(
"Offer Crossing with Limit Override");
1250 using namespace jtx;
1252 Env env{*
this, features};
1254 auto const gw =
Account{
"gateway"};
1255 auto const alice =
Account{
"alice"};
1256 auto const bob =
Account{
"bob"};
1257 auto const USD = gw[
"USD"];
1259 env.fund(
XRP(100000), gw, alice, bob);
1261 env(
trust(alice, USD(1000)));
1263 env(
pay(gw, alice, alice[
"USD"](500)));
1265 env(offer(alice,
XRP(150000), USD(50)));
1266 env(offer(bob, USD(1),
XRP(3000)));
1288 testcase(
"Offer Accept then Cancel.");
1290 using namespace jtx;
1292 Env env{*
this, features};
1294 auto const USD = env.master[
"USD"];
1296 auto const nextOfferSeq = env.seq(env.master);
1297 env(offer(env.master,
XRP(500), USD(100)));
1301 cancelOffer[jss::Account] = env.master.human();
1302 cancelOffer[jss::OfferSequence] = nextOfferSeq;
1303 cancelOffer[jss::TransactionType] = jss::OfferCancel;
1305 BEAST_EXPECT(env.seq(env.master) == nextOfferSeq + 2);
1310 BEAST_EXPECT(env.seq(env.master) == nextOfferSeq + 2);
1316 testcase(
"Offer Cancel Past and Future Sequence.");
1318 using namespace jtx;
1320 Env env{*
this, features};
1322 auto const alice =
Account{
"alice"};
1324 auto const nextOfferSeq = env.seq(env.master);
1325 env.fund(
XRP(10000), alice);
1328 cancelOffer[jss::Account] = env.master.human();
1329 cancelOffer[jss::OfferSequence] = nextOfferSeq;
1330 cancelOffer[jss::TransactionType] = jss::OfferCancel;
1333 cancelOffer[jss::OfferSequence] = env.seq(env.master);
1336 cancelOffer[jss::OfferSequence] = env.seq(env.master) + 1;
1346 testcase(
"Currency Conversion: Entire Offer");
1348 using namespace jtx;
1350 Env env{*
this, features};
1352 auto const gw =
Account{
"gateway"};
1353 auto const alice =
Account{
"alice"};
1354 auto const bob =
Account{
"bob"};
1355 auto const USD = gw[
"USD"];
1357 env.fund(
XRP(10000), gw, alice, bob);
1358 env.require(
owners(bob, 0));
1360 env(
trust(alice, USD(100)));
1361 env(
trust(bob, USD(1000)));
1365 env(
pay(gw, alice, alice[
"USD"](100)));
1366 auto const bobOfferSeq = env.seq(bob);
1367 env(offer(bob, USD(100),
XRP(500)));
1372 jro[jss::node][jss::TakerGets] ==
XRP(500).value().getText());
1374 jro[jss::node][jss::TakerPays] ==
1391 BEAST_EXPECT(jro[jss::error] ==
"entryNotFound");
1399 testcase(
"Currency Conversion: Offerer Into Debt");
1401 using namespace jtx;
1403 Env env{*
this, features};
1405 auto const alice =
Account{
"alice"};
1406 auto const bob =
Account{
"bob"};
1407 auto const carol =
Account{
"carol"};
1409 env.fund(
XRP(10000), alice, bob, carol);
1411 env(
trust(alice, carol[
"EUR"](2000)));
1412 env(
trust(bob, alice[
"USD"](100)));
1413 env(
trust(carol, bob[
"EUR"](1000)));
1415 auto const bobOfferSeq = env.seq(bob);
1416 env(offer(bob, alice[
"USD"](50), carol[
"EUR"](200)),
1419 env(offer(alice, carol[
"EUR"](200), alice[
"USD"](50)));
1422 BEAST_EXPECT(jro[jss::error] ==
"entryNotFound");
1428 testcase(
"Currency Conversion: In Parts");
1430 using namespace jtx;
1432 Env env{*
this, features};
1434 auto const gw =
Account{
"gateway"};
1435 auto const alice =
Account{
"alice"};
1436 auto const bob =
Account{
"bob"};
1437 auto const USD = gw[
"USD"];
1439 env.fund(
XRP(10000), gw, alice, bob);
1441 env(
trust(alice, USD(200)));
1442 env(
trust(bob, USD(1000)));
1444 env(
pay(gw, alice, alice[
"USD"](200)));
1446 auto const bobOfferSeq = env.seq(bob);
1447 env(offer(bob, USD(100),
XRP(500)));
1454 jro[jss::node][jss::TakerGets] ==
XRP(300).value().getText());
1456 jro[jss::node][jss::TakerPays] ==
1476 env(
pay(alice, alice,
XRP(600)),
1482 env(
pay(alice, alice,
XRP(600)),
1488 BEAST_EXPECT(jro[jss::error] ==
"entryNotFound");
1501 env.current()->fees().base * 4)
1513 testcase(
"Cross Currency Payment: Start with XRP");
1515 using namespace jtx;
1517 Env env{*
this, features};
1519 auto const gw =
Account{
"gateway"};
1520 auto const alice =
Account{
"alice"};
1521 auto const bob =
Account{
"bob"};
1522 auto const carol =
Account{
"carol"};
1523 auto const USD = gw[
"USD"];
1525 env.fund(
XRP(10000), gw, alice, bob, carol);
1527 env(
trust(carol, USD(1000)));
1528 env(
trust(bob, USD(2000)));
1530 env(
pay(gw, carol, carol[
"USD"](500)));
1532 auto const carolOfferSeq = env.seq(carol);
1533 env(offer(carol,
XRP(500), USD(50)));
1545 jro[jss::node][jss::TakerGets] ==
1548 jro[jss::node][jss::TakerPays] ==
XRP(250).value().getText());
1554 testcase(
"Cross Currency Payment: End with XRP");
1556 using namespace jtx;
1558 Env env{*
this, features};
1560 auto const gw =
Account{
"gateway"};
1561 auto const alice =
Account{
"alice"};
1562 auto const bob =
Account{
"bob"};
1563 auto const carol =
Account{
"carol"};
1564 auto const USD = gw[
"USD"];
1566 env.fund(
XRP(10000), gw, alice, bob, carol);
1568 env(
trust(alice, USD(1000)));
1569 env(
trust(carol, USD(2000)));
1571 env(
pay(gw, alice, alice[
"USD"](500)));
1573 auto const carolOfferSeq = env.seq(carol);
1574 env(offer(carol, USD(50),
XRP(500)));
1588 XRP(10000).value().mantissa() +
XRP(250).value().mantissa()));
1592 jro[jss::node][jss::TakerGets] ==
XRP(250).value().getText());
1594 jro[jss::node][jss::TakerPays] ==
1601 testcase(
"Cross Currency Payment: Bridged");
1603 using namespace jtx;
1605 Env env{*
this, features};
1607 auto const gw1 =
Account{
"gateway_1"};
1608 auto const gw2 =
Account{
"gateway_2"};
1609 auto const alice =
Account{
"alice"};
1610 auto const bob =
Account{
"bob"};
1611 auto const carol =
Account{
"carol"};
1612 auto const dan =
Account{
"dan"};
1613 auto const USD = gw1[
"USD"];
1614 auto const EUR = gw2[
"EUR"];
1616 env.fund(
XRP(10000), gw1, gw2, alice, bob, carol, dan);
1618 env(
trust(alice, USD(1000)));
1619 env(
trust(bob, EUR(1000)));
1620 env(
trust(carol, USD(1000)));
1621 env(
trust(dan, EUR(1000)));
1623 env(
pay(gw1, alice, alice[
"USD"](500)));
1624 env(
pay(gw2, dan, dan[
"EUR"](400)));
1626 auto const carolOfferSeq = env.seq(carol);
1627 env(offer(carol, USD(50),
XRP(500)));
1629 auto const danOfferSeq = env.seq(dan);
1630 env(offer(dan,
XRP(500), EUR(50)));
1633 jtp[0u][0u][jss::currency] =
"XRP";
1634 env(
pay(alice, bob, EUR(30)),
json(jss::Paths, jtp),
sendmax(USD(333)));
1650 jro[jss::node][jss::TakerGets] ==
XRP(200).value().getText());
1652 jro[jss::node][jss::TakerPays] ==
1657 jro[jss::node][jss::TakerGets] ==
1660 jro[jss::node][jss::TakerPays] ==
XRP(200).value().getText());
1669 testcase(
"Auto Bridged Second Leg Dry");
1671 using namespace jtx;
1672 Env env(*
this, features);
1678 auto const USD = gw[
"USD"];
1679 auto const EUR = gw[
"EUR"];
1681 env.
fund(
XRP(100000000), alice, bob, carol, gw);
1683 env.
trust(USD(10), alice);
1685 env(
pay(gw, alice, USD(10)));
1686 env.
trust(USD(10), carol);
1688 env(
pay(gw, carol, USD(3)));
1690 env(offer(alice, EUR(2),
XRP(1)));
1691 env(offer(alice, EUR(2),
XRP(1)));
1693 env(offer(alice,
XRP(1), USD(4)));
1694 env(offer(carol,
XRP(1), USD(3)));
1705 env.
trust(EUR(10), bob);
1707 env(
pay(gw, bob, EUR(10)));
1709 env(offer(bob, USD(10), EUR(10)));
1726 int const emptyOfferCount{
1738 testcase(
"Offer Fees Consume Funds");
1740 using namespace jtx;
1742 Env env{*
this, features};
1744 auto const gw1 =
Account{
"gateway_1"};
1745 auto const gw2 =
Account{
"gateway_2"};
1746 auto const gw3 =
Account{
"gateway_3"};
1747 auto const alice =
Account{
"alice"};
1748 auto const bob =
Account{
"bob"};
1749 auto const USD1 = gw1[
"USD"];
1750 auto const USD2 = gw2[
"USD"];
1751 auto const USD3 = gw3[
"USD"];
1759 auto const starting_xrp =
XRP(100) +
1760 env.current()->fees().accountReserve(3) +
1761 env.current()->fees().base * 4;
1763 env.fund(starting_xrp, gw1, gw2, gw3, alice, bob);
1765 env(
trust(alice, USD1(1000)));
1766 env(
trust(alice, USD2(1000)));
1767 env(
trust(alice, USD3(1000)));
1768 env(
trust(bob, USD1(1000)));
1769 env(
trust(bob, USD2(1000)));
1771 env(
pay(gw1, bob, bob[
"USD"](500)));
1773 env(offer(bob,
XRP(200), USD1(200)));
1776 env(offer(alice, USD1(200),
XRP(200)));
1791 testcase(
"Offer Create, then Cross");
1793 using namespace jtx;
1795 Env env{*
this, features};
1797 auto const gw =
Account{
"gateway"};
1798 auto const alice =
Account{
"alice"};
1799 auto const bob =
Account{
"bob"};
1800 auto const USD = gw[
"USD"];
1802 env.fund(
XRP(10000), gw, alice, bob);
1804 env(
rate(gw, 1.005));
1806 env(
trust(alice, USD(1000)));
1807 env(
trust(bob, USD(1000)));
1808 env(
trust(gw, alice[
"USD"](50)));
1810 env(
pay(gw, bob, bob[
"USD"](1)));
1811 env(
pay(alice, gw, USD(50)));
1813 env(
trust(gw, alice[
"USD"](0)));
1815 env(offer(alice, USD(50),
XRP(150000)));
1816 env(offer(bob,
XRP(100), USD(0.1)));
1821 "49.96666666666667");
1825 "-0.966500000033334");
1831 testcase(
"Offer tfSell: Basic Sell");
1833 using namespace jtx;
1835 Env env{*
this, features};
1837 auto const gw =
Account{
"gateway"};
1838 auto const alice =
Account{
"alice"};
1839 auto const bob =
Account{
"bob"};
1840 auto const USD = gw[
"USD"];
1842 auto const starting_xrp =
XRP(100) +
1843 env.current()->fees().accountReserve(1) +
1844 env.current()->fees().base * 2;
1846 env.fund(starting_xrp, gw, alice, bob);
1848 env(
trust(alice, USD(1000)));
1849 env(
trust(bob, USD(1000)));
1851 env(
pay(gw, bob, bob[
"USD"](500)));
1853 env(offer(bob,
XRP(200), USD(200)),
json(jss::Flags,
tfSell));
1857 env(offer(alice, USD(200),
XRP(200)),
json(jss::Flags,
tfSell));
1872 testcase(
"Offer tfSell: 2x Sell Exceed Limit");
1874 using namespace jtx;
1876 Env env{*
this, features};
1878 auto const gw =
Account{
"gateway"};
1879 auto const alice =
Account{
"alice"};
1880 auto const bob =
Account{
"bob"};
1881 auto const USD = gw[
"USD"];
1883 auto const starting_xrp =
XRP(100) +
1884 env.current()->fees().accountReserve(1) +
1885 env.current()->fees().base * 2;
1887 env.fund(starting_xrp, gw, alice, bob);
1889 env(
trust(alice, USD(150)));
1890 env(
trust(bob, USD(1000)));
1892 env(
pay(gw, bob, bob[
"USD"](500)));
1894 env(offer(bob,
XRP(100), USD(200)));
1900 env(offer(alice, USD(100),
XRP(100)),
json(jss::Flags,
tfSell));
1915 testcase(
"Client Issue #535: Gateway Cross Currency");
1917 using namespace jtx;
1919 Env env{*
this, features};
1921 auto const gw =
Account{
"gateway"};
1922 auto const alice =
Account{
"alice"};
1923 auto const bob =
Account{
"bob"};
1924 auto const XTS = gw[
"XTS"];
1925 auto const XXX = gw[
"XXX"];
1927 auto const starting_xrp =
XRP(100.1) +
1928 env.current()->fees().accountReserve(1) +
1929 env.current()->fees().base * 2;
1931 env.fund(starting_xrp, gw, alice, bob);
1933 env(
trust(alice, XTS(1000)));
1934 env(
trust(alice, XXX(1000)));
1935 env(
trust(bob, XTS(1000)));
1936 env(
trust(bob, XXX(1000)));
1938 env(
pay(gw, alice, alice[
"XTS"](100)));
1939 env(
pay(gw, alice, alice[
"XXX"](100)));
1940 env(
pay(gw, bob, bob[
"XTS"](100)));
1941 env(
pay(gw, bob, bob[
"XXX"](100)));
1943 env(offer(alice, XTS(100), XXX(100)));
1950 payment[jss::id] = env.seq(bob);
1951 payment[jss::build_path] =
true;
1952 payment[jss::tx_json] =
pay(bob, bob, bob[
"XXX"](1));
1953 payment[jss::tx_json][jss::Sequence] =
1957 payment[jss::tx_json][jss::Fee] =
to_string(env.current()->fees().base);
1958 payment[jss::tx_json][jss::SendMax] =
1960 auto jrr = wsc->invoke(
"submit", payment);
1961 BEAST_EXPECT(jrr[jss::status] ==
"success");
1962 BEAST_EXPECT(jrr[jss::result][jss::engine_result] ==
"tesSUCCESS");
1963 if (wsc->version() == 2)
1966 jrr.isMember(jss::jsonrpc) && jrr[jss::jsonrpc] ==
"2.0");
1968 jrr.isMember(jss::ripplerpc) && jrr[jss::ripplerpc] ==
"2.0");
1969 BEAST_EXPECT(jrr.isMember(jss::id) && jrr[jss::id] == 5);
1995 auto const sleTrust =
1997 BEAST_EXPECT(sleTrust);
2001 bool const accountLow = account.id() < issue.
account;
2006 low.setIssuer(accountLow ? account.id() : issue.
account);
2007 high.setIssuer(accountLow ? issue.
account : account.id());
2009 BEAST_EXPECT(sleTrust->getFieldAmount(
sfLowLimit) == low);
2010 BEAST_EXPECT(sleTrust->getFieldAmount(
sfHighLimit) == high);
2016 BEAST_EXPECT(actualBalance == expectBalance);
2026 testcase(
"Partial Crossing");
2028 using namespace jtx;
2030 auto const gw =
Account(
"gateway");
2031 auto const USD = gw[
"USD"];
2033 Env env{*
this, features};
2035 env.fund(
XRP(10000000), gw);
2038 auto const f = env.current()->fees().
base;
2041 enum preTrustType { noPreTrust, gwPreTrust, acctPreTrust };
2047 preTrustType preTrust;
2056 TestData
const tests[]{
2440 for (
auto const& t : tests)
2442 auto const acct =
Account(t.account);
2443 env.fund(t.fundXrp, acct);
2447 env.require(
offers(gw, 0));
2450 auto const book = t.bookAmount;
2452 env(offer(gw,
XRP(book), USD(book)));
2457 if (t.preTrust == gwPreTrust)
2458 env(
trust(gw, acct[
"USD"](1)));
2463 if (t.preTrust == acctPreTrust)
2464 env(
trust(acct, USD(1)));
2470 auto const acctOffer = t.offerAmount;
2471 env(offer(acct, USD(acctOffer),
XRP(acctOffer)),
ter(t.tec));
2476 BEAST_EXPECT(env.balance(acct, USD.issue()) == t.balanceUsd);
2478 env.balance(acct,
xrpIssue()) == t.fundXrp - t.spentXrp);
2479 env.require(
offers(acct, t.offers));
2480 env.require(
owners(acct, t.owners));
2483 BEAST_EXPECT(acctOffers.size() == t.offers);
2484 if (acctOffers.size() && t.offers)
2486 auto const& acctOffer = *(acctOffers.front());
2488 auto const leftover = t.offerAmount - t.bookAmount;
2490 BEAST_EXPECT(acctOffer[
sfTakerPays] == USD(leftover));
2493 if (t.preTrust == noPreTrust)
2495 if (t.balanceUsd.value().signum())
2503 auto const sleTrust =
2505 BEAST_EXPECT(!sleTrust);
2520 testcase(
"XRP Direct Crossing");
2522 using namespace jtx;
2524 auto const gw =
Account(
"gateway");
2525 auto const alice =
Account(
"alice");
2526 auto const bob =
Account(
"bob");
2527 auto const USD = gw[
"USD"];
2529 auto const usdOffer = USD(1000);
2530 auto const xrpOffer =
XRP(1000);
2532 Env env{*
this, features};
2534 env.fund(
XRP(1000000), gw, bob);
2538 auto const fee = env.current()->fees().base;
2545 env(
trust(alice, usdOffer));
2549 env(
pay(gw, alice, usdOffer));
2556 auto const alicesXRP = env.balance(alice);
2557 auto const bobsXRP = env.balance(bob);
2559 env(offer(alice, xrpOffer, usdOffer));
2561 env(offer(bob, usdOffer, xrpOffer));
2575 env(offer(alice, USD(999),
XRP(999)));
2576 env(offer(bob, xrpOffer, usdOffer));
2579 env.require(
balance(alice, USD(999)));
2580 env.require(
balance(bob, USD(1)));
2581 env.require(
offers(alice, 0));
2585 BEAST_EXPECT(bobsOffers.size() == 1);
2586 auto const& bobsOffer = *(bobsOffers.front());
2597 testcase(
"Direct Crossing");
2599 using namespace jtx;
2601 auto const gw =
Account(
"gateway");
2602 auto const alice =
Account(
"alice");
2603 auto const bob =
Account(
"bob");
2604 auto const USD = gw[
"USD"];
2605 auto const EUR = gw[
"EUR"];
2607 auto const usdOffer = USD(1000);
2608 auto const eurOffer = EUR(1000);
2610 Env env{*
this, features};
2612 env.fund(
XRP(1000000), gw);
2616 auto const fee = env.current()->fees().base;
2624 env(
trust(alice, usdOffer));
2625 env(
trust(bob, eurOffer));
2628 env(
pay(gw, alice, usdOffer));
2629 env(
pay(gw, bob, eurOffer));
2637 env(offer(alice, eurOffer, usdOffer));
2638 env(offer(bob, usdOffer, eurOffer));
2655 env(offer(bob, eurOffer, usdOffer));
2658 env(offer(alice, USD(999), eurOffer));
2661 env.require(
offers(alice, 0));
2662 env.require(
offers(bob, 1));
2664 env.require(
balance(alice, USD(999)));
2665 env.require(
balance(alice, EUR(1)));
2666 env.require(
balance(bob, USD(1)));
2667 env.require(
balance(bob, EUR(999)));
2671 if (BEAST_EXPECT(bobsOffers.size() == 1))
2673 auto const& bobsOffer = *(bobsOffers.front());
2681 env(offer(alice, USD(1), EUR(1)));
2684 env.require(
balance(alice, USD(1000)));
2687 env.require(
balance(bob, EUR(1000)));
2688 env.require(
offers(alice, 0));
2689 env.require(
offers(bob, 0));
2692 BEAST_EXPECT(!env.le(
keylet::line(alice.id(), EUR.issue())));
2693 BEAST_EXPECT(!env.le(
keylet::line(bob.id(), USD.issue())));
2697 env(offer(alice, EUR(999), usdOffer));
2700 env(offer(bob, usdOffer, eurOffer));
2703 env.require(
offers(alice, 0));
2704 env.require(
offers(bob, 0));
2706 env.require(
balance(alice, USD(0)));
2707 env.require(
balance(alice, EUR(999)));
2708 env.require(
balance(bob, USD(1000)));
2709 env.require(
balance(bob, EUR(1)));
2715 testcase(
"Bridged Crossing");
2717 using namespace jtx;
2719 auto const gw =
Account(
"gateway");
2720 auto const alice =
Account(
"alice");
2721 auto const bob =
Account(
"bob");
2722 auto const carol =
Account(
"carol");
2723 auto const USD = gw[
"USD"];
2724 auto const EUR = gw[
"EUR"];
2726 auto const usdOffer = USD(1000);
2727 auto const eurOffer = EUR(1000);
2729 Env env{*
this, features};
2731 env.fund(
XRP(1000000), gw, alice, bob, carol);
2734 env(
trust(alice, usdOffer));
2735 env(
trust(carol, eurOffer));
2737 env(
pay(gw, alice, usdOffer));
2738 env(
pay(gw, carol, eurOffer));
2747 env(offer(alice,
XRP(1000), usdOffer));
2748 env(offer(bob, eurOffer,
XRP(1000)));
2749 auto const bobXrpBalance = env.balance(bob);
2753 env(offer(carol, USD(400), EUR(400)));
2766 BEAST_EXPECT(alicesOffers.size() == 1);
2767 auto const& alicesOffer = *(alicesOffers.front());
2770 BEAST_EXPECT(alicesOffer[
sfTakerGets] == USD(600));
2775 BEAST_EXPECT(bobsOffers.size() == 1);
2776 auto const& bobsOffer = *(bobsOffers.front());
2784 env(offer(carol, USD(600), EUR(600)));
2799 if (alicesOffers.size() != 0)
2801 BEAST_EXPECT(alicesOffers.size() == 1);
2802 auto const& alicesOffer = *(alicesOffers.front());
2816 testcase(
"Sell Offer");
2818 using namespace jtx;
2820 auto const gw =
Account(
"gateway");
2821 auto const USD = gw[
"USD"];
2823 Env env{*
this, features};
2825 env.fund(
XRP(10000000), gw);
2828 auto const f = env.current()->fees().
base;
2831 enum preTrustType { noPreTrust, gwPreTrust, acctPreTrust };
2865 : account(std::move(account_))
2870 , acctGets(acctGets_)
2871 , acctPays(acctPays_)
2873 , spentXrp(spentXrp_)
2874 , finalUsd(finalUsd_)
2877 , takerGets(takerGets_)
2878 , takerPays(takerPays_)
2897 std::move(account_),
2915 TestData
const tests[]{
3112 auto const zeroUsd = USD(0);
3113 for (
auto const& t : tests)
3116 env.require(
offers(gw, 0));
3118 auto const acct =
Account(t.account);
3120 env.fund(t.fundXrp, acct);
3126 if (t.fundUSD != zeroUsd)
3128 env(
trust(acct, t.fundUSD));
3130 env(
pay(gw, acct, t.fundUSD));
3134 env(offer(gw, t.gwGets, t.gwPays));
3139 env(offer(acct, t.acctGets, t.acctPays,
tfSell),
ter(t.tec));
3144 BEAST_EXPECT(env.balance(acct, USD.issue()) == t.finalUsd);
3146 env.balance(acct,
xrpIssue()) == t.fundXrp - t.spentXrp);
3147 env.require(
offers(acct, t.offers));
3148 env.require(
owners(acct, t.owners));
3153 if (acctOffers.size() > 0)
3155 BEAST_EXPECT(acctOffers.size() == 1);
3156 auto const& acctOffer = *(acctOffers.front());
3159 BEAST_EXPECT(acctOffer[
sfTakerGets] == t.takerGets);
3160 BEAST_EXPECT(acctOffer[
sfTakerPays] == t.takerPays);
3177 testcase(
"Combine tfSell with tfFillOrKill");
3179 using namespace jtx;
3181 auto const gw =
Account(
"gateway");
3182 auto const alice =
Account(
"alice");
3183 auto const bob =
Account(
"bob");
3184 auto const USD = gw[
"USD"];
3186 Env env{*
this, features};
3188 env.fund(
XRP(10000000), gw, alice, bob);
3191 TER const killedCode{
3195 env(
trust(bob, USD(200)));
3197 env(
pay(gw, bob, USD(100)));
3199 env(offer(bob,
XRP(2000), USD(20)));
3207 env.require(
offers(alice, 0));
3208 env.require(
balance(bob, USD(100)));
3215 env.require(
balance(alice, USD(20)));
3216 env.require(
offers(alice, 0));
3217 env.require(
balance(bob, USD(80)));
3222 env(offer(bob,
XRP(2000), USD(20)));
3226 env.require(
balance(alice, USD(35)));
3227 env.require(
offers(alice, 0));
3228 env.require(
balance(bob, USD(65)));
3240 env.require(
balance(alice, USD(35)));
3241 env.require(
offers(alice, 0));
3242 env.require(
balance(bob, USD(65)));
3251 env.require(
balance(alice, USD(40)));
3252 env.require(
offers(alice, 0));
3253 env.require(
balance(bob, USD(60)));
3260 testcase(
"Transfer Rate Offer");
3262 using namespace jtx;
3264 auto const gw1 =
Account(
"gateway1");
3265 auto const USD = gw1[
"USD"];
3267 Env env{*
this, features};
3270 auto const fee = env.current()->fees().base;
3272 env.fund(
XRP(100000), gw1);
3275 env(
rate(gw1, 1.25));
3277 auto const ann =
Account(
"ann");
3278 auto const bob =
Account(
"bob");
3282 env(
trust(ann, USD(200)));
3283 env(
trust(bob, USD(200)));
3286 env(
pay(gw1, bob, USD(125)));
3295 env(offer(bob,
XRP(1), USD(100)));
3298 env(offer(ann, USD(100),
XRP(1)));
3301 env.require(
balance(ann, USD(100)));
3303 env.require(
offers(ann, 0));
3305 env.require(
balance(bob, USD(0)));
3307 env.require(
offers(bob, 0));
3312 auto const che =
Account(
"che");
3313 auto const deb =
Account(
"deb");
3317 env(
trust(che, USD(200)));
3318 env(
trust(deb, USD(200)));
3321 env(
pay(gw1, deb, USD(125)));
3324 env(offer(che, USD(100),
XRP(1)));
3327 env(offer(deb,
XRP(1), USD(100)));
3330 env.require(
balance(che, USD(100)));
3332 env.require(
offers(che, 0));
3334 env.require(
balance(deb, USD(0)));
3336 env.require(
offers(deb, 0));
3339 auto const eve =
Account(
"eve");
3340 auto const fyn =
Account(
"fyn");
3342 env.fund(
XRP(20000) + (
fee * 2), eve, fyn);
3345 env(
trust(eve, USD(1000)));
3346 env(
trust(fyn, USD(1000)));
3349 env(
pay(gw1, eve, USD(100)));
3350 env(
pay(gw1, fyn, USD(100)));
3356 env(offer(eve, USD(10),
XRP(4000)));
3360 env(offer(fyn,
XRP(2000), USD(5)));
3363 env.require(
balance(eve, USD(105)));
3366 BEAST_EXPECT(evesOffers.size() == 1);
3367 if (evesOffers.size() != 0)
3369 auto const& evesOffer = *(evesOffers.front());
3376 env.require(
balance(fyn, USD(93.75)));
3378 env.require(
offers(fyn, 0));
3381 auto const gw2 =
Account(
"gateway2");
3382 auto const EUR = gw2[
"EUR"];
3384 env.fund(
XRP(100000), gw2);
3387 env(
rate(gw2, 1.5));
3392 auto const gay =
Account(
"gay");
3393 auto const hal =
Account(
"hal");
3394 env.fund(
reserve(env, 3) + (
fee * 3), gay, hal);
3397 env(
trust(gay, USD(200)));
3398 env(
trust(gay, EUR(200)));
3399 env(
trust(hal, USD(200)));
3400 env(
trust(hal, EUR(200)));
3403 env(
pay(gw1, gay, USD(125)));
3404 env(
pay(gw2, hal, EUR(150)));
3407 env(offer(gay, EUR(100), USD(100)));
3410 env(offer(hal, USD(100), EUR(100)));
3413 env.require(
balance(gay, USD(0)));
3414 env.require(
balance(gay, EUR(100)));
3416 env.require(
offers(gay, 0));
3418 env.require(
balance(hal, USD(100)));
3419 env.require(
balance(hal, EUR(0)));
3421 env.require(
offers(hal, 0));
3425 auto const ivy =
Account(
"ivy");
3426 auto const joe =
Account(
"joe");
3427 env.fund(
reserve(env, 3) + (
fee * 3), ivy, joe);
3436 env(
pay(gw1, ivy, USD(270)),
sendmax(USD(500)));
3437 env(
pay(gw2, joe, EUR(150)),
sendmax(EUR(300)));
3439 env.require(
balance(ivy, USD(300)));
3440 env.require(
balance(joe, EUR(250)));
3442 env(offer(ivy, EUR(100), USD(200)));
3445 env(offer(joe, USD(200), EUR(100)));
3448 env.require(
balance(ivy, USD(50)));
3449 env.require(
balance(ivy, EUR(100)));
3451 env.require(
offers(ivy, 0));
3453 env.require(
balance(joe, USD(200)));
3454 env.require(
balance(joe, EUR(100)));
3456 env.require(
offers(joe, 0));
3460 auto const kim =
Account(
"kim");
3461 auto const K_BUX = kim[
"BUX"];
3462 auto const lex =
Account(
"lex");
3463 auto const meg =
Account(
"meg");
3464 auto const ned =
Account(
"ned");
3465 auto const N_BUX = ned[
"BUX"];
3468 env.fund(
reserve(env, 4) + (
fee * 4), kim, lex, meg, ned);
3471 env(
trust(lex, K_BUX(400)));
3473 env(
trust(meg, N_BUX(100)));
3475 env(
pay(ned, lex, N_BUX(100)));
3477 env.require(
balance(lex, N_BUX(100)));
3479 env(
pay(kim, meg, N_BUX(60)),
path(lex, ned),
sendmax(K_BUX(200)));
3484 env.require(
balance(lex, K_BUX(72)));
3485 env.require(
balance(lex, N_BUX(40)));
3487 env.require(
balance(meg, N_BUX(60)));
3492 env(offer(lex, K_BUX(30), N_BUX(30)));
3495 env(offer(kim, N_BUX(30), K_BUX(30)));
3499 env.require(
balance(kim, N_BUX(30)));
3500 env.require(
balance(lex, K_BUX(102)));
3501 env.require(
balance(lex, N_BUX(10)));
3503 env.require(
balance(meg, N_BUX(60)));
3504 env.require(
balance(ned, K_BUX(-30)));
3509 auto const ova =
Account(
"ova");
3510 auto const pat =
Account(
"pat");
3511 auto const qae =
Account(
"qae");
3512 env.fund(
XRP(2) +
reserve(env, 3) + (
fee * 3), ova, pat, qae);
3518 env(
trust(ova, USD(200)));
3519 env(
trust(ova, EUR(200)));
3520 env(
trust(pat, USD(200)));
3521 env(
trust(pat, EUR(200)));
3522 env(
trust(qae, USD(200)));
3523 env(
trust(qae, EUR(200)));
3526 env(
pay(gw1, ova, USD(125)));
3527 env(
pay(gw2, qae, EUR(150)));
3530 env(offer(ova,
XRP(2), USD(100)));
3531 env(offer(pat, EUR(100),
XRP(2)));
3534 env(offer(qae, USD(100), EUR(100)));
3537 env.require(
balance(ova, USD(0)));
3538 env.require(
balance(ova, EUR(0)));
3543 if (ovasOffers.size() != 0)
3545 BEAST_EXPECT(ovasOffers.size() == 1);
3546 auto const& ovasOffer = *(ovasOffers.front());
3553 env.require(
balance(pat, USD(0)));
3554 env.require(
balance(pat, EUR(100)));
3556 env.require(
offers(pat, 0));
3558 env.require(
balance(qae, USD(100)));
3559 env.require(
balance(qae, EUR(0)));
3561 env.require(
offers(qae, 0));
3582 using namespace jtx;
3584 auto const gw =
Account(
"gateway");
3585 auto const USD = gw[
"USD"];
3587 Env env{*
this, features};
3590 auto const fee = env.current()->fees().base;
3591 auto const startBalance =
XRP(1000000);
3593 env.fund(startBalance + (
fee * 4), gw);
3596 env(offer(gw, USD(60),
XRP(600)));
3598 env(offer(gw, USD(60),
XRP(600)));
3600 env(offer(gw, USD(60),
XRP(600)));
3603 env.require(
owners(gw, 3));
3604 env.require(
balance(gw, startBalance +
fee));
3607 BEAST_EXPECT(gwOffers.size() == 3);
3608 for (
auto const& offerPtr : gwOffers)
3610 auto const& offer = *offerPtr;
3618 env(offer(gw,
XRP(1000), USD(100)));
3620 env.require(
owners(gw, 1));
3621 env.require(
offers(gw, 1));
3622 env.require(
balance(gw, startBalance));
3625 BEAST_EXPECT(gwOffers.size() == 1);
3626 for (
auto const& offerPtr : gwOffers)
3628 auto const& offer = *offerPtr;
3638 using namespace jtx;
3640 auto const gw1 =
Account(
"gateway1");
3641 auto const gw2 =
Account(
"gateway2");
3642 auto const alice =
Account(
"alice");
3643 auto const USD = gw1[
"USD"];
3644 auto const EUR = gw2[
"EUR"];
3646 Env env{*
this, features};
3648 env.fund(
XRP(1000000), gw1, gw2);
3652 auto const f = env.current()->fees().
base;
3665 TestData
const tests[]{
3706 for (
auto const& t : tests)
3708 auto const acct =
Account{t.acct};
3709 env.fund(t.fundXRP, acct);
3712 env(
trust(acct, USD(1000)));
3713 env(
trust(acct, EUR(1000)));
3716 if (t.fundUSD > USD(0))
3717 env(
pay(gw1, acct, t.fundUSD));
3718 if (t.fundEUR > EUR(0))
3719 env(
pay(gw2, acct, t.fundEUR));
3722 env(offer(acct, USD(500), EUR(600)),
ter(t.firstOfferTec));
3726 int offerCount = t.firstOfferTec ==
tesSUCCESS ? 1 : 0;
3727 env.require(
owners(acct, 2 + offerCount));
3728 env.require(
balance(acct, t.fundUSD));
3729 env.require(
balance(acct, t.fundEUR));
3732 BEAST_EXPECT(acctOffers.size() == offerCount);
3733 for (
auto const& offerPtr : acctOffers)
3735 auto const& offer = *offerPtr;
3741 env(offer(acct, EUR(600), USD(500)),
ter(t.secondOfferTec));
3745 offerCount = t.secondOfferTec ==
tesSUCCESS ? 1 : offerCount;
3746 env.require(
owners(acct, 2 + offerCount));
3747 env.require(
balance(acct, t.fundUSD));
3748 env.require(
balance(acct, t.fundEUR));
3751 BEAST_EXPECT(acctOffers.size() == offerCount);
3752 for (
auto const& offerPtr : acctOffers)
3754 auto const& offer = *offerPtr;
3779 testcase(
"Self Cross Offer");
3791 using namespace jtx;
3793 Env env{*
this, features};
3795 auto const alice =
Account(
"alice");
3796 auto const bob =
Account(
"bob");
3797 auto const USD = bob[
"USD"];
3798 auto const f = env.current()->fees().base;
3800 env.fund(
XRP(50000) + f, alice, bob);
3803 env(offer(alice, USD(5000),
XRP(50000)));
3807 env(offer(bob,
XRP(50000), USD(5000)));
3813 env.require(
owners(alice, 1));
3814 env.require(
lines(alice, 1));
3819 BEAST_EXPECT(bobOffers.size() == 1);
3820 for (
auto const& offerPtr : bobOffers)
3822 auto const& offer = *offerPtr;
3835 testcase(
"Bad path assert");
3837 using namespace jtx;
3844 auto const fee = env.current()->fees().base;
3847 auto const ann =
Account(
"ann");
3848 auto const A_BUX = ann[
"BUX"];
3849 auto const bob =
Account(
"bob");
3850 auto const cam =
Account(
"cam");
3851 auto const dan =
Account(
"dan");
3852 auto const D_BUX = dan[
"BUX"];
3855 env.fund(
reserve(env, 4) + (
fee * 4), ann, bob, cam, dan);
3858 env(
trust(bob, A_BUX(400)));
3860 env(
trust(cam, D_BUX(100)));
3862 env(
pay(dan, bob, D_BUX(100)));
3864 env.require(
balance(bob, D_BUX(100)));
3866 env(
pay(ann, cam, D_BUX(60)),
path(bob, dan),
sendmax(A_BUX(200)));
3871 env.require(
balance(bob, A_BUX(72)));
3872 env.require(
balance(bob, D_BUX(40)));
3874 env.require(
balance(cam, D_BUX(60)));
3878 env(offer(bob, A_BUX(30), D_BUX(30)));
3881 env(
trust(ann, D_BUX(100)));
3885 env(
pay(ann, ann, D_BUX(30)),
3892 env.require(
balance(ann, D_BUX(0)));
3893 env.require(
balance(bob, A_BUX(72)));
3894 env.require(
balance(bob, D_BUX(40)));
3896 env.require(
balance(cam, D_BUX(60)));
3897 env.require(
balance(dan, A_BUX(0)));
3909 testcase(
"Direct to Direct path");
3911 using namespace jtx;
3913 Env env{*
this, features};
3915 auto const ann =
Account(
"ann");
3916 auto const bob =
Account(
"bob");
3917 auto const cam =
Account(
"cam");
3918 auto const A_BUX = ann[
"BUX"];
3919 auto const B_BUX = bob[
"BUX"];
3921 auto const fee = env.current()->fees().base;
3922 env.fund(
reserve(env, 4) + (
fee * 5), ann, bob, cam);
3925 env(
trust(ann, B_BUX(40)));
3926 env(
trust(cam, A_BUX(40)));
3927 env(
trust(cam, B_BUX(40)));
3930 env(
pay(ann, cam, A_BUX(35)));
3931 env(
pay(bob, cam, B_BUX(35)));
3933 env(offer(bob, A_BUX(30), B_BUX(30)));
3939 env(offer(cam, A_BUX(29), B_BUX(30),
tfPassive));
3941 env.require(
balance(cam, A_BUX(35)));
3942 env.require(
balance(cam, B_BUX(35)));
3943 env.require(
offers(cam, 1));
3946 env(offer(cam, B_BUX(30), A_BUX(30)));
3949 env.require(
balance(bob, A_BUX(30)));
3950 env.require(
balance(cam, A_BUX(5)));
3951 env.require(
balance(cam, B_BUX(65)));
3952 env.require(
offers(cam, 0));
3961 testcase(
"Self crossing low quality offer");
3963 using namespace jtx;
3965 Env env{*
this, features};
3967 auto const ann =
Account(
"ann");
3968 auto const gw =
Account(
"gateway");
3969 auto const BTC = gw[
"BTC"];
3971 auto const fee = env.current()->fees().base;
3976 env(
rate(gw, 1.002));
3977 env(
trust(ann, BTC(10)));
3980 env(
pay(gw, ann, BTC(2.856)));
3983 env(offer(ann,
drops(365611702030), BTC(5.713)));
3987 env(offer(ann, BTC(0.687),
drops(20000000000)),
3998 testcase(
"Offer In Scaling");
4000 using namespace jtx;
4002 Env env{*
this, features};
4004 auto const gw =
Account(
"gateway");
4005 auto const alice =
Account(
"alice");
4006 auto const bob =
Account(
"bob");
4007 auto const CNY = gw[
"CNY"];
4009 auto const fee = env.current()->fees().base;
4014 env(
trust(bob, CNY(500)));
4017 env(
pay(gw, bob, CNY(300)));
4020 env(offer(bob,
drops(5400000000), CNY(216.054)));
4024 env(offer(alice, CNY(13562.0001),
drops(339000000000)));
4028 BEAST_EXPECT(aliceOffers.size() == 1);
4029 for (
auto const& offerPtr : aliceOffers)
4031 auto const& offer = *offerPtr;
4034 BEAST_EXPECT(offer[
sfTakerPays] == CNY(13345.9461));
4044 testcase(
"Offer In Scaling With Xfer Rate");
4046 using namespace jtx;
4048 Env env{*
this, features};
4050 auto const gw =
Account(
"gateway");
4051 auto const alice =
Account(
"alice");
4052 auto const bob =
Account(
"bob");
4053 auto const BTC = gw[
"BTC"];
4054 auto const JPY = gw[
"JPY"];
4056 auto const fee = env.current()->fees().base;
4061 env(
rate(gw, 1.002));
4062 env(
trust(alice, JPY(4000)));
4063 env(
trust(bob, BTC(2)));
4066 env(
pay(gw, alice, JPY(3699.034802280317)));
4067 env(
pay(gw, bob, BTC(1.156722559140311)));
4070 env(offer(bob, JPY(1241.913390770747), BTC(0.01969825690469254)));
4074 env(offer(alice, BTC(0.05507568706427876), JPY(3472.696773391072)));
4078 BEAST_EXPECT(aliceOffers.size() == 1);
4079 for (
auto const& offerPtr : aliceOffers)
4081 auto const& offer = *offerPtr;
4086 BEAST_EXPECT(offer[
sfTakerPays] == BTC(0.035378));
4096 testcase(
"Offer Threshold With Reduced Funds");
4098 using namespace jtx;
4100 Env env{*
this, features};
4102 auto const gw1 =
Account(
"gw1");
4103 auto const gw2 =
Account(
"gw2");
4104 auto const alice =
Account(
"alice");
4105 auto const bob =
Account(
"bob");
4106 auto const USD = gw1[
"USD"];
4107 auto const JPY = gw2[
"JPY"];
4109 auto const fee = env.current()->fees().base;
4111 env.fund(
reserve(env, 2) + (
fee * 4), gw1, gw2);
4114 env(
rate(gw1, 1.002));
4115 env(
trust(alice, USD(1000)));
4116 env(
trust(bob, JPY(100000)));
4143 BEAST_EXPECT(aliceOffers.size() == 1);
4144 for (
auto const& offerPtr : aliceOffers)
4146 auto const& offer = *offerPtr;
4160 testcase(
"Tiny Offer");
4162 using namespace jtx;
4164 Env env{*
this, features};
4166 auto const gw =
Account(
"gw");
4167 auto const alice =
Account(
"alice");
4168 auto const bob =
Account(
"bob");
4169 auto const CNY = gw[
"CNY"];
4170 auto const fee = env.current()->fees().base;
4171 auto const startXrpBalance =
drops(400000000000) + (
fee * 2);
4173 env.fund(startXrpBalance, gw, alice, bob);
4176 env(
trust(bob, CNY(100000)));
4188 STAmount const bobsCnyStartBalance{
4190 env(
pay(gw, bob, bobsCnyStartBalance));
4199 env.require(
balance(alice, alicesCnyOffer));
4201 env.require(
balance(bob, bobsCnyStartBalance - alicesCnyOffer));
4208 testcase(
"Self Pay Xfer Fee");
4244 using namespace jtx;
4246 Env env{*
this, features};
4248 auto const gw =
Account(
"gw");
4249 auto const BTC = gw[
"BTC"];
4250 auto const USD = gw[
"USD"];
4251 auto const startXrpBalance =
XRP(4000000);
4253 env.fund(startXrpBalance, gw);
4256 env(
rate(gw, 1.25));
4281 TestData
const tests[]{
4289 {{
"ann", 0,
drops(3899999999960), BTC(20.0), USD(3000)},
4290 {
"abe", 0,
drops(4099999999970), BTC(0), USD(750)}}},
4296 {{
"bev", 0,
drops(4099999999960), BTC(7.5), USD(2000)},
4297 {
"bob", 0,
drops(3899999999970), BTC(10), USD(0)}}},
4305 drops(3999999999950),
4315 {{
"eve", 1,
drops(4039999999960), BTC(0.0), USD(2000)},
4316 {
"eli", 1,
drops(3959999999970), BTC(4), USD(0)}}},
4323 for (
auto const& t : tests)
4325 Account const&
self = t.actors[t.self].acct;
4326 Account const& leg0 = t.actors[t.leg0].acct;
4327 Account const& leg1 = t.actors[t.leg1].acct;
4329 for (
auto const& actor : t.actors)
4331 env.fund(
XRP(4000000), actor.acct);
4334 env(
trust(actor.acct, BTC(40)));
4335 env(
trust(actor.acct, USD(8000)));
4339 env(
pay(gw,
self, t.btcStart));
4340 env(
pay(gw,
self, USD(2000)));
4341 if (
self.
id() != leg1.
id())
4342 env(
pay(gw, leg1, USD(2000)));
4356 env(offer(
self, USD(1000), BTC(10)));
4361 for (
auto const& actor : t.actors)
4367 actorOffers.begin(),
4369 actorOffers.begin(),
4372 return (*offer)[sfTakerGets].signum() == 0;
4374 BEAST_EXPECT(offerCount == actor.offers);
4376 env.require(
balance(actor.acct, actor.xrp));
4377 env.require(
balance(actor.acct, actor.btc));
4378 env.require(
balance(actor.acct, actor.usd));
4394 testcase(
"Self Pay Unlimited Funds");
4426 using namespace jtx;
4428 Env env{*
this, features};
4430 auto const gw =
Account(
"gw");
4431 auto const BTC = gw[
"BTC"];
4432 auto const USD = gw[
"USD"];
4433 auto const startXrpBalance =
XRP(4000000);
4435 env.fund(startXrpBalance, gw);
4438 env(
rate(gw, 1.25));
4463 TestData
const takerTests[]{
4471 {{
"deb", 0,
drops(3899999999960), BTC(5), USD(3000)},
4472 {
"dan", 0,
drops(4099999999970), BTC(0), USD(750)}}},
4478 {{
"flo", 0,
drops(3999999999950), BTC(5), USD(2000)}}}
4482 TestData
const flowTests[]{
4490 {{
"gay", 1,
drops(3949999999960), BTC(5), USD(2500)},
4493 drops(4049999999970),
4500 {{
"hye", 2,
drops(3999999999950), BTC(5), USD(2000)}}}
4507 for (
auto const& t : tests)
4509 Account const&
self = t.actors[t.self].acct;
4510 Account const& leg0 = t.actors[t.leg0].acct;
4511 Account const& leg1 = t.actors[t.leg1].acct;
4513 for (
auto const& actor : t.actors)
4515 env.fund(
XRP(4000000), actor.acct);
4518 env(
trust(actor.acct, BTC(40)));
4519 env(
trust(actor.acct, USD(8000)));
4523 env(
pay(gw,
self, t.btcStart));
4524 env(
pay(gw,
self, USD(2000)));
4525 if (
self.
id() != leg1.
id())
4526 env(
pay(gw, leg1, USD(2000)));
4540 env(offer(
self, USD(1000), BTC(10)));
4545 for (
auto const& actor : t.actors)
4551 actorOffers.begin(),
4553 actorOffers.begin(),
4556 return (*offer)[sfTakerGets].signum() == 0;
4558 BEAST_EXPECT(offerCount == actor.offers);
4560 env.require(
balance(actor.acct, actor.xrp));
4561 env.require(
balance(actor.acct, actor.btc));
4562 env.require(
balance(actor.acct, actor.usd));
4578 testcase(
"lsfRequireAuth");
4580 using namespace jtx;
4582 Env env{*
this, features};
4584 auto const gw =
Account(
"gw");
4585 auto const alice =
Account(
"alice");
4586 auto const bob =
Account(
"bob");
4587 auto const gwUSD = gw[
"USD"];
4588 auto const aliceUSD = alice[
"USD"];
4589 auto const bobUSD = bob[
"USD"];
4591 env.fund(
XRP(400000), gw, alice, bob);
4600 env(
trust(bob, gwUSD(100)));
4602 env(
trust(alice, gwUSD(100)));
4604 env(offer(alice, gwUSD(40),
XRP(4000)));
4607 env.require(
offers(alice, 1));
4608 env.require(
balance(alice, gwUSD(0)));
4610 env(
pay(gw, bob, gwUSD(50)));
4613 env.require(
balance(bob, gwUSD(50)));
4616 env(offer(bob,
XRP(4000), gwUSD(40)));
4619 env.require(
offers(alice, 0));
4620 env.require(
balance(alice, gwUSD(40)));
4622 env.require(
offers(bob, 0));
4623 env.require(
balance(bob, gwUSD(10)));
4629 testcase(
"Missing Auth");
4649 using namespace jtx;
4651 Env env{*
this, features};
4653 auto const gw =
Account(
"gw");
4654 auto const alice =
Account(
"alice");
4655 auto const bob =
Account(
"bob");
4656 auto const gwUSD = gw[
"USD"];
4657 auto const aliceUSD = alice[
"USD"];
4658 auto const bobUSD = bob[
"USD"];
4660 env.fund(
XRP(400000), gw, alice, bob);
4663 env(offer(alice, gwUSD(40),
XRP(4000)));
4666 env.require(
offers(alice, 1));
4673 env(
trust(bob, gwUSD(100)));
4676 env(
pay(gw, bob, gwUSD(50)));
4678 env.require(
balance(bob, gwUSD(50)));
4686 env(offer(bob,
XRP(4000), gwUSD(40)));
4692 env.require(
offers(alice, 0));
4697 env.require(
offers(bob, 1));
4698 env.require(
balance(bob, gwUSD(50)));
4703 env.require(
balance(alice, gwUSD(40)));
4704 env.require(
offers(bob, 0));
4705 env.require(
balance(bob, gwUSD(10)));
4717 env.require(
offers(alice, 0));
4720 env.require(
offers(bob, 1));
4721 env.require(
balance(bob, gwUSD(50)));
4725 env(
trust(gw, aliceUSD(100)));
4731 env.require(
offers(alice, 0));
4732 env.require(
balance(alice, gwUSD(0)));
4734 env.require(
offers(bob, 1));
4735 env.require(
balance(bob, gwUSD(50)));
4740 env.require(
offers(bob, 0));
4748 env(offer(alice, gwUSD(40),
XRP(4000)));
4751 env.require(
offers(alice, 1));
4754 env(offer(bob,
XRP(4000), gwUSD(40)));
4757 env.require(
offers(alice, 0));
4758 env.require(
balance(alice, gwUSD(40)));
4760 env.require(
offers(bob, 0));
4761 env.require(
balance(bob, gwUSD(10)));
4767 testcase(
"RippleConnect Smoketest payment flow");
4768 using namespace jtx;
4770 Env env{*
this, features};
4780 auto const hotUS =
Account(
"hotUS");
4781 auto const coldUS =
Account(
"coldUS");
4782 auto const hotEU =
Account(
"hotEU");
4783 auto const coldEU =
Account(
"coldEU");
4784 auto const mm =
Account(
"mm");
4786 auto const USD = coldUS[
"USD"];
4787 auto const EUR = coldEU[
"EUR"];
4789 env.fund(
XRP(100000), hotUS, coldUS, hotEU, coldEU, mm);
4793 for (
auto const& cold : {coldUS, coldEU})
4816 env(
pay(coldUS, hotUS, USD(5000000)));
4817 env(
pay(coldEU, hotEU, EUR(5000000)));
4818 env(
pay(coldUS, mm, USD(5000000)));
4819 env(
pay(coldEU, mm, EUR(5000000)));
4823 float const rate = 0.9f;
4824 env(offer(mm, EUR(4000000 *
rate), USD(4000000)),
4827 float const reverseRate = 1.0f /
rate * 1.00101f;
4828 env(offer(mm, USD(4000000 * reverseRate), EUR(4000000)),
4835 jvParams[jss::destination_account] = coldEU.human();
4836 jvParams[jss::destination_amount][jss::issuer] = coldEU.human();
4837 jvParams[jss::destination_amount][jss::currency] =
"EUR";
4838 jvParams[jss::destination_amount][jss::value] = 10;
4839 jvParams[jss::source_account] = hotUS.human();
4842 "json",
"ripple_path_find",
to_string(jvParams))[jss::result]};
4844 BEAST_EXPECT(jrr[jss::status] ==
"success");
4846 jrr[jss::alternatives].isArray() &&
4847 jrr[jss::alternatives].size() > 0);
4850 env(
pay(hotUS, coldEU, EUR(10)),
sendmax(USD(11.1223326)));
4856 testcase(
"Self Auth");
4858 using namespace jtx;
4860 Env env{*
this, features};
4862 auto const gw =
Account(
"gw");
4863 auto const alice =
Account(
"alice");
4864 auto const gwUSD = gw[
"USD"];
4865 auto const aliceUSD = alice[
"USD"];
4867 env.fund(
XRP(400000), gw, alice);
4871 env(offer(gw, gwUSD(40),
XRP(4000)));
4874 env.require(
offers(gw, 1));
4883 env.require(
offers(gw, 0));
4895 env(offer(gw, gwUSD(40),
XRP(4000)),
4899 env.require(
offers(gw, preauth ? 1 : 0));
4907 env(
trust(alice, gwUSD(100)));
4910 env(
pay(gw, alice, gwUSD(50)));
4913 env.require(
balance(alice, gwUSD(50)));
4916 env(offer(alice,
XRP(4000), gwUSD(40)));
4919 env.require(
offers(alice, 0));
4920 env.require(
balance(alice, gwUSD(10)));
4922 env.require(
offers(gw, 0));
4929 using namespace jtx;
4931 testcase(
"Deleted offer issuer");
4933 auto trustLineExists = [](
jtx::Env const& env,
4944 auto const USD = gw[
"USD"];
4945 auto const BUX = alice[
"BUX"];
4947 Env env{*
this, features};
4950 env.
trust(USD(1000), becky);
4951 env(
pay(gw, becky, USD(5)));
4953 BEAST_EXPECT(trustLineExists(env, gw, becky, USD.currency));
4964 env(
pay(becky, gw, USD(5)));
4965 env.
trust(USD(0), becky);
4967 BEAST_EXPECT(!trustLineExists(env, gw, becky, USD.currency));
4968 BEAST_EXPECT(
isOffer(env, becky,
XRP(2), USD(2)));
4969 BEAST_EXPECT(
isOffer(env, becky, BUX(3), USD(3)));
4976 [&env, &gw, openLedgerSeq = env.
current()->seq()]() ->
int {
4978 if (gwSeq + 255 > openLedgerSeq)
4979 return gwSeq - openLedgerSeq + 255;
4983 for (
int i = 0; i < delta; ++i)
5000 BEAST_EXPECT(
isOffer(env, becky,
XRP(2), USD(2)));
5001 BEAST_EXPECT(
isOffer(env, becky, BUX(3), USD(3)));
5007 BEAST_EXPECT(
isOffer(env, becky,
XRP(2), USD(2)));
5008 BEAST_EXPECT(
isOffer(env, becky, BUX(3), USD(3)));
5013 BEAST_EXPECT(!
isOffer(env, becky, BUX(3), USD(3)));
5017 env.
trust(BUX(1000), carol);
5018 env(
pay(alice, carol, BUX(2)));
5020 env(offer(alice, BUX(2),
XRP(2)));
5027 BEAST_EXPECT(
isOffer(env, alice, BUX(2),
XRP(2)));
5028 BEAST_EXPECT(
isOffer(env, becky,
XRP(2), USD(2)));
5034 testcase(
"Tick Size");
5036 using namespace jtx;
5040 Env env{*
this, features};
5041 auto const gw =
Account{
"gateway"};
5042 env.fund(
XRP(10000), gw);
5044 auto txn =
noop(gw);
5050 BEAST_EXPECT((*env.le(gw))[
sfTickSize] == Quality::minTickSize);
5055 BEAST_EXPECT(!env.le(gw)->isFieldPresent(
sfTickSize));
5060 BEAST_EXPECT((*env.le(gw))[
sfTickSize] == Quality::maxTickSize - 1);
5068 BEAST_EXPECT(!env.le(gw)->isFieldPresent(
sfTickSize));
5071 Env env{*
this, features};
5072 auto const gw =
Account{
"gateway"};
5073 auto const alice =
Account{
"alice"};
5074 auto const XTS = gw[
"XTS"];
5075 auto const XXX = gw[
"XXX"];
5077 env.fund(
XRP(10000), gw, alice);
5081 auto txn =
noop(gw);
5084 BEAST_EXPECT((*env.le(gw))[
sfTickSize] == 5);
5087 env(
trust(alice, XTS(1000)));
5088 env(
trust(alice, XXX(1000)));
5090 env(
pay(gw, alice, alice[
"XTS"](100)));
5091 env(
pay(gw, alice, alice[
"XXX"](100)));
5093 env(offer(alice, XTS(10), XXX(30)));
5094 env(offer(alice, XTS(30), XXX(10)));
5095 env(offer(alice, XTS(10), XXX(30)),
json(jss::Flags,
tfSell));
5096 env(offer(alice, XTS(30), XXX(10)),
json(jss::Flags,
tfSell));
5101 if (sle->getType() == ltOFFER)
5105 (*sle)[sfTakerPays], (*sle)[sfTakerGets]));
5109 auto it =
offers.begin();
5110 BEAST_EXPECT(it !=
offers.end());
5112 it->second.first == XTS(10) && it->second.second < XXX(30) &&
5113 it->second.second > XXX(29.9994));
5117 BEAST_EXPECT(it !=
offers.end());
5119 it->second.first == XTS(30) && it->second.second == XXX(10));
5123 BEAST_EXPECT(it !=
offers.end());
5125 it->second.first == XTS(10.0002) && it->second.second == XXX(30));
5130 BEAST_EXPECT(it !=
offers.end());
5132 it->second.first == XTS(30) && it->second.second == XXX(10));
5134 BEAST_EXPECT(++it ==
offers.end());
5148 return (*rhs)[sfSequence] < (*lhs)[sfSequence];
5156 testcase(
"Ticket Offers");
5158 using namespace jtx;
5166 Env env{*
this, features};
5167 auto const gw =
Account{
"gateway"};
5168 auto const alice =
Account{
"alice"};
5169 auto const bob =
Account{
"bob"};
5170 auto const USD = gw[
"USD"];
5172 env.fund(
XRP(10000), gw, alice, bob);
5175 env(
trust(alice, USD(1000)));
5176 env(
trust(bob, USD(1000)));
5179 env(
pay(gw, alice, USD(200)));
5186 env(offer(alice,
XRP(50), USD(50)));
5191 env(ticket::create(alice, 2));
5196 BEAST_EXPECT(offerId_1 == offerId_0 + 4);
5197 env(offer(alice,
XRP(50), USD(50)));
5213 BEAST_EXPECT(
offers.size() == 4);
5218 env.require(
balance(alice, USD(200)));
5219 env.require(
owners(alice, 5));
5223 env(offer(bob, USD(50),
XRP(50)));
5229 BEAST_EXPECT(
offers.size() == 3);
5236 env(offer(bob, USD(50),
XRP(50)));
5242 BEAST_EXPECT(
offers.size() == 2);
5248 env(offer(bob, USD(50),
XRP(50)));
5254 BEAST_EXPECT(
offers.size() == 1);
5259 env(offer(bob, USD(50),
XRP(50)));
5265 BEAST_EXPECT(
offers.size() == 0);
5267 env.require(
balance(alice, USD(0)));
5268 env.require(
owners(alice, 1));
5269 env.require(
balance(bob, USD(200)));
5270 env.require(
owners(bob, 1));
5276 testcase(
"Ticket Cancel Offers");
5278 using namespace jtx;
5282 Env env{*
this, features};
5283 auto const gw =
Account{
"gateway"};
5284 auto const alice =
Account{
"alice"};
5285 auto const USD = gw[
"USD"];
5287 env.fund(
XRP(10000), gw, alice);
5290 env(
trust(alice, USD(1000)));
5294 env(
pay(gw, alice, USD(200)));
5299 env(offer(alice,
XRP(50), USD(50)));
5305 env(ticket::create(alice, 4));
5311 BEAST_EXPECT(offerSeqId_1 == offerSeqId_0 + 6);
5312 env(offer(alice,
XRP(50), USD(50)));
5328 BEAST_EXPECT(
offers.size() == 4);
5333 env.require(
balance(alice, USD(200)));
5334 env.require(
owners(alice, 7));
5344 BEAST_EXPECT(
offers.size() == 3);
5357 BEAST_EXPECT(
offers.size() == 2);
5372 BEAST_EXPECT(
offers.size() == 1);
5390 testcase(
"false assert");
5391 using namespace jtx;
5394 auto const alice =
Account(
"alice");
5395 auto const USD = alice[
"USD"];
5397 env.fund(
XRP(10000), alice);
5399 env(offer(alice,
XRP(100000000000), USD(100000000)));
5467 using namespace jtx;
5485 using namespace jtx;