2#include <test/jtx/PathSet.h>
3#include <test/jtx/WSClient.h>
5#include <xrpl/protocol/Feature.h>
6#include <xrpl/protocol/Quality.h>
7#include <xrpl/protocol/jss.h>
17 return env.
current()->fees().accountReserve(count);
23 return env.
current()->info().parentCloseTime.time_since_epoch().count();
33 jvParams[jss::offer][jss::account] = acct.
human();
34 jvParams[jss::offer][jss::seq] = offer_seq;
36 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
42 Issue const& taker_pays,
43 Issue const& taker_gets)
46 jvbp[jss::ledger_index] =
"current";
51 return env.
rpc(
"json",
"book_offers",
to_string(jvbp))[jss::result];
58 testcase(
"Incorrect Removal of Funded Offers");
70 Env env{*
this, features};
72 auto const gw =
Account{
"gateway"};
73 auto const USD = gw[
"USD"];
74 auto const BTC = gw[
"BTC"];
79 env.fund(
XRP(10000), alice, bob, carol, gw);
81 env.trust(USD(1000), alice, bob, carol);
82 env.trust(BTC(1000), alice, bob, carol);
84 env(
pay(gw, alice, BTC(1000)));
86 env(
pay(gw, carol, USD(1000)));
87 env(
pay(gw, carol, BTC(1000)));
101 env(
offer(carol, BTC(1), USD(100)));
105 env(
pay(alice, bob, USD(100)),
110 env.require(
balance(bob, USD(100)));
112 !
isOffer(env, carol, BTC(1), USD(100)) &&
119 testcase(
"Removing Canceled Offers");
122 Env env{*
this, features};
124 auto const gw =
Account{
"gateway"};
125 auto const alice =
Account{
"alice"};
126 auto const USD = gw[
"USD"];
128 env.fund(
XRP(10000), alice, gw);
130 env.trust(USD(100), alice);
133 env(
pay(gw, alice, USD(50)));
136 auto const offer1Seq = env.seq(alice);
141 BEAST_EXPECT(
isOffer(env, alice,
XRP(500), USD(100)));
144 auto const offer2Seq = env.seq(alice);
146 env(
offer(alice,
XRP(300), USD(100)),
147 json(jss::OfferSequence, offer1Seq),
158 env(
offer(alice,
XRP(400), USD(200)),
159 json(jss::OfferSequence, offer1Seq),
168 auto const offer4Seq = env.seq(alice);
172 BEAST_EXPECT(
isOffer(env, alice,
XRP(222), USD(111)));
175 BEAST_EXPECT(env.seq(alice) == offer4Seq + 2);
177 BEAST_EXPECT(!
isOffer(env, alice,
XRP(222), USD(111)));
181 env.require(
offers(alice, 2));
185 json(jss::OfferSequence, offer2Seq),
189 env.require(
offers(alice, 2));
190 BEAST_EXPECT(
isOffer(env, alice,
XRP(300), USD(100)));
191 BEAST_EXPECT(!
isOffer(env, alice,
XRP(5), USD(2)));
201 using namespace std::chrono_literals;
202 auto const alice =
Account{
"alice"};
203 auto const bob =
Account{
"bob"};
204 auto const carol =
Account{
"carol"};
207 auto const USD = gw[
"USD"];
208 auto const EUR = gw[
"EUR"];
210 Env env{*
this, features};
212 env.fund(
XRP(10000), alice, bob, carol, gw);
214 env.trust(USD(1000), alice, bob, carol);
215 env.trust(EUR(1000), alice, bob, carol);
216 env(
pay(gw, alice, USD(100)));
217 env(
pay(gw, carol, EUR(100)));
223 for (
int i = 0; i < 101; ++i)
224 env(
offer(carol, USD(1), EUR(2)));
250 using namespace std::chrono_literals;
251 auto const alice =
Account{
"alice"};
252 auto const bob =
Account{
"bob"};
253 auto const carol =
Account{
"carol"};
254 auto const dan =
Account{
"dan"};
255 auto const erin =
Account{
"erin"};
258 auto const USD = gw[
"USD"];
259 Env env{*
this, features};
261 env.fund(
XRP(10000), alice, bob, carol, dan, erin, gw);
263 env.trust(USD(1000), alice, bob, carol, dan, erin);
265 env(
pay(gw, carol, USD(0.99999)));
266 env(
pay(gw, dan, USD(1)));
267 env(
pay(gw, erin, USD(1)));
289 env(
pay(alice, bob, USD(1)),
304 testcase(
"Rm small increased q offers XRP");
312 using namespace std::chrono_literals;
313 auto const alice =
Account{
"alice"};
314 auto const bob =
Account{
"bob"};
315 auto const carol =
Account{
"carol"};
318 auto const USD = gw[
"USD"];
321 for (
auto crossBothOffers : {
false,
true})
323 Env env{*
this, features};
325 env.fund(
XRP(10000), alice, bob, carol, gw);
327 env.trust(USD(1000), alice, bob, carol);
329 auto initialCarolUSD = USD(0.499);
330 env(
pay(gw, carol, initialCarolUSD));
331 env(
pay(gw, bob, USD(100)));
343 auto aliceTakerGets = crossBothOffers ?
drops(2) :
drops(1);
344 env(
offer(alice, USD(1), aliceTakerGets));
367 for (
auto partialPayment : {
false,
true})
369 Env env{*
this, features};
371 env.fund(
XRP(10000), alice, bob, carol, gw);
373 env.trust(USD(1000), alice, bob, carol);
375 auto const initialCarolUSD = USD(0.999);
376 env(
pay(gw, carol, initialCarolUSD));
378 env(
pay(gw, bob, USD(100)));
390 TER const expectedTer =
393 env(
pay(alice, bob, USD(5)),
402 env.require(
offers(carol, 0));
420 testcase(
"Rm small increased q offers IOU");
428 using namespace std::chrono_literals;
429 auto const alice =
Account{
"alice"};
430 auto const bob =
Account{
"bob"};
431 auto const carol =
Account{
"carol"};
434 auto const USD = gw[
"USD"];
435 auto const EUR = gw[
"EUR"];
446 for (
auto crossBothOffers : {
false,
true})
448 Env env{*
this, features};
450 env.fund(
XRP(10000), alice, bob, carol, gw);
452 env.trust(USD(1000), alice, bob, carol);
453 env.trust(EUR(1000), alice, bob, carol);
455 auto initialCarolUSD = tinyAmount(USD);
456 env(
pay(gw, carol, initialCarolUSD));
457 env(
pay(gw, bob, USD(100)));
458 env(
pay(gw, alice, EUR(100)));
461 env(
offer(carol, EUR(1), USD(10)));
471 auto aliceTakerGets = crossBothOffers ? EUR(0.2) : EUR(0.1);
472 env(
offer(alice, USD(1), aliceTakerGets));
495 for (
auto partialPayment : {
false,
true})
497 Env env{*
this, features};
499 env.fund(
XRP(10000), alice, bob, carol, gw);
501 env.trust(USD(1000), alice, bob, carol);
502 env.trust(EUR(1000), alice, bob, carol);
505 auto const initialCarolUSD = tinyAmount(USD);
506 env(
pay(gw, carol, initialCarolUSD));
507 env(
pay(gw, bob, USD(100)));
508 env(
pay(gw, alice, EUR(100)));
511 env(
offer(carol, EUR(1), USD(2)));
521 TER const expectedTer =
524 env(
pay(alice, bob, USD(5)),
533 env.require(
offers(carol, 0));
555 auto const gw =
Account{
"gateway"};
556 auto const USD = gw[
"USD"];
557 auto const BTC = gw[
"BTC"];
558 auto const EUR = gw[
"EUR"];
566 Env env{*
this, features};
568 auto const gw1 =
Account{
"gw1"};
569 auto const USD1 = gw1[
"USD"];
570 auto const gw2 =
Account{
"gw2"};
571 auto const USD2 = gw2[
"USD"];
573 env.fund(
XRP(10000), alice,
noripple(bob), carol, dan, gw1, gw2);
575 env.trust(USD1(1000), alice, carol, dan);
577 env.trust(USD2(1000), alice, carol, dan);
580 env(
pay(gw1, dan, USD1(50)));
581 env(
pay(gw1, bob, USD1(50)));
582 env(
pay(gw2, bob, USD2(50)));
586 env(
pay(alice, carol, USD2(50)),
594 Env env{*
this, features};
596 auto const gw1 =
Account{
"gw1"};
597 auto const USD1 = gw1[
"USD"];
598 auto const gw2 =
Account{
"gw2"};
599 auto const USD2 = gw2[
"USD"];
601 env.fund(
XRP(10000), alice, bob, carol, dan, gw1, gw2);
603 env.trust(USD1(1000), alice, bob, carol, dan);
604 env.trust(USD2(1000), alice, bob, carol, dan);
606 env(
pay(gw1, dan, USD1(50)));
607 env(
pay(gw1, bob, USD1(50)));
608 env(
pay(gw2, bob, USD2(50)));
612 env(
pay(alice, carol, USD2(50)),
618 env.require(
balance(bob, USD1(100)));
619 env.require(
balance(bob, USD2(0)));
620 env.require(
balance(carol, USD2(50)));
637 auto const gw =
Account{
"gateway"};
638 auto const alice =
Account{
"alice"};
639 auto const bob =
Account{
"bob"};
640 auto const carol =
Account{
"carol"};
641 auto const USD = gw[
"USD"];
643 auto const usdOffer = USD(1000);
644 auto const xrpOffer =
XRP(1000);
648 Env env{*
this, features};
650 env.fund(
XRP(1000000), gw);
652 auto const f = env.current()->fees().base;
653 auto const r =
reserve(env, 0);
655 env.fund(r + f, alice);
666 Env env{*
this, features};
668 env.fund(
XRP(1000000), gw);
670 auto const f = env.current()->fees().base;
671 auto const r =
reserve(env, 0);
673 auto const usdOffer2 = USD(500);
674 auto const xrpOffer2 =
XRP(500);
676 env.fund(r + f + xrpOffer, bob);
679 env.fund(r + f, alice);
686 balance(alice, r - f + xrpOffer2),
698 Env env{*
this, features};
700 env.fund(
XRP(1000000), gw);
702 auto const f = env.current()->fees().base;
703 auto const r =
reserve(env, 0);
705 auto const usdOffer2 = USD(500);
706 auto const xrpOffer2 =
XRP(500);
708 env.fund(r + f + xrpOffer, bob, carol);
713 env.fund(r + f, alice);
720 balance(alice, r - f + xrpOffer),
741 if (sle->getType() == ltOFFER)
742 result.push_back(sle);
754 auto const startBalance =
XRP(1000000);
755 auto const gw =
Account{
"gateway"};
756 auto const alice =
Account{
"alice"};
757 auto const bob =
Account{
"bob"};
758 auto const USD = gw[
"USD"];
764 Env env{*
this, features};
766 auto const f = env.current()->fees().base;
768 env.fund(startBalance, gw, alice, bob);
791 env(
offer(alice,
XRP(1000), USD(1000)),
796 balance(alice, startBalance - (f * 2)),
800 balance(bob, startBalance - (f * 2)),
806 env(
offer(alice,
XRP(500), USD(500)),
811 balance(alice, startBalance - (f * 3) +
XRP(500)),
815 balance(bob, startBalance - (f * 2) -
XRP(500)),
824 Env env{*
this, features};
826 auto const f = env.current()->fees().base;
828 env.fund(startBalance, gw, alice, bob);
837 env(
offer(alice,
XRP(1000), USD(1000)),
843 balance(alice, startBalance - f - f),
850 env(
offer(alice,
XRP(1000), USD(1000)),
855 balance(alice, startBalance - f - f - f +
XRP(50)),
871 balance(alice, startBalance - f - f - f - f +
XRP(100)),
875 balance(bob, startBalance - f - f -
XRP(100)),
883 Env env(*
this, features);
885 env.
fund(startBalance, gw, alice, bob);
888 env(
trust(bob, USD(1000)));
891 env(
pay(gw, bob, USD(1000)));
894 env(
offer(alice, USD(1000),
XRP(2000)));
898 BEAST_EXPECT(aliceOffers.size() == 1);
899 for (
auto offerPtr : aliceOffers)
901 auto const&
offer = *offerPtr;
902 BEAST_EXPECT(
offer[sfTakerGets] ==
XRP(2000));
903 BEAST_EXPECT(
offer[sfTakerPays] == USD(1000));
913 BEAST_EXPECT(bobOffers.size() == 1);
914 for (
auto offerPtr : bobOffers)
916 auto const&
offer = *offerPtr;
917 BEAST_EXPECT(
offer[sfTakerGets] == USD(1000));
918 BEAST_EXPECT(
offer[sfTakerPays] ==
XRP(2000));
922 env(
offer(gw,
XRP(2000), USD(1000)));
928 env(
offer(gw, USD(1000),
XRP(2000)));
936 Env env(*
this, features);
938 env.
fund(startBalance, gw,
"alice",
"bob");
941 env(
trust(
"bob", USD(1000)));
944 env(
pay(gw,
"bob", USD(1000)));
945 env(
offer(
"alice", USD(500),
XRP(1001)));
948 env(
offer(
"alice", USD(500),
XRP(1000)));
952 BEAST_EXPECT(aliceOffers.size() == 2);
962 BEAST_EXPECT(bobOffers.size() == 1);
963 for (
auto offerPtr : bobOffers)
965 auto const&
offer = *offerPtr;
966 BEAST_EXPECT(
offer[sfTakerGets] == USD(499.5));
967 BEAST_EXPECT(
offer[sfTakerPays] ==
XRP(999));
979 auto const startBalance =
XRP(1000000);
980 auto const gw =
Account{
"gateway"};
981 auto const alice =
Account{
"alice"};
982 auto const USD = gw[
"USD"];
984 Env env{*
this, features};
986 env.fund(startBalance, gw, alice);
990 env(
offer(alice, USD(1000),
XRP(1000)),
997 env(
offer(alice, USD(1000),
XRP(1000)),
1027 env(
offer(alice, USD(1000),
XRP(1000)),
1035 env(
offer(alice, USD(1000),
XRP(1000)),
1055 using namespace jtx;
1057 auto const gw =
Account{
"gateway"};
1058 auto const alice =
Account{
"alice"};
1059 auto const bob =
Account{
"bob"};
1060 auto const USD = gw[
"USD"];
1062 auto const startBalance =
XRP(1000000);
1063 auto const usdOffer = USD(1000);
1064 auto const xrpOffer =
XRP(1000);
1066 Env env{*
this, features};
1068 env.fund(startBalance, gw, alice, bob);
1071 auto const f = env.current()->fees().base;
1077 balance(alice, startBalance - f),
1082 env(
offer(alice, xrpOffer, usdOffer),
1087 balance(alice, startBalance - f - f),
1094 env(
offer(alice, xrpOffer, usdOffer),
1098 balance(alice, startBalance - f - f - f),
1106 balance(alice, startBalance - f - f - f),
1114 balance(alice, startBalance - f - f - f),
1118 balance(bob, startBalance - f),
1129 using namespace jtx;
1131 auto const gw =
Account{
"gateway"};
1132 auto const USD = gw[
"USD"];
1134 auto const usdOffer = USD(1000);
1135 auto const xrpOffer =
XRP(1000);
1137 Env env{*
this, features};
1139 env.fund(
XRP(1000000), gw);
1143 auto const f = env.current()->fees().base;
1147 env.fund(
reserve(env, 0),
"alice");
1154 env.fund(
reserve(env, 0) + f,
"bob");
1162 env.fund(
reserve(env, 0) + f +
XRP(1),
"carol");
1170 env.fund(
reserve(env, 1) + f,
"dan");
1177 env.fund(
reserve(env, 1) + f + xrpOffer,
"eve");
1189 (use_partner ?
", with partner account" :
""));
1191 using namespace jtx;
1193 auto const gw =
Account{
"gateway"};
1194 auto const partner =
Account{
"partner"};
1195 auto const USD = gw[
"USD"];
1196 auto const BTC = gw[
"BTC"];
1198 Env env{*
this, features};
1201 env.fund(
XRP(10000), gw);
1204 env.fund(
XRP(10000), partner);
1206 env(
trust(partner, USD(100)));
1207 env(
trust(partner, BTC(500)));
1209 env(
pay(gw, partner, USD(100)));
1210 env(
pay(gw, partner, BTC(500)));
1212 auto const& account_to_test = use_partner ? partner : gw;
1215 env.require(
offers(account_to_test, 0));
1220 env(
offer(account_to_test, BTC(250),
XRP(1000)));
1221 env.require(
offers(account_to_test, 1));
1224 BEAST_EXPECT(
isOffer(env, account_to_test, BTC(250),
XRP(1000)));
1226 auto const secondLegSeq = env.seq(account_to_test);
1227 env(
offer(account_to_test,
XRP(1000), USD(50)));
1228 env.require(
offers(account_to_test, 2));
1231 BEAST_EXPECT(
isOffer(env, account_to_test,
XRP(1000), USD(50)));
1235 env(
offer(account_to_test, USD(50), BTC(250)));
1238 BEAST_EXPECT(jrr[jss::offers].isArray());
1239 BEAST_EXPECT(jrr[jss::offers].size() == 0);
1242 BEAST_EXPECT(jrr[jss::offers].isArray());
1243 BEAST_EXPECT(jrr[jss::offers].size() == 0);
1250 BEAST_EXPECT(acctOffers.size() == 0);
1251 for (
auto const& offerPtr : acctOffers)
1253 auto const&
offer = *offerPtr;
1254 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
1255 BEAST_EXPECT(
offer[sfTakerGets] == USD(0));
1256 BEAST_EXPECT(
offer[sfTakerPays] ==
XRP(0));
1264 env.require(
offers(account_to_test, 0));
1269 env(
offer(account_to_test, BTC(250), USD(50)));
1270 env.require(
offers(account_to_test, 1));
1274 BEAST_EXPECT(
isOffer(env, account_to_test, BTC(250), USD(50)));
1277 BEAST_EXPECT(jrr[jss::offers].isArray());
1278 BEAST_EXPECT(jrr[jss::offers].size() == 0);
1282 env(
offer(account_to_test, USD(50), BTC(250)));
1283 env.require(
offers(account_to_test, 1));
1288 BEAST_EXPECT(jrr[jss::offers].isArray());
1289 BEAST_EXPECT(jrr[jss::offers].size() == 0);
1291 BEAST_EXPECT(
isOffer(env, account_to_test, USD(50), BTC(250)));
1301 using namespace jtx;
1306 {features - fixReducedOffersV2, features | fixReducedOffersV2})
1308 Env env{*
this, localFeatures};
1310 auto const gw =
Account{
"gateway"};
1311 auto const alice =
Account{
"alice"};
1312 auto const bob =
Account{
"bob"};
1313 auto const USD = gw[
"USD"];
1314 auto const BTC = gw[
"BTC"];
1318 auto const gw_initial_balance =
drops(1149999730);
1319 auto const alice_initial_balance =
drops(499946999680);
1320 auto const bob_initial_balance =
drops(10199999920);
1321 auto const small_amount =
1322 STAmount{bob[
"USD"].
issue(), UINT64_C(2710505431213761), -33};
1324 env.fund(gw_initial_balance, gw);
1325 env.fund(alice_initial_balance, alice);
1326 env.fund(bob_initial_balance, bob);
1329 env(
rate(gw, 1.005));
1331 env(
trust(alice, USD(500)));
1332 env(
trust(bob, USD(50)));
1333 env(
trust(gw, alice[
"USD"](100)));
1335 env(
pay(gw, alice, alice[
"USD"](50)));
1336 env(
pay(gw, bob, small_amount));
1338 env(
offer(alice, USD(50),
XRP(150000)));
1341 env(
pay(alice, gw, USD(100)));
1344 env(
trust(gw, alice[
"USD"](0)));
1349 jrr[jss::node][sfBalance.fieldName][jss::value] ==
"50");
1353 jrr[jss::node][sfBalance.fieldName][jss::value] ==
1354 "-2710505431213761e-33");
1358 env(
offer(bob,
XRP(2000), USD(1)));
1360 if (localFeatures[fixReducedOffersV2])
1367 jrr[jss::node][sfBalance.fieldName][jss::value] ==
1368 "-2710505431213761e-33");
1372 BEAST_EXPECT(bobOffer[sfTakerGets.jsonName][jss::value] ==
"1");
1373 BEAST_EXPECT(bobOffer[sfTakerPays.jsonName] ==
"2000000000");
1384 auto const crossingDelta =
drops(1);
1388 jrr[jss::node][sfBalance.fieldName][jss::value] ==
"50");
1391 alice_initial_balance - env.current()->fees().base * 3 -
1396 jrr[jss::node][sfBalance.fieldName][jss::value] ==
"0");
1399 bob_initial_balance - env.current()->fees().base * 2 +
1409 (reverse_order ?
"Reverse" :
"Normal") +
" order");
1411 using namespace jtx;
1413 Env env{*
this, features};
1415 auto const gw =
Account{
"gateway"};
1416 auto const alice =
Account{
"alice"};
1417 auto const bob =
Account{
"bob"};
1418 auto const USD = gw[
"USD"];
1420 env.fund(
XRP(10000), gw, alice, bob);
1423 env(
trust(alice, USD(1000)));
1424 env(
trust(bob, USD(1000)));
1426 env(
pay(gw, alice, alice[
"USD"](500)));
1429 env(
offer(bob, USD(1),
XRP(4000)));
1431 env(
offer(alice,
XRP(150000), USD(50)));
1434 env(
offer(bob, USD(1),
XRP(4000)));
1441 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-1");
1444 jrr[jss::node][sfBalance.fieldName] ==
1446 env.current()->fees().base * 2)
1450 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-499");
1453 jrr[jss::node][sfBalance.fieldName] ==
1455 env.current()->fees().base * 2)
1462 testcase(
"Offer Crossing with Limit Override");
1464 using namespace jtx;
1466 Env env{*
this, features};
1468 auto const gw =
Account{
"gateway"};
1469 auto const alice =
Account{
"alice"};
1470 auto const bob =
Account{
"bob"};
1471 auto const USD = gw[
"USD"];
1473 env.fund(
XRP(100000), gw, alice, bob);
1476 env(
trust(alice, USD(1000)));
1478 env(
pay(gw, alice, alice[
"USD"](500)));
1480 env(
offer(alice,
XRP(150000), USD(50)));
1481 env(
offer(bob, USD(1),
XRP(3000)));
1484 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-1");
1487 jrr[jss::node][sfBalance.fieldName] ==
1492 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-499");
1495 jrr[jss::node][sfBalance.fieldName] ==
1503 testcase(
"Offer Accept then Cancel.");
1505 using namespace jtx;
1507 Env env{*
this, features};
1509 auto const USD = env.master[
"USD"];
1511 auto const nextOfferSeq = env.seq(env.master);
1512 env(
offer(env.master,
XRP(500), USD(100)));
1516 BEAST_EXPECT(env.seq(env.master) == nextOfferSeq + 2);
1521 BEAST_EXPECT(env.seq(env.master) == nextOfferSeq + 2);
1527 testcase(
"Offer Cancel Past and Future Sequence.");
1529 using namespace jtx;
1531 Env env{*
this, features};
1533 auto const alice =
Account{
"alice"};
1535 auto const nextOfferSeq = env.seq(env.master);
1536 env.fund(
XRP(10000), alice);
1553 testcase(
"Currency Conversion: Entire Offer");
1555 using namespace jtx;
1557 Env env{*
this, features};
1559 auto const gw =
Account{
"gateway"};
1560 auto const alice =
Account{
"alice"};
1561 auto const bob =
Account{
"bob"};
1562 auto const USD = gw[
"USD"];
1564 env.fund(
XRP(10000), gw, alice, bob);
1566 env.require(
owners(bob, 0));
1568 env(
trust(alice, USD(100)));
1569 env(
trust(bob, USD(1000)));
1573 env(
pay(gw, alice, alice[
"USD"](100)));
1574 auto const bobOfferSeq = env.seq(bob);
1575 env(
offer(bob, USD(100),
XRP(500)));
1580 jro[jss::node][jss::TakerGets] ==
XRP(500).value().getText());
1582 jro[jss::node][jss::TakerPays] ==
1588 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"0");
1591 jrr[jss::node][sfBalance.fieldName] ==
1596 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-100");
1599 BEAST_EXPECT(jro[jss::error] ==
"entryNotFound");
1607 testcase(
"Currency Conversion: Offerer Into Debt");
1609 using namespace jtx;
1611 Env env{*
this, features};
1613 auto const alice =
Account{
"alice"};
1614 auto const bob =
Account{
"bob"};
1615 auto const carol =
Account{
"carol"};
1617 env.fund(
XRP(10000), alice, bob, carol);
1620 env(
trust(alice, carol[
"EUR"](2000)));
1621 env(
trust(bob, alice[
"USD"](100)));
1622 env(
trust(carol, bob[
"EUR"](1000)));
1624 auto const bobOfferSeq = env.seq(bob);
1625 env(
offer(bob, alice[
"USD"](50), carol[
"EUR"](200)),
1628 env(
offer(alice, carol[
"EUR"](200), alice[
"USD"](50)));
1631 BEAST_EXPECT(jro[jss::error] ==
"entryNotFound");
1637 testcase(
"Currency Conversion: In Parts");
1639 using namespace jtx;
1641 Env env{*
this, features};
1643 auto const gw =
Account{
"gateway"};
1644 auto const alice =
Account{
"alice"};
1645 auto const bob =
Account{
"bob"};
1646 auto const USD = gw[
"USD"];
1648 env.fund(
XRP(10000), gw, alice, bob);
1651 env(
trust(alice, USD(200)));
1652 env(
trust(bob, USD(1000)));
1654 env(
pay(gw, alice, alice[
"USD"](200)));
1656 auto const bobOfferSeq = env.seq(bob);
1657 env(
offer(bob, USD(100),
XRP(500)));
1664 jro[jss::node][jss::TakerGets] ==
XRP(300).value().getText());
1666 jro[jss::node][jss::TakerPays] ==
1672 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-160");
1676 jrr[jss::node][sfBalance.fieldName] ==
1682 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-40");
1686 env(
pay(alice, alice,
XRP(600)),
1692 env(
pay(alice, alice,
XRP(600)),
1698 BEAST_EXPECT(jro[jss::error] ==
"entryNotFound");
1706 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-100");
1709 jrr[jss::node][sfBalance.fieldName] ==
1711 env.current()->fees().base * 4)
1717 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-100");
1723 testcase(
"Cross Currency Payment: Start with XRP");
1725 using namespace jtx;
1727 Env env{*
this, features};
1729 auto const gw =
Account{
"gateway"};
1730 auto const alice =
Account{
"alice"};
1731 auto const bob =
Account{
"bob"};
1732 auto const carol =
Account{
"carol"};
1733 auto const USD = gw[
"USD"];
1735 env.fund(
XRP(10000), gw, alice, bob, carol);
1738 env(
trust(carol, USD(1000)));
1739 env(
trust(bob, USD(2000)));
1741 env(
pay(gw, carol, carol[
"USD"](500)));
1743 auto const carolOfferSeq = env.seq(carol);
1744 env(
offer(carol,
XRP(500), USD(50)));
1749 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-25");
1752 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-475");
1756 jro[jss::node][jss::TakerGets] ==
1759 jro[jss::node][jss::TakerPays] ==
XRP(250).value().getText());
1765 testcase(
"Cross Currency Payment: End with XRP");
1767 using namespace jtx;
1769 Env env{*
this, features};
1771 auto const gw =
Account{
"gateway"};
1772 auto const alice =
Account{
"alice"};
1773 auto const bob =
Account{
"bob"};
1774 auto const carol =
Account{
"carol"};
1775 auto const USD = gw[
"USD"];
1777 env.fund(
XRP(10000), gw, alice, bob, carol);
1780 env(
trust(alice, USD(1000)));
1781 env(
trust(carol, USD(2000)));
1783 env(
pay(gw, alice, alice[
"USD"](500)));
1785 auto const carolOfferSeq = env.seq(carol);
1786 env(
offer(carol, USD(50),
XRP(500)));
1791 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-475");
1794 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-25");
1798 jrr[jss::node][sfBalance.fieldName] ==
1800 XRP(10000).value().mantissa() +
XRP(250).value().mantissa()));
1804 jro[jss::node][jss::TakerGets] ==
XRP(250).value().getText());
1806 jro[jss::node][jss::TakerPays] ==
1813 testcase(
"Cross Currency Payment: Bridged");
1815 using namespace jtx;
1817 Env env{*
this, features};
1819 auto const gw1 =
Account{
"gateway_1"};
1820 auto const gw2 =
Account{
"gateway_2"};
1821 auto const alice =
Account{
"alice"};
1822 auto const bob =
Account{
"bob"};
1823 auto const carol =
Account{
"carol"};
1824 auto const dan =
Account{
"dan"};
1825 auto const USD = gw1[
"USD"];
1826 auto const EUR = gw2[
"EUR"];
1828 env.fund(
XRP(10000), gw1, gw2, alice, bob, carol, dan);
1831 env(
trust(alice, USD(1000)));
1832 env(
trust(bob, EUR(1000)));
1833 env(
trust(carol, USD(1000)));
1834 env(
trust(dan, EUR(1000)));
1836 env(
pay(gw1, alice, alice[
"USD"](500)));
1837 env(
pay(gw2, dan, dan[
"EUR"](400)));
1839 auto const carolOfferSeq = env.seq(carol);
1840 env(
offer(carol, USD(50),
XRP(500)));
1842 auto const danOfferSeq = env.seq(dan);
1843 env(
offer(dan,
XRP(500), EUR(50)));
1846 jtp[0u][0u][jss::currency] =
"XRP";
1847 env(
pay(alice, bob, EUR(30)),
json(jss::Paths, jtp),
sendmax(USD(333)));
1850 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"470");
1853 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-30");
1856 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-30");
1859 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-370");
1863 jro[jss::node][jss::TakerGets] ==
XRP(200).value().getText());
1865 jro[jss::node][jss::TakerPays] ==
1870 jro[jss::node][jss::TakerGets] ==
1873 jro[jss::node][jss::TakerPays] ==
XRP(200).value().getText());
1882 testcase(
"Auto Bridged Second Leg Dry");
1884 using namespace jtx;
1885 Env env(*
this, features);
1891 auto const USD = gw[
"USD"];
1892 auto const EUR = gw[
"EUR"];
1894 env.
fund(
XRP(100000000), alice, bob, carol, gw);
1897 env.
trust(USD(10), alice);
1899 env(
pay(gw, alice, USD(10)));
1900 env.
trust(USD(10), carol);
1902 env(
pay(gw, carol, USD(3)));
1919 env.
trust(EUR(10), bob);
1921 env(
pay(gw, bob, EUR(10)));
1923 env(
offer(bob, USD(10), EUR(10)));
1946 testcase(
"Offer Fees Consume Funds");
1948 using namespace jtx;
1950 Env env{*
this, features};
1952 auto const gw1 =
Account{
"gateway_1"};
1953 auto const gw2 =
Account{
"gateway_2"};
1954 auto const gw3 =
Account{
"gateway_3"};
1955 auto const alice =
Account{
"alice"};
1956 auto const bob =
Account{
"bob"};
1957 auto const USD1 = gw1[
"USD"];
1958 auto const USD2 = gw2[
"USD"];
1959 auto const USD3 = gw3[
"USD"];
1967 auto const starting_xrp =
XRP(100) +
1968 env.current()->fees().accountReserve(3) +
1969 env.current()->fees().base * 4;
1971 env.fund(starting_xrp, gw1, gw2, gw3, alice, bob);
1974 env(
trust(alice, USD1(1000)));
1975 env(
trust(alice, USD2(1000)));
1976 env(
trust(alice, USD3(1000)));
1977 env(
trust(bob, USD1(1000)));
1978 env(
trust(bob, USD2(1000)));
1980 env(
pay(gw1, bob, bob[
"USD"](500)));
1982 env(
offer(bob,
XRP(200), USD1(200)));
1985 env(
offer(alice, USD1(200),
XRP(200)));
1988 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"100");
1991 jrr[jss::node][sfBalance.fieldName] ==
1995 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-400");
2001 testcase(
"Offer Create, then Cross");
2003 using namespace jtx;
2005 for (
auto NumberSwitchOver : {
false,
true})
2007 Env env{*
this, features};
2008 if (NumberSwitchOver)
2009 env.enableFeature(fixUniversalNumber);
2011 env.disableFeature(fixUniversalNumber);
2013 auto const gw =
Account{
"gateway"};
2014 auto const alice =
Account{
"alice"};
2015 auto const bob =
Account{
"bob"};
2016 auto const USD = gw[
"USD"];
2018 env.fund(
XRP(10000), gw, alice, bob);
2021 env(
rate(gw, 1.005));
2023 env(
trust(alice, USD(1000)));
2024 env(
trust(bob, USD(1000)));
2025 env(
trust(gw, alice[
"USD"](50)));
2027 env(
pay(gw, bob, bob[
"USD"](1)));
2028 env(
pay(alice, gw, USD(50)));
2030 env(
trust(gw, alice[
"USD"](0)));
2032 env(
offer(alice, USD(50),
XRP(150000)));
2033 env(
offer(bob,
XRP(100), USD(0.1)));
2037 jrr[jss::node][sfBalance.fieldName][jss::value] ==
2038 "49.96666666666667");
2042 jrr[jss::node][sfBalance.fieldName][jss::value];
2043 if (!NumberSwitchOver)
2045 BEAST_EXPECT(bobsUSD ==
"-0.966500000033334");
2049 BEAST_EXPECT(bobsUSD ==
"-0.9665000000333333");
2057 testcase(
"Offer tfSell: Basic Sell");
2059 using namespace jtx;
2061 Env env{*
this, features};
2063 auto const gw =
Account{
"gateway"};
2064 auto const alice =
Account{
"alice"};
2065 auto const bob =
Account{
"bob"};
2066 auto const USD = gw[
"USD"];
2068 auto const starting_xrp =
XRP(100) +
2069 env.current()->fees().accountReserve(1) +
2070 env.current()->fees().base * 2;
2072 env.fund(starting_xrp, gw, alice, bob);
2075 env(
trust(alice, USD(1000)));
2076 env(
trust(bob, USD(1000)));
2078 env(
pay(gw, bob, bob[
"USD"](500)));
2087 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-100");
2090 jrr[jss::node][sfBalance.fieldName] ==
2094 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-400");
2100 testcase(
"Offer tfSell: 2x Sell Exceed Limit");
2102 using namespace jtx;
2104 Env env{*
this, features};
2106 auto const gw =
Account{
"gateway"};
2107 auto const alice =
Account{
"alice"};
2108 auto const bob =
Account{
"bob"};
2109 auto const USD = gw[
"USD"];
2111 auto const starting_xrp =
XRP(100) +
2112 env.current()->fees().accountReserve(1) +
2113 env.current()->fees().base * 2;
2115 env.fund(starting_xrp, gw, alice, bob);
2118 env(
trust(alice, USD(150)));
2119 env(
trust(bob, USD(1000)));
2121 env(
pay(gw, bob, bob[
"USD"](500)));
2123 env(
offer(bob,
XRP(100), USD(200)));
2132 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-200");
2135 jrr[jss::node][sfBalance.fieldName] ==
2139 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-300");
2145 testcase(
"Client Issue #535: Gateway Cross Currency");
2147 using namespace jtx;
2149 Env env{*
this, features};
2151 auto const gw =
Account{
"gateway"};
2152 auto const alice =
Account{
"alice"};
2153 auto const bob =
Account{
"bob"};
2154 auto const XTS = gw[
"XTS"];
2155 auto const XXX = gw[
"XXX"];
2157 auto const starting_xrp =
XRP(100.1) +
2158 env.current()->fees().accountReserve(1) +
2159 env.current()->fees().base * 2;
2161 env.fund(starting_xrp, gw, alice, bob);
2164 env(
trust(alice, XTS(1000)));
2165 env(
trust(alice, XXX(1000)));
2166 env(
trust(bob, XTS(1000)));
2167 env(
trust(bob, XXX(1000)));
2169 env(
pay(gw, alice, alice[
"XTS"](100)));
2170 env(
pay(gw, alice, alice[
"XXX"](100)));
2171 env(
pay(gw, bob, bob[
"XTS"](100)));
2172 env(
pay(gw, bob, bob[
"XXX"](100)));
2174 env(
offer(alice, XTS(100), XXX(100)));
2181 payment[jss::id] = env.seq(bob);
2182 payment[jss::build_path] =
true;
2183 payment[jss::tx_json] =
pay(bob, bob, bob[
"XXX"](1));
2184 payment[jss::tx_json][jss::Sequence] =
2187 ->getFieldU32(sfSequence);
2188 payment[jss::tx_json][jss::Fee] =
to_string(env.current()->fees().base);
2189 payment[jss::tx_json][jss::SendMax] =
2191 auto jrr = wsc->invoke(
"submit", payment);
2192 BEAST_EXPECT(jrr[jss::status] ==
"success");
2193 BEAST_EXPECT(jrr[jss::result][jss::engine_result] ==
"tesSUCCESS");
2194 if (wsc->version() == 2)
2197 jrr.isMember(jss::jsonrpc) && jrr[jss::jsonrpc] ==
"2.0");
2199 jrr.isMember(jss::ripplerpc) && jrr[jss::ripplerpc] ==
"2.0");
2200 BEAST_EXPECT(jrr.isMember(jss::id) && jrr[jss::id] == 5);
2204 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-101");
2206 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-99");
2209 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-99");
2211 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-101");
2226 auto const sleTrust =
2228 BEAST_EXPECT(sleTrust);
2232 bool const accountLow = account.id() < issue.
account;
2237 low.setIssuer(accountLow ? account.id() : issue.
account);
2238 high.setIssuer(accountLow ? issue.
account : account.id());
2240 BEAST_EXPECT(sleTrust->getFieldAmount(sfLowLimit) == low);
2241 BEAST_EXPECT(sleTrust->getFieldAmount(sfHighLimit) == high);
2243 STAmount actualBalance{sleTrust->getFieldAmount(sfBalance)};
2247 BEAST_EXPECT(actualBalance == expectBalance);
2259 using namespace jtx;
2261 auto const gw =
Account(
"gateway");
2262 auto const USD = gw[
"USD"];
2264 Env env{*
this, features};
2266 env.fund(
XRP(10000000), gw);
2270 auto const f = env.current()->fees().base;
2273 enum preTrustType { noPreTrust, gwPreTrust, acctPreTrust };
2279 preTrustType preTrust;
2289 TestData
const tests[]{
2291 {
"ann",
reserve(env, 0) + 0 * f, 1, noPreTrust, 1000,
tecUNFUNDED_OFFER, f, USD( 0), 0, 0},
2292 {
"bev",
reserve(env, 0) + 1 * f, 1, noPreTrust, 1000,
tecUNFUNDED_OFFER, f, USD( 0), 0, 0},
2293 {
"cam",
reserve(env, 0) + 2 * f, 0, noPreTrust, 1000,
tecINSUF_RESERVE_OFFER, f, USD( 0), 0, 0},
2294 {
"deb",
drops(10) +
reserve(env, 0) + 1 * f, 1, noPreTrust, 1000,
tesSUCCESS,
drops(10) + f, USD(0.00001), 0, 1},
2295 {
"eve",
reserve(env, 1) + 0 * f, 0, noPreTrust, 1000,
tesSUCCESS, f, USD( 0), 1, 1},
2296 {
"flo",
reserve(env, 1) + 0 * f, 1, noPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 0, 1},
2297 {
"gay",
reserve(env, 1) + 1 * f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP( 50) + f, USD( 50), 0, 1},
2298 {
"hye",
XRP(1000) + 1 * f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP( 800) + f, USD( 800), 0, 1},
2299 {
"ivy",
XRP( 1) +
reserve(env, 1) + 1 * f, 1, noPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 0, 1},
2300 {
"joy",
XRP( 1) +
reserve(env, 2) + 1 * f, 1, noPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 1, 2},
2301 {
"kim",
XRP( 900) +
reserve(env, 2) + 1 * f, 999, noPreTrust, 1000,
tesSUCCESS,
XRP( 999) + f, USD( 999), 0, 1},
2302 {
"liz",
XRP( 998) +
reserve(env, 0) + 1 * f, 999, noPreTrust, 1000,
tesSUCCESS,
XRP( 998) + f, USD( 998), 0, 1},
2303 {
"meg",
XRP( 998) +
reserve(env, 1) + 1 * f, 999, noPreTrust, 1000,
tesSUCCESS,
XRP( 999) + f, USD( 999), 0, 1},
2304 {
"nia",
XRP( 998) +
reserve(env, 2) + 1 * f, 999, noPreTrust, 1000,
tesSUCCESS,
XRP( 999) + f, USD( 999), 1, 2},
2305 {
"ova",
XRP( 999) +
reserve(env, 0) + 1 * f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP( 999) + f, USD( 999), 0, 1},
2306 {
"pam",
XRP( 999) +
reserve(env, 1) + 1 * f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP(1000) + f, USD( 1000), 0, 1},
2307 {
"rae",
XRP( 999) +
reserve(env, 2) + 1 * f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP(1000) + f, USD( 1000), 0, 1},
2308 {
"sue",
XRP(1000) +
reserve(env, 2) + 1 * f, 0, noPreTrust, 1000,
tesSUCCESS, f, USD( 0), 1, 1},
2310 {
"abe",
reserve(env, 0) + 0 * f, 1, gwPreTrust, 1000,
tecUNFUNDED_OFFER, f, USD( 0), 0, 0},
2311 {
"bud",
reserve(env, 0) + 1 * f, 1, gwPreTrust, 1000,
tecUNFUNDED_OFFER, f, USD( 0), 0, 0},
2312 {
"che",
reserve(env, 0) + 2 * f, 0, gwPreTrust, 1000,
tecINSUF_RESERVE_OFFER, f, USD( 0), 0, 0},
2313 {
"dan",
drops(10) +
reserve(env, 0) + 1 * f, 1, gwPreTrust, 1000,
tesSUCCESS,
drops(10) + f, USD(0.00001), 0, 0},
2314 {
"eli",
XRP( 20) +
reserve(env, 0) + 1 * f, 1000, gwPreTrust, 1000,
tesSUCCESS,
XRP(20) + 1 * f, USD( 20), 0, 0},
2315 {
"fyn",
reserve(env, 1) + 0 * f, 0, gwPreTrust, 1000,
tesSUCCESS, f, USD( 0), 1, 1},
2316 {
"gar",
reserve(env, 1) + 0 * f, 1, gwPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 1, 1},
2317 {
"hal",
reserve(env, 1) + 1 * f, 1, gwPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 1, 1},
2319 {
"ned",
reserve(env, 1) + 0 * f, 1, acctPreTrust, 1000,
tecUNFUNDED_OFFER, 2 * f, USD( 0), 0, 1},
2320 {
"ole",
reserve(env, 1) + 1 * f, 1, acctPreTrust, 1000,
tecUNFUNDED_OFFER, 2 * f, USD( 0), 0, 1},
2321 {
"pat",
reserve(env, 1) + 2 * f, 0, acctPreTrust, 1000,
tecUNFUNDED_OFFER, 2 * f, USD( 0), 0, 1},
2322 {
"quy",
reserve(env, 1) + 2 * f, 1, acctPreTrust, 1000,
tecUNFUNDED_OFFER, 2 * f, USD( 0), 0, 1},
2323 {
"ron",
reserve(env, 1) + 3 * f, 0, acctPreTrust, 1000,
tecINSUF_RESERVE_OFFER, 2 * f, USD( 0), 0, 1},
2324 {
"syd",
drops(10) +
reserve(env, 1) + 2 * f, 1, acctPreTrust, 1000,
tesSUCCESS,
drops(10) + 2 * f, USD(0.00001), 0, 1},
2325 {
"ted",
XRP( 20) +
reserve(env, 1) + 2 * f, 1000, acctPreTrust, 1000,
tesSUCCESS,
XRP(20) + 2 * f, USD( 20), 0, 1},
2326 {
"uli",
reserve(env, 2) + 0 * f, 0, acctPreTrust, 1000,
tecINSUF_RESERVE_OFFER, 2 * f, USD( 0), 0, 1},
2327 {
"vic",
reserve(env, 2) + 0 * f, 1, acctPreTrust, 1000,
tesSUCCESS,
XRP( 1) + 2 * f, USD( 1), 0, 1},
2328 {
"wes",
reserve(env, 2) + 1 * f, 0, acctPreTrust, 1000,
tesSUCCESS, 2 * f, USD( 0), 1, 2},
2329 {
"xan",
reserve(env, 2) + 1 * f, 1, acctPreTrust, 1000,
tesSUCCESS,
XRP( 1) + 2 * f, USD( 1), 1, 2},
2333 for (
auto const& t : tests)
2335 auto const acct =
Account(t.account);
2336 env.fund(t.fundXrp, acct);
2340 env.require(
offers(gw, 0));
2343 auto const book = t.bookAmount;
2345 env(
offer(gw,
XRP(book), USD(book)));
2350 if (t.preTrust == gwPreTrust)
2351 env(
trust(gw, acct[
"USD"](1)));
2357 if (t.preTrust == acctPreTrust)
2358 env(
trust(acct, USD(1)));
2363 auto const acctOffer = t.offerAmount;
2364 env(
offer(acct, USD(acctOffer),
XRP(acctOffer)),
ter(t.tec));
2369 BEAST_EXPECT(env.balance(acct, USD.issue()) == t.balanceUsd);
2371 env.balance(acct,
xrpIssue()) == t.fundXrp - t.spentXrp);
2372 env.require(
offers(acct, t.offers));
2373 env.require(
owners(acct, t.owners));
2376 BEAST_EXPECT(acctOffers.size() == t.offers);
2377 if (acctOffers.size() && t.offers)
2379 auto const& acctOffer = *(acctOffers.front());
2381 auto const leftover = t.offerAmount - t.bookAmount;
2382 BEAST_EXPECT(acctOffer[sfTakerGets] ==
XRP(leftover));
2383 BEAST_EXPECT(acctOffer[sfTakerPays] == USD(leftover));
2386 if (t.preTrust == noPreTrust)
2388 if (t.balanceUsd.value().signum())
2396 auto const sleTrust =
2398 BEAST_EXPECT(!sleTrust);
2415 using namespace jtx;
2417 auto const gw =
Account(
"gateway");
2418 auto const alice =
Account(
"alice");
2419 auto const bob =
Account(
"bob");
2420 auto const USD = gw[
"USD"];
2422 auto const usdOffer = USD(1000);
2423 auto const xrpOffer =
XRP(1000);
2425 Env env{*
this, features};
2427 env.fund(
XRP(1000000), gw, bob);
2431 auto const fee = env.current()->fees().base;
2438 env(
trust(alice, usdOffer));
2442 env(
pay(gw, alice, usdOffer));
2449 auto const alicesXRP = env.balance(alice);
2450 auto const bobsXRP = env.balance(bob);
2452 env(
offer(alice, xrpOffer, usdOffer));
2454 env(
offer(bob, usdOffer, xrpOffer));
2468 env(
offer(alice, USD(999),
XRP(999)));
2469 env(
offer(bob, xrpOffer, usdOffer));
2472 env.require(
balance(alice, USD(999)));
2473 env.require(
balance(bob, USD(1)));
2474 env.require(
offers(alice, 0));
2478 BEAST_EXPECT(bobsOffers.size() == 1);
2479 auto const& bobsOffer = *(bobsOffers.front());
2481 BEAST_EXPECT(bobsOffer[sfLedgerEntryType] == ltOFFER);
2482 BEAST_EXPECT(bobsOffer[sfTakerGets] == USD(1));
2483 BEAST_EXPECT(bobsOffer[sfTakerPays] ==
XRP(1));
2492 using namespace jtx;
2494 auto const gw =
Account(
"gateway");
2495 auto const alice =
Account(
"alice");
2496 auto const bob =
Account(
"bob");
2497 auto const USD = gw[
"USD"];
2498 auto const EUR = gw[
"EUR"];
2500 auto const usdOffer = USD(1000);
2501 auto const eurOffer = EUR(1000);
2503 Env env{*
this, features};
2505 env.fund(
XRP(1000000), gw);
2509 auto const fee = env.current()->fees().base;
2517 env(
trust(alice, usdOffer));
2518 env(
trust(bob, eurOffer));
2521 env(
pay(gw, alice, usdOffer));
2522 env(
pay(gw, bob, eurOffer));
2530 env(
offer(alice, eurOffer, usdOffer));
2531 env(
offer(bob, usdOffer, eurOffer));
2548 env(
offer(bob, eurOffer, usdOffer));
2551 env(
offer(alice, USD(999), eurOffer));
2554 env.require(
offers(alice, 0));
2555 env.require(
offers(bob, 1));
2557 env.require(
balance(alice, USD(999)));
2558 env.require(
balance(alice, EUR(1)));
2559 env.require(
balance(bob, USD(1)));
2560 env.require(
balance(bob, EUR(999)));
2564 if (BEAST_EXPECT(bobsOffers.size() == 1))
2566 auto const& bobsOffer = *(bobsOffers.front());
2568 BEAST_EXPECT(bobsOffer[sfTakerGets] == USD(1));
2569 BEAST_EXPECT(bobsOffer[sfTakerPays] == EUR(1));
2574 env(
offer(alice, USD(1), EUR(1)));
2577 env.require(
balance(alice, USD(1000)));
2580 env.require(
balance(bob, EUR(1000)));
2581 env.require(
offers(alice, 0));
2582 env.require(
offers(bob, 0));
2585 BEAST_EXPECT(!env.le(
keylet::line(alice.id(), EUR.issue())));
2586 BEAST_EXPECT(!env.le(
keylet::line(bob.id(), USD.issue())));
2590 env(
offer(alice, EUR(999), usdOffer));
2593 env(
offer(bob, usdOffer, eurOffer));
2596 env.require(
offers(alice, 0));
2597 env.require(
offers(bob, 0));
2599 env.require(
balance(alice, USD(0)));
2600 env.require(
balance(alice, EUR(999)));
2601 env.require(
balance(bob, USD(1000)));
2602 env.require(
balance(bob, EUR(1)));
2610 using namespace jtx;
2612 auto const gw =
Account(
"gateway");
2613 auto const alice =
Account(
"alice");
2614 auto const bob =
Account(
"bob");
2615 auto const carol =
Account(
"carol");
2616 auto const USD = gw[
"USD"];
2617 auto const EUR = gw[
"EUR"];
2619 auto const usdOffer = USD(1000);
2620 auto const eurOffer = EUR(1000);
2622 Env env{*
this, features};
2624 env.fund(
XRP(1000000), gw, alice, bob, carol);
2627 env(
trust(alice, usdOffer));
2628 env(
trust(carol, eurOffer));
2630 env(
pay(gw, alice, usdOffer));
2631 env(
pay(gw, carol, eurOffer));
2640 env(
offer(alice,
XRP(1000), usdOffer));
2641 env(
offer(bob, eurOffer,
XRP(1000)));
2642 auto const bobXrpBalance = env.balance(bob);
2646 env(
offer(carol, USD(400), EUR(400)));
2659 BEAST_EXPECT(alicesOffers.size() == 1);
2660 auto const& alicesOffer = *(alicesOffers.front());
2662 BEAST_EXPECT(alicesOffer[sfLedgerEntryType] == ltOFFER);
2663 BEAST_EXPECT(alicesOffer[sfTakerGets] == USD(600));
2664 BEAST_EXPECT(alicesOffer[sfTakerPays] ==
XRP(600));
2668 BEAST_EXPECT(bobsOffers.size() == 1);
2669 auto const& bobsOffer = *(bobsOffers.front());
2671 BEAST_EXPECT(bobsOffer[sfLedgerEntryType] == ltOFFER);
2672 BEAST_EXPECT(bobsOffer[sfTakerGets] ==
XRP(600));
2673 BEAST_EXPECT(bobsOffer[sfTakerPays] == EUR(600));
2677 env(
offer(carol, USD(600), EUR(600)));
2692 if (alicesOffers.size() != 0)
2694 BEAST_EXPECT(alicesOffers.size() == 1);
2695 auto const& alicesOffer = *(alicesOffers.front());
2697 BEAST_EXPECT(alicesOffer[sfLedgerEntryType] == ltOFFER);
2698 BEAST_EXPECT(alicesOffer[sfTakerGets] == USD(0));
2699 BEAST_EXPECT(alicesOffer[sfTakerPays] ==
XRP(0));
2711 using namespace jtx;
2713 auto const gw =
Account(
"gateway");
2714 auto const USD = gw[
"USD"];
2716 Env env{*
this, features};
2718 env.fund(
XRP(10000000), gw);
2722 auto const f = env.current()->fees().base;
2725 enum preTrustType { noPreTrust, gwPreTrust, acctPreTrust };
2759 : account(std::move(account_))
2764 , acctGets(acctGets_)
2765 , acctPays(acctPays_)
2767 , spentXrp(spentXrp_)
2768 , finalUsd(finalUsd_)
2771 , takerGets(takerGets_)
2772 , takerPays(takerPays_)
2791 std::move(account_),
2810 TestData
const tests[]{
2813 {
"ann",
XRP(10) +
reserve(env, 0) + 1 * f, USD( 0),
XRP(10), USD( 5), USD(10),
XRP(10),
tecINSUF_RESERVE_OFFER,
XRP( 0) + (1 * f), USD( 0), 0, 0},
2814 {
"bev",
XRP(10) +
reserve(env, 1) + 1 * f, USD( 0),
XRP(10), USD( 5), USD(10),
XRP(10),
tesSUCCESS,
XRP( 0) + (1 * f), USD( 0), 1, 1,
XRP(10), USD(10)},
2815 {
"cam",
XRP(10) +
reserve(env, 0) + 1 * f, USD( 0),
XRP(10), USD(10), USD(10),
XRP(10),
tesSUCCESS,
XRP( 10) + (1 * f), USD(10), 0, 1},
2816 {
"deb",
XRP(10) +
reserve(env, 0) + 1 * f, USD( 0),
XRP(10), USD(20), USD(10),
XRP(10),
tesSUCCESS,
XRP( 10) + (1 * f), USD(20), 0, 1},
2817 {
"eve",
XRP(10) +
reserve(env, 0) + 1 * f, USD( 0),
XRP(10), USD(20), USD( 5),
XRP( 5),
tesSUCCESS,
XRP( 5) + (1 * f), USD(10), 0, 1},
2818 {
"flo",
XRP(10) +
reserve(env, 0) + 1 * f, USD( 0),
XRP(10), USD(20), USD(20),
XRP(20),
tesSUCCESS,
XRP( 10) + (1 * f), USD(20), 0, 1},
2819 {
"gay",
XRP(20) +
reserve(env, 1) + 1 * f, USD( 0),
XRP(10), USD(20), USD(20),
XRP(20),
tesSUCCESS,
XRP( 10) + (1 * f), USD(20), 0, 1},
2820 {
"hye",
XRP(20) +
reserve(env, 2) + 1 * f, USD( 0),
XRP(10), USD(20), USD(20),
XRP(20),
tesSUCCESS,
XRP( 10) + (1 * f), USD(20), 1, 2,
XRP(10), USD(10)},
2822 {
"meg",
reserve(env, 1) + 2 * f, USD(10), USD(10),
XRP( 5),
XRP(10), USD(10),
tecINSUF_RESERVE_OFFER,
XRP( 0) + (2 * f), USD(10), 0, 1},
2823 {
"nia",
reserve(env, 2) + 2 * f, USD(10), USD(10),
XRP( 5),
XRP(10), USD(10),
tesSUCCESS,
XRP( 0) + (2 * f), USD(10), 1, 2, USD(10),
XRP(10)},
2824 {
"ova",
reserve(env, 1) + 2 * f, USD(10), USD(10),
XRP(10),
XRP(10), USD(10),
tesSUCCESS,
XRP(-10) + (2 * f), USD( 0), 0, 1},
2825 {
"pam",
reserve(env, 1) + 2 * f, USD(10), USD(10),
XRP(20),
XRP(10), USD(10),
tesSUCCESS,
XRP(-20) + (2 * f), USD( 0), 0, 1},
2826 {
"qui",
reserve(env, 1) + 2 * f, USD(10), USD(20),
XRP(40),
XRP(10), USD(10),
tesSUCCESS,
XRP(-20) + (2 * f), USD( 0), 0, 1},
2827 {
"rae",
reserve(env, 2) + 2 * f, USD(10), USD( 5),
XRP( 5),
XRP(10), USD(10),
tesSUCCESS,
XRP( -5) + (2 * f), USD( 5), 1, 2, USD( 5),
XRP( 5)},
2828 {
"sue",
reserve(env, 2) + 2 * f, USD(10), USD( 5),
XRP(10),
XRP(10), USD(10),
tesSUCCESS,
XRP(-10) + (2 * f), USD( 5), 1, 2, USD( 5),
XRP( 5)},
2832 auto const zeroUsd = USD(0);
2833 for (
auto const& t : tests)
2836 env.require(
offers(gw, 0));
2838 auto const acct =
Account(t.account);
2840 env.fund(t.fundXrp, acct);
2846 if (t.fundUSD != zeroUsd)
2848 env(
trust(acct, t.fundUSD));
2850 env(
pay(gw, acct, t.fundUSD));
2854 env(
offer(gw, t.gwGets, t.gwPays));
2864 BEAST_EXPECT(env.balance(acct, USD.issue()) == t.finalUsd);
2866 env.balance(acct,
xrpIssue()) == t.fundXrp - t.spentXrp);
2867 env.require(
offers(acct, t.offers));
2868 env.require(
owners(acct, t.owners));
2873 if (acctOffers.size() > 0)
2875 BEAST_EXPECT(acctOffers.size() == 1);
2876 auto const& acctOffer = *(acctOffers.front());
2878 BEAST_EXPECT(acctOffer[sfLedgerEntryType] == ltOFFER);
2879 BEAST_EXPECT(acctOffer[sfTakerGets] == t.takerGets);
2880 BEAST_EXPECT(acctOffer[sfTakerPays] == t.takerPays);
2897 testcase(
"Combine tfSell with tfFillOrKill");
2899 using namespace jtx;
2901 auto const gw =
Account(
"gateway");
2902 auto const alice =
Account(
"alice");
2903 auto const bob =
Account(
"bob");
2904 auto const USD = gw[
"USD"];
2906 Env env{*
this, features};
2908 env.fund(
XRP(10000000), gw, alice, bob);
2915 env(
trust(bob, USD(200)));
2917 env(
pay(gw, bob, USD(100)));
2919 env(
offer(bob,
XRP(2000), USD(20)));
2927 env.require(
offers(alice, 0));
2928 env.require(
balance(bob, USD(100)));
2935 env.require(
balance(alice, USD(20)));
2936 env.require(
offers(alice, 0));
2937 env.require(
balance(bob, USD(80)));
2942 env(
offer(bob,
XRP(2000), USD(20)));
2946 env.require(
balance(alice, USD(35)));
2947 env.require(
offers(alice, 0));
2948 env.require(
balance(bob, USD(65)));
2960 env.require(
balance(alice, USD(35)));
2961 env.require(
offers(alice, 0));
2962 env.require(
balance(bob, USD(65)));
2971 env.require(
balance(alice, USD(40)));
2972 env.require(
offers(alice, 0));
2973 env.require(
balance(bob, USD(60)));
2982 using namespace jtx;
2984 auto const gw1 =
Account(
"gateway1");
2985 auto const USD = gw1[
"USD"];
2987 Env env{*
this, features};
2990 auto const fee = env.current()->fees().base;
2992 env.fund(
XRP(100000), gw1);
2995 env(
rate(gw1, 1.25));
2997 auto const ann =
Account(
"ann");
2998 auto const bob =
Account(
"bob");
3002 env(
trust(ann, USD(200)));
3003 env(
trust(bob, USD(200)));
3006 env(
pay(gw1, bob, USD(125)));
3021 env.require(
balance(ann, USD(100)));
3023 env.require(
offers(ann, 0));
3025 env.require(
balance(bob, USD(0)));
3027 env.require(
offers(bob, 0));
3032 auto const che =
Account(
"che");
3033 auto const deb =
Account(
"deb");
3037 env(
trust(che, USD(200)));
3038 env(
trust(deb, USD(200)));
3041 env(
pay(gw1, deb, USD(125)));
3050 env.require(
balance(che, USD(100)));
3052 env.require(
offers(che, 0));
3054 env.require(
balance(deb, USD(0)));
3056 env.require(
offers(deb, 0));
3059 auto const eve =
Account(
"eve");
3060 auto const fyn =
Account(
"fyn");
3062 env.fund(
XRP(20000) + (
fee * 2), eve, fyn);
3065 env(
trust(eve, USD(1000)));
3066 env(
trust(fyn, USD(1000)));
3069 env(
pay(gw1, eve, USD(100)));
3070 env(
pay(gw1, fyn, USD(100)));
3076 env(
offer(eve, USD(10),
XRP(4000)));
3080 env(
offer(fyn,
XRP(2000), USD(5)));
3083 env.require(
balance(eve, USD(105)));
3086 BEAST_EXPECT(evesOffers.size() == 1);
3087 if (evesOffers.size() != 0)
3089 auto const& evesOffer = *(evesOffers.front());
3090 BEAST_EXPECT(evesOffer[sfLedgerEntryType] == ltOFFER);
3091 BEAST_EXPECT(evesOffer[sfTakerGets] ==
XRP(2000));
3092 BEAST_EXPECT(evesOffer[sfTakerPays] == USD(5));
3096 env.require(
balance(fyn, USD(93.75)));
3098 env.require(
offers(fyn, 0));
3101 auto const gw2 =
Account(
"gateway2");
3102 auto const EUR = gw2[
"EUR"];
3104 env.fund(
XRP(100000), gw2);
3107 env(
rate(gw2, 1.5));
3112 auto const gay =
Account(
"gay");
3113 auto const hal =
Account(
"hal");
3114 env.fund(
reserve(env, 3) + (
fee * 3), gay, hal);
3117 env(
trust(gay, USD(200)));
3118 env(
trust(gay, EUR(200)));
3119 env(
trust(hal, USD(200)));
3120 env(
trust(hal, EUR(200)));
3123 env(
pay(gw1, gay, USD(125)));
3124 env(
pay(gw2, hal, EUR(150)));
3127 env(
offer(gay, EUR(100), USD(100)));
3130 env(
offer(hal, USD(100), EUR(100)));
3133 env.require(
balance(gay, USD(0)));
3134 env.require(
balance(gay, EUR(100)));
3136 env.require(
offers(gay, 0));
3138 env.require(
balance(hal, USD(100)));
3139 env.require(
balance(hal, EUR(0)));
3141 env.require(
offers(hal, 0));
3145 auto const ivy =
Account(
"ivy");
3146 auto const joe =
Account(
"joe");
3147 env.fund(
reserve(env, 3) + (
fee * 3), ivy, joe);
3156 env(
pay(gw1, ivy, USD(270)),
sendmax(USD(500)));
3157 env(
pay(gw2, joe, EUR(150)),
sendmax(EUR(300)));
3159 env.require(
balance(ivy, USD(300)));
3160 env.require(
balance(joe, EUR(250)));
3162 env(
offer(ivy, EUR(100), USD(200)));
3165 env(
offer(joe, USD(200), EUR(100)));
3168 env.require(
balance(ivy, USD(50)));
3169 env.require(
balance(ivy, EUR(100)));
3171 env.require(
offers(ivy, 0));
3173 env.require(
balance(joe, USD(200)));
3174 env.require(
balance(joe, EUR(100)));
3176 env.require(
offers(joe, 0));
3180 auto const kim =
Account(
"kim");
3181 auto const K_BUX = kim[
"BUX"];
3182 auto const lex =
Account(
"lex");
3183 auto const meg =
Account(
"meg");
3184 auto const ned =
Account(
"ned");
3185 auto const N_BUX = ned[
"BUX"];
3188 env.fund(
reserve(env, 4) + (
fee * 4), kim, lex, meg, ned);
3191 env(
trust(lex, K_BUX(400)));
3193 env(
trust(meg, N_BUX(100)));
3195 env(
pay(ned, lex, N_BUX(100)));
3197 env.require(
balance(lex, N_BUX(100)));
3199 env(
pay(kim, meg, N_BUX(60)),
path(lex, ned),
sendmax(K_BUX(200)));
3204 env.require(
balance(lex, K_BUX(72)));
3205 env.require(
balance(lex, N_BUX(40)));
3207 env.require(
balance(meg, N_BUX(60)));
3212 env(
offer(lex, K_BUX(30), N_BUX(30)));
3215 env(
offer(kim, N_BUX(30), K_BUX(30)));
3219 env.require(
balance(kim, N_BUX(30)));
3220 env.require(
balance(lex, K_BUX(102)));
3221 env.require(
balance(lex, N_BUX(10)));
3223 env.require(
balance(meg, N_BUX(60)));
3224 env.require(
balance(ned, K_BUX(-30)));
3229 auto const ova =
Account(
"ova");
3230 auto const pat =
Account(
"pat");
3231 auto const qae =
Account(
"qae");
3232 env.fund(
XRP(2) +
reserve(env, 3) + (
fee * 3), ova, pat, qae);
3238 env(
trust(ova, USD(200)));
3239 env(
trust(ova, EUR(200)));
3240 env(
trust(pat, USD(200)));
3241 env(
trust(pat, EUR(200)));
3242 env(
trust(qae, USD(200)));
3243 env(
trust(qae, EUR(200)));
3246 env(
pay(gw1, ova, USD(125)));
3247 env(
pay(gw2, qae, EUR(150)));
3254 env(
offer(qae, USD(100), EUR(100)));
3257 env.require(
balance(ova, USD(0)));
3258 env.require(
balance(ova, EUR(0)));
3263 if (ovasOffers.size() != 0)
3265 BEAST_EXPECT(ovasOffers.size() == 1);
3266 auto const& ovasOffer = *(ovasOffers.front());
3268 BEAST_EXPECT(ovasOffer[sfLedgerEntryType] == ltOFFER);
3269 BEAST_EXPECT(ovasOffer[sfTakerGets] == USD(0));
3270 BEAST_EXPECT(ovasOffer[sfTakerPays] ==
XRP(0));
3273 env.require(
balance(pat, USD(0)));
3274 env.require(
balance(pat, EUR(100)));
3276 env.require(
offers(pat, 0));
3278 env.require(
balance(qae, USD(100)));
3279 env.require(
balance(qae, EUR(0)));
3281 env.require(
offers(qae, 0));
3302 using namespace jtx;
3304 auto const gw =
Account(
"gateway");
3305 auto const USD = gw[
"USD"];
3307 Env env{*
this, features};
3310 auto const fee = env.current()->fees().base;
3311 auto const startBalance =
XRP(1000000);
3313 env.fund(startBalance + (
fee * 4), gw);
3323 env.require(
owners(gw, 3));
3324 env.require(
balance(gw, startBalance +
fee));
3327 BEAST_EXPECT(gwOffers.size() == 3);
3328 for (
auto const& offerPtr : gwOffers)
3330 auto const&
offer = *offerPtr;
3331 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
3332 BEAST_EXPECT(
offer[sfTakerGets] ==
XRP(600));
3333 BEAST_EXPECT(
offer[sfTakerPays] == USD(60));
3338 env(
offer(gw,
XRP(1000), USD(100)));
3340 env.require(
owners(gw, 1));
3341 env.require(
offers(gw, 1));
3342 env.require(
balance(gw, startBalance));
3345 BEAST_EXPECT(gwOffers.size() == 1);
3346 for (
auto const& offerPtr : gwOffers)
3348 auto const&
offer = *offerPtr;
3349 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
3350 BEAST_EXPECT(
offer[sfTakerGets] == USD(100));
3351 BEAST_EXPECT(
offer[sfTakerPays] ==
XRP(1000));
3358 using namespace jtx;
3360 auto const gw1 =
Account(
"gateway1");
3361 auto const gw2 =
Account(
"gateway2");
3362 auto const alice =
Account(
"alice");
3363 auto const USD = gw1[
"USD"];
3364 auto const EUR = gw2[
"EUR"];
3366 Env env{*
this, features};
3368 env.fund(
XRP(1000000), gw1, gw2);
3372 auto const f = env.current()->fees().base;
3386 TestData
const tests[]{
3397 for (
auto const& t : tests)
3399 auto const acct =
Account{t.acct};
3400 env.fund(t.fundXRP, acct);
3403 env(
trust(acct, USD(1000)));
3404 env(
trust(acct, EUR(1000)));
3407 if (t.fundUSD > USD(0))
3408 env(
pay(gw1, acct, t.fundUSD));
3409 if (t.fundEUR > EUR(0))
3410 env(
pay(gw2, acct, t.fundEUR));
3413 env(
offer(acct, USD(500), EUR(600)),
ter(t.firstOfferTec));
3417 int offerCount = t.firstOfferTec ==
tesSUCCESS ? 1 : 0;
3418 env.require(
owners(acct, 2 + offerCount));
3419 env.require(
balance(acct, t.fundUSD));
3420 env.require(
balance(acct, t.fundEUR));
3423 BEAST_EXPECT(acctOffers.size() == offerCount);
3424 for (
auto const& offerPtr : acctOffers)
3426 auto const&
offer = *offerPtr;
3427 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
3428 BEAST_EXPECT(
offer[sfTakerGets] == EUR(600));
3429 BEAST_EXPECT(
offer[sfTakerPays] == USD(500));
3432 env(
offer(acct, EUR(600), USD(500)),
ter(t.secondOfferTec));
3436 offerCount = t.secondOfferTec ==
tesSUCCESS ? 1 : offerCount;
3437 env.require(
owners(acct, 2 + offerCount));
3438 env.require(
balance(acct, t.fundUSD));
3439 env.require(
balance(acct, t.fundEUR));
3442 BEAST_EXPECT(acctOffers.size() == offerCount);
3443 for (
auto const& offerPtr : acctOffers)
3445 auto const&
offer = *offerPtr;
3446 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
3447 if (
offer[sfSequence] == firstOfferSeq)
3449 BEAST_EXPECT(
offer[sfTakerGets] == EUR(600));
3450 BEAST_EXPECT(
offer[sfTakerPays] == USD(500));
3454 BEAST_EXPECT(
offer[sfTakerGets] == USD(500));
3455 BEAST_EXPECT(
offer[sfTakerPays] == EUR(600));
3482 using namespace jtx;
3484 Env env{*
this, features};
3486 auto const alice =
Account(
"alice");
3487 auto const bob =
Account(
"bob");
3488 auto const USD = bob[
"USD"];
3489 auto const f = env.current()->fees().base;
3491 env.fund(
XRP(50000) + f, alice, bob);
3494 env(
offer(alice, USD(5000),
XRP(50000)));
3498 env(
offer(bob,
XRP(50000), USD(5000)));
3504 env.require(
owners(alice, 1));
3505 env.require(
lines(alice, 1));
3510 BEAST_EXPECT(bobOffers.size() == 1);
3511 for (
auto const& offerPtr : bobOffers)
3513 auto const&
offer = *offerPtr;
3514 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
3515 BEAST_EXPECT(
offer[sfTakerGets] == USD(25));
3516 BEAST_EXPECT(
offer[sfTakerPays] ==
XRP(250));
3528 using namespace jtx;
3530 Env env{*
this, features};
3533 auto const fee = env.current()->fees().base;
3536 auto const ann =
Account(
"ann");
3537 auto const A_BUX = ann[
"BUX"];
3538 auto const bob =
Account(
"bob");
3539 auto const cam =
Account(
"cam");
3540 auto const dan =
Account(
"dan");
3541 auto const D_BUX = dan[
"BUX"];
3544 env.fund(
reserve(env, 4) + (
fee * 4), ann, bob, cam, dan);
3547 env(
trust(bob, A_BUX(400)));
3549 env(
trust(cam, D_BUX(100)));
3551 env(
pay(dan, bob, D_BUX(100)));
3553 env.require(
balance(bob, D_BUX(100)));
3555 env(
pay(ann, cam, D_BUX(60)),
path(bob, dan),
sendmax(A_BUX(200)));
3560 env.require(
balance(bob, A_BUX(72)));
3561 env.require(
balance(bob, D_BUX(40)));
3563 env.require(
balance(cam, D_BUX(60)));
3567 env(
offer(bob, A_BUX(30), D_BUX(30)));
3570 env(
trust(ann, D_BUX(100)));
3574 env(
pay(ann, ann, D_BUX(30)),
3581 env.require(
balance(ann, D_BUX(0)));
3582 env.require(
balance(bob, A_BUX(72)));
3583 env.require(
balance(bob, D_BUX(40)));
3585 env.require(
balance(cam, D_BUX(60)));
3586 env.require(
balance(dan, A_BUX(0)));
3600 using namespace jtx;
3602 Env env{*
this, features};
3604 auto const ann =
Account(
"ann");
3605 auto const bob =
Account(
"bob");
3606 auto const cam =
Account(
"cam");
3607 auto const A_BUX = ann[
"BUX"];
3608 auto const B_BUX = bob[
"BUX"];
3610 auto const fee = env.current()->fees().base;
3611 env.fund(
reserve(env, 4) + (
fee * 5), ann, bob, cam);
3614 env(
trust(ann, B_BUX(40)));
3615 env(
trust(cam, A_BUX(40)));
3616 env(
trust(cam, B_BUX(40)));
3619 env(
pay(ann, cam, A_BUX(35)));
3620 env(
pay(bob, cam, B_BUX(35)));
3622 env(
offer(bob, A_BUX(30), B_BUX(30)));
3630 env.require(
balance(cam, A_BUX(35)));
3631 env.require(
balance(cam, B_BUX(35)));
3632 env.require(
offers(cam, 1));
3635 env(
offer(cam, B_BUX(30), A_BUX(30)));
3638 env.require(
balance(bob, A_BUX(30)));
3639 env.require(
balance(cam, A_BUX(5)));
3640 env.require(
balance(cam, B_BUX(65)));
3641 env.require(
offers(cam, 0));
3650 testcase(
"Self crossing low quality offer");
3652 using namespace jtx;
3654 Env env{*
this, features};
3656 auto const ann =
Account(
"ann");
3657 auto const gw =
Account(
"gateway");
3658 auto const BTC = gw[
"BTC"];
3660 auto const fee = env.current()->fees().base;
3665 env(
rate(gw, 1.002));
3666 env(
trust(ann, BTC(10)));
3669 env(
pay(gw, ann, BTC(2.856)));
3672 env(
offer(ann,
drops(365611702030), BTC(5.713)));
3676 env(
offer(ann, BTC(0.687),
drops(20000000000)),
3689 using namespace jtx;
3691 Env env{*
this, features};
3693 auto const gw =
Account(
"gateway");
3694 auto const alice =
Account(
"alice");
3695 auto const bob =
Account(
"bob");
3696 auto const CNY = gw[
"CNY"];
3698 auto const fee = env.current()->fees().base;
3703 env(
trust(bob, CNY(500)));
3706 env(
pay(gw, bob, CNY(300)));
3709 env(
offer(bob,
drops(5400000000), CNY(216.054)));
3713 env(
offer(alice, CNY(13562.0001),
drops(339000000000)));
3717 BEAST_EXPECT(aliceOffers.size() == 1);
3718 for (
auto const& offerPtr : aliceOffers)
3720 auto const&
offer = *offerPtr;
3721 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
3722 BEAST_EXPECT(
offer[sfTakerGets] ==
drops(333599446582));
3723 BEAST_EXPECT(
offer[sfTakerPays] == CNY(13345.9461));
3733 testcase(
"Offer In Scaling With Xfer Rate");
3735 using namespace jtx;
3737 Env env{*
this, features};
3739 auto const gw =
Account(
"gateway");
3740 auto const alice =
Account(
"alice");
3741 auto const bob =
Account(
"bob");
3742 auto const BTC = gw[
"BTC"];
3743 auto const JPY = gw[
"JPY"];
3745 auto const fee = env.current()->fees().base;
3750 env(
rate(gw, 1.002));
3751 env(
trust(alice, JPY(4000)));
3752 env(
trust(bob, BTC(2)));
3755 env(
pay(gw, alice, JPY(3699.034802280317)));
3756 env(
pay(gw, bob, BTC(1.156722559140311)));
3759 env(
offer(bob, JPY(1241.913390770747), BTC(0.01969825690469254)));
3763 env(
offer(alice, BTC(0.05507568706427876), JPY(3472.696773391072)));
3767 BEAST_EXPECT(aliceOffers.size() == 1);
3768 for (
auto const& offerPtr : aliceOffers)
3770 auto const&
offer = *offerPtr;
3771 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
3773 offer[sfTakerGets] ==
3775 BEAST_EXPECT(
offer[sfTakerPays] == BTC(0.035378));
3785 testcase(
"Offer Threshold With Reduced Funds");
3787 using namespace jtx;
3789 Env env{*
this, features};
3791 auto const gw1 =
Account(
"gw1");
3792 auto const gw2 =
Account(
"gw2");
3793 auto const alice =
Account(
"alice");
3794 auto const bob =
Account(
"bob");
3795 auto const USD = gw1[
"USD"];
3796 auto const JPY = gw2[
"JPY"];
3798 auto const fee = env.current()->fees().base;
3800 env.fund(
reserve(env, 2) + (
fee * 4), gw1, gw2);
3803 env(
rate(gw1, 1.002));
3804 env(
trust(alice, USD(1000)));
3805 env(
trust(bob, JPY(100000)));
3832 BEAST_EXPECT(aliceOffers.size() == 1);
3833 for (
auto const& offerPtr : aliceOffers)
3835 auto const&
offer = *offerPtr;
3836 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
3838 offer[sfTakerGets] ==
3841 offer[sfTakerPays] ==
3851 using namespace jtx;
3853 Env env{*
this, features};
3855 auto const gw =
Account(
"gw");
3856 auto const alice =
Account(
"alice");
3857 auto const bob =
Account(
"bob");
3858 auto const CNY = gw[
"CNY"];
3859 auto const fee = env.current()->fees().base;
3860 auto const startXrpBalance =
drops(400000000000) + (
fee * 2);
3862 env.fund(startXrpBalance, gw, alice, bob);
3865 env(
trust(bob, CNY(100000)));
3877 STAmount const bobsCnyStartBalance{
3879 env(
pay(gw, bob, bobsCnyStartBalance));
3888 env.require(
balance(alice, alicesCnyOffer));
3890 env.require(
balance(bob, bobsCnyStartBalance - alicesCnyOffer));
3933 using namespace jtx;
3935 Env env{*
this, features};
3936 auto const baseFee = env.current()->fees().base.drops();
3938 auto const gw =
Account(
"gw");
3939 auto const BTC = gw[
"BTC"];
3940 auto const USD = gw[
"USD"];
3941 auto const startXrpBalance =
XRP(4000000);
3943 env.fund(startXrpBalance, gw);
3946 env(
rate(gw, 1.25));
3972 TestData
const tests[]{
3974 {0, 0, 1, BTC(20), {{
"ann", 0,
drops(3900000'000000 - 4 * baseFee), BTC(20.0), USD(3000)}, {
"abe", 0,
drops(4100000'000000 - 3 * baseFee), BTC( 0), USD(750)}}},
3975 {0, 1, 0, BTC(20), {{
"bev", 0,
drops(4100000'000000 - 4 * baseFee), BTC( 7.5), USD(2000)}, {
"bob", 0,
drops(3900000'000000 - 3 * baseFee), BTC(10), USD( 0)}}},
3976 {0, 0, 0, BTC(20), {{
"cam", 0,
drops(4000000'000000 - 5 * baseFee), BTC(20.0), USD(2000)} }},
3977 {0, 1, 0, BTC( 5), {{
"deb", 1,
drops(4040000'000000 - 4 * baseFee), BTC( 0.0), USD(2000)}, {
"dan", 1,
drops(3960000'000000 - 3 * baseFee), BTC( 4), USD( 0)}}},
3981 for (
auto const& t : tests)
3983 Account const& self = t.actors[t.self].acct;
3984 Account const& leg0 = t.actors[t.leg0].acct;
3985 Account const& leg1 = t.actors[t.leg1].acct;
3987 for (
auto const& actor : t.actors)
3989 env.fund(
XRP(4000000), actor.acct);
3992 env(
trust(actor.acct, BTC(40)));
3993 env(
trust(actor.acct, USD(8000)));
3997 env(
pay(gw, self, t.btcStart));
3998 env(
pay(gw, self, USD(2000)));
3999 if (self.
id() != leg1.
id())
4000 env(
pay(gw, leg1, USD(2000)));
4014 env(
offer(self, USD(1000), BTC(10)));
4019 for (
auto const& actor : t.actors)
4025 actorOffers.begin(),
4027 actorOffers.begin(),
4030 return (*offer)[sfTakerGets].signum() == 0;
4032 BEAST_EXPECT(offerCount == actor.offers);
4034 env.require(
balance(actor.acct, actor.xrp));
4035 env.require(
balance(actor.acct, actor.btc));
4036 env.require(
balance(actor.acct, actor.usd));
4052 testcase(
"Self Pay Unlimited Funds");
4084 using namespace jtx;
4086 Env env{*
this, features};
4087 auto const baseFee = env.current()->fees().base.drops();
4089 auto const gw =
Account(
"gw");
4090 auto const BTC = gw[
"BTC"];
4091 auto const USD = gw[
"USD"];
4092 auto const startXrpBalance =
XRP(4000000);
4094 env.fund(startXrpBalance, gw);
4097 env(
rate(gw, 1.25));
4123 TestData
const tests[]{
4125 {0, 0, 1, BTC(5), {{
"gay", 1,
drops(3950000'000000 - 4 * baseFee), BTC(5), USD(2500)}, {
"gar", 1,
drops(4050000'000000 - 3 * baseFee), BTC(0), USD(1375)}}},
4126 {0, 0, 0, BTC(5), {{
"hye", 2,
drops(4000000'000000 - 5 * baseFee), BTC(5), USD(2000)} }}
4130 for (
auto const& t : tests)
4132 Account const& self = t.actors[t.self].acct;
4133 Account const& leg0 = t.actors[t.leg0].acct;
4134 Account const& leg1 = t.actors[t.leg1].acct;
4136 for (
auto const& actor : t.actors)
4138 env.fund(
XRP(4000000), actor.acct);
4141 env(
trust(actor.acct, BTC(40)));
4142 env(
trust(actor.acct, USD(8000)));
4146 env(
pay(gw, self, t.btcStart));
4147 env(
pay(gw, self, USD(2000)));
4148 if (self.
id() != leg1.
id())
4149 env(
pay(gw, leg1, USD(2000)));
4163 env(
offer(self, USD(1000), BTC(10)));
4168 for (
auto const& actor : t.actors)
4174 actorOffers.begin(),
4176 actorOffers.begin(),
4179 return (*offer)[sfTakerGets].signum() == 0;
4181 BEAST_EXPECT(offerCount == actor.offers);
4183 env.require(
balance(actor.acct, actor.xrp));
4184 env.require(
balance(actor.acct, actor.btc));
4185 env.require(
balance(actor.acct, actor.usd));
4203 using namespace jtx;
4205 Env env{*
this, features};
4207 auto const gw =
Account(
"gw");
4208 auto const alice =
Account(
"alice");
4209 auto const bob =
Account(
"bob");
4210 auto const gwUSD = gw[
"USD"];
4211 auto const aliceUSD = alice[
"USD"];
4212 auto const bobUSD = bob[
"USD"];
4214 env.fund(
XRP(400000), gw, alice, bob);
4223 env(
trust(bob, gwUSD(100)));
4225 env(
trust(alice, gwUSD(100)));
4227 env(
offer(alice, gwUSD(40),
XRP(4000)));
4230 env.require(
offers(alice, 1));
4231 env.require(
balance(alice, gwUSD(0)));
4233 env(
pay(gw, bob, gwUSD(50)));
4236 env.require(
balance(bob, gwUSD(50)));
4239 env(
offer(bob,
XRP(4000), gwUSD(40)));
4242 env.require(
offers(alice, 0));
4243 env.require(
balance(alice, gwUSD(40)));
4245 env.require(
offers(bob, 0));
4246 env.require(
balance(bob, gwUSD(10)));
4271 using namespace jtx;
4273 Env env{*
this, features};
4275 auto const gw =
Account(
"gw");
4276 auto const alice =
Account(
"alice");
4277 auto const bob =
Account(
"bob");
4278 auto const gwUSD = gw[
"USD"];
4279 auto const aliceUSD = alice[
"USD"];
4280 auto const bobUSD = bob[
"USD"];
4282 env.fund(
XRP(400000), gw, alice, bob);
4285 env(
offer(alice, gwUSD(40),
XRP(4000)));
4288 env.require(
offers(alice, 1));
4295 env(
trust(bob, gwUSD(100)));
4298 env(
pay(gw, bob, gwUSD(50)));
4300 env.require(
balance(bob, gwUSD(50)));
4307 env(
offer(bob,
XRP(4000), gwUSD(40)));
4311 env.require(
offers(alice, 0));
4314 env.require(
offers(bob, 1));
4315 env.require(
balance(bob, gwUSD(50)));
4323 env.require(
offers(alice, 0));
4326 env.require(
offers(bob, 1));
4327 env.require(
balance(bob, gwUSD(50)));
4331 env(
trust(gw, aliceUSD(100)));
4337 env.require(
offers(alice, 0));
4338 env.require(
balance(alice, gwUSD(0)));
4340 env.require(
offers(bob, 1));
4341 env.require(
balance(bob, gwUSD(50)));
4346 env.require(
offers(bob, 0));
4354 env(
offer(alice, gwUSD(40),
XRP(4000)));
4357 env.require(
offers(alice, 1));
4360 env(
offer(bob,
XRP(4000), gwUSD(40)));
4363 env.require(
offers(alice, 0));
4364 env.require(
balance(alice, gwUSD(40)));
4366 env.require(
offers(bob, 0));
4367 env.require(
balance(bob, gwUSD(10)));
4373 testcase(
"RippleConnect Smoketest payment flow");
4374 using namespace jtx;
4376 Env env{*
this, features};
4386 auto const hotUS =
Account(
"hotUS");
4387 auto const coldUS =
Account(
"coldUS");
4388 auto const hotEU =
Account(
"hotEU");
4389 auto const coldEU =
Account(
"coldEU");
4390 auto const mm =
Account(
"mm");
4392 auto const USD = coldUS[
"USD"];
4393 auto const EUR = coldEU[
"EUR"];
4395 env.fund(
XRP(100000), hotUS, coldUS, hotEU, coldEU, mm);
4399 for (
auto const& cold : {coldUS, coldEU})
4422 env(
pay(coldUS, hotUS, USD(5000000)));
4423 env(
pay(coldEU, hotEU, EUR(5000000)));
4424 env(
pay(coldUS, mm, USD(5000000)));
4425 env(
pay(coldEU, mm, EUR(5000000)));
4429 float const rate = 0.9f;
4430 env(
offer(mm, EUR(4000000 *
rate), USD(4000000)),
4433 float const reverseRate = 1.0f /
rate * 1.00101f;
4434 env(
offer(mm, USD(4000000 * reverseRate), EUR(4000000)),
4441 jvParams[jss::destination_account] = coldEU.human();
4442 jvParams[jss::destination_amount][jss::issuer] = coldEU.human();
4443 jvParams[jss::destination_amount][jss::currency] =
"EUR";
4444 jvParams[jss::destination_amount][jss::value] = 10;
4445 jvParams[jss::source_account] = hotUS.human();
4448 "json",
"ripple_path_find",
to_string(jvParams))[jss::result]};
4450 BEAST_EXPECT(jrr[jss::status] ==
"success");
4452 jrr[jss::alternatives].isArray() &&
4453 jrr[jss::alternatives].size() > 0);
4456 env(
pay(hotUS, coldEU, EUR(10)),
sendmax(USD(11.1223326)));
4464 using namespace jtx;
4466 Env env{*
this, features};
4468 auto const gw =
Account(
"gw");
4469 auto const alice =
Account(
"alice");
4470 auto const gwUSD = gw[
"USD"];
4471 auto const aliceUSD = alice[
"USD"];
4473 env.fund(
XRP(400000), gw, alice);
4477 env(
offer(gw, gwUSD(40),
XRP(4000)));
4480 env.require(
offers(gw, 1));
4489 env.require(
offers(gw, 0));
4501 env.require(
offers(gw, 1));
4505 env(
trust(alice, gwUSD(100)));
4508 env(
pay(gw, alice, gwUSD(50)));
4511 env.require(
balance(alice, gwUSD(50)));
4514 env(
offer(alice,
XRP(4000), gwUSD(40)));
4517 env.require(
offers(alice, 0));
4518 env.require(
balance(alice, gwUSD(10)));
4520 env.require(
offers(gw, 0));
4527 using namespace jtx;
4531 auto trustLineExists = [](
jtx::Env const& env,
4542 auto const USD = gw[
"USD"];
4543 auto const BUX = alice[
"BUX"];
4545 Env env{*
this, features};
4549 env.
trust(USD(1000), becky);
4550 env(
pay(gw, becky, USD(5)));
4552 BEAST_EXPECT(trustLineExists(env, gw, becky, USD.currency));
4563 env(
pay(becky, gw, USD(5)));
4564 env.
trust(USD(0), becky);
4566 BEAST_EXPECT(!trustLineExists(env, gw, becky, USD.currency));
4567 BEAST_EXPECT(
isOffer(env, becky,
XRP(2), USD(2)));
4568 BEAST_EXPECT(
isOffer(env, becky, BUX(3), USD(3)));
4575 [&env, &gw, openLedgerSeq = env.
current()->seq()]() ->
int {
4577 if (gwSeq + 255 > openLedgerSeq)
4578 return gwSeq - openLedgerSeq + 255;
4582 for (
int i = 0; i < delta; ++i)
4599 BEAST_EXPECT(
isOffer(env, becky,
XRP(2), USD(2)));
4600 BEAST_EXPECT(
isOffer(env, becky, BUX(3), USD(3)));
4606 BEAST_EXPECT(
isOffer(env, becky,
XRP(2), USD(2)));
4607 BEAST_EXPECT(
isOffer(env, becky, BUX(3), USD(3)));
4612 BEAST_EXPECT(!
isOffer(env, becky, BUX(3), USD(3)));
4616 env.
trust(BUX(1000), carol);
4617 env(
pay(alice, carol, BUX(2)));
4626 BEAST_EXPECT(
isOffer(env, alice, BUX(2),
XRP(2)));
4627 BEAST_EXPECT(
isOffer(env, becky,
XRP(2), USD(2)));
4635 using namespace jtx;
4639 Env env{*
this, features};
4640 auto const gw =
Account{
"gateway"};
4641 env.fund(
XRP(10000), gw);
4644 auto txn =
noop(gw);
4645 txn[sfTickSize.fieldName] = Quality::minTickSize - 1;
4648 txn[sfTickSize.fieldName] = Quality::minTickSize;
4650 BEAST_EXPECT((*env.le(gw))[sfTickSize] == Quality::minTickSize);
4653 txn[sfTickSize.fieldName] = Quality::maxTickSize;
4655 BEAST_EXPECT(!env.le(gw)->isFieldPresent(sfTickSize));
4658 txn[sfTickSize.fieldName] = Quality::maxTickSize - 1;
4660 BEAST_EXPECT((*env.le(gw))[sfTickSize] == Quality::maxTickSize - 1);
4663 txn[sfTickSize.fieldName] = Quality::maxTickSize + 1;
4666 txn[sfTickSize.fieldName] = 0;
4668 BEAST_EXPECT(!env.le(gw)->isFieldPresent(sfTickSize));
4671 Env env{*
this, features};
4672 auto const gw =
Account{
"gateway"};
4673 auto const alice =
Account{
"alice"};
4674 auto const XTS = gw[
"XTS"];
4675 auto const XXX = gw[
"XXX"];
4677 env.fund(
XRP(10000), gw, alice);
4682 auto txn =
noop(gw);
4683 txn[sfTickSize.fieldName] = 5;
4685 BEAST_EXPECT((*env.le(gw))[sfTickSize] == 5);
4688 env(
trust(alice, XTS(1000)));
4689 env(
trust(alice, XXX(1000)));
4691 env(
pay(gw, alice, alice[
"XTS"](100)));
4692 env(
pay(gw, alice, alice[
"XXX"](100)));
4694 env(
offer(alice, XTS(10), XXX(30)));
4695 env(
offer(alice, XTS(30), XXX(10)));
4702 if (sle->getType() == ltOFFER)
4706 (*sle)[sfTakerPays], (*sle)[sfTakerGets]));
4710 auto it =
offers.begin();
4711 BEAST_EXPECT(it !=
offers.end());
4713 it->second.first == XTS(10) && it->second.second < XXX(30) &&
4714 it->second.second > XXX(29.9994));
4718 BEAST_EXPECT(it !=
offers.end());
4720 it->second.first == XTS(30) && it->second.second == XXX(10));
4724 BEAST_EXPECT(it !=
offers.end());
4726 it->second.first == XTS(10.0002) && it->second.second == XXX(30));
4731 BEAST_EXPECT(it !=
offers.end());
4733 it->second.first == XTS(30) && it->second.second == XXX(10));
4735 BEAST_EXPECT(++it ==
offers.end());
4749 return (*rhs)[sfSequence] < (*lhs)[sfSequence];
4759 using namespace jtx;
4767 Env env{*
this, features};
4768 auto const gw =
Account{
"gateway"};
4769 auto const alice =
Account{
"alice"};
4770 auto const bob =
Account{
"bob"};
4771 auto const USD = gw[
"USD"];
4773 env.fund(
XRP(10000), gw, alice, bob);
4776 env(
trust(alice, USD(1000)));
4777 env(
trust(bob, USD(1000)));
4780 env(
pay(gw, alice, USD(200)));
4787 env(
offer(alice,
XRP(50), USD(50)));
4797 BEAST_EXPECT(offerId_1 == offerId_0 + 4);
4798 env(
offer(alice,
XRP(50), USD(50)));
4814 BEAST_EXPECT(
offers.size() == 4);
4815 BEAST_EXPECT(
offers[0]->getFieldU32(sfSequence) == offerId_0);
4816 BEAST_EXPECT(
offers[1]->getFieldU32(sfSequence) == offerId_3);
4817 BEAST_EXPECT(
offers[2]->getFieldU32(sfSequence) == offerId_2);
4818 BEAST_EXPECT(
offers[3]->getFieldU32(sfSequence) == offerId_1);
4819 env.require(
balance(alice, USD(200)));
4820 env.require(
owners(alice, 5));
4830 BEAST_EXPECT(
offers.size() == 3);
4831 BEAST_EXPECT(
offers[0]->getFieldU32(sfSequence) == offerId_3);
4832 BEAST_EXPECT(
offers[1]->getFieldU32(sfSequence) == offerId_2);
4833 BEAST_EXPECT(
offers[2]->getFieldU32(sfSequence) == offerId_1);
4843 BEAST_EXPECT(
offers.size() == 2);
4844 BEAST_EXPECT(
offers[0]->getFieldU32(sfSequence) == offerId_3);
4845 BEAST_EXPECT(
offers[1]->getFieldU32(sfSequence) == offerId_2);
4855 BEAST_EXPECT(
offers.size() == 1);
4856 BEAST_EXPECT(
offers[0]->getFieldU32(sfSequence) == offerId_3);
4866 BEAST_EXPECT(
offers.size() == 0);
4868 env.require(
balance(alice, USD(0)));
4869 env.require(
owners(alice, 1));
4870 env.require(
balance(bob, USD(200)));
4871 env.require(
owners(bob, 1));
4879 using namespace jtx;
4883 Env env{*
this, features};
4884 auto const gw =
Account{
"gateway"};
4885 auto const alice =
Account{
"alice"};
4886 auto const USD = gw[
"USD"];
4888 env.fund(
XRP(10000), gw, alice);
4891 env(
trust(alice, USD(1000)));
4895 env(
pay(gw, alice, USD(200)));
4900 env(
offer(alice,
XRP(50), USD(50)));
4912 BEAST_EXPECT(offerSeqId_1 == offerSeqId_0 + 6);
4913 env(
offer(alice,
XRP(50), USD(50)));
4929 BEAST_EXPECT(
offers.size() == 4);
4930 BEAST_EXPECT(
offers[0]->getFieldU32(sfSequence) == offerSeqId_0);
4931 BEAST_EXPECT(
offers[1]->getFieldU32(sfSequence) == offerTixId_1);
4932 BEAST_EXPECT(
offers[2]->getFieldU32(sfSequence) == offerTixId_0);
4933 BEAST_EXPECT(
offers[3]->getFieldU32(sfSequence) == offerSeqId_1);
4934 env.require(
balance(alice, USD(200)));
4935 env.require(
owners(alice, 7));
4945 BEAST_EXPECT(
offers.size() == 3);
4946 BEAST_EXPECT(
offers[0]->getFieldU32(sfSequence) == offerTixId_1);
4947 BEAST_EXPECT(
offers[1]->getFieldU32(sfSequence) == offerTixId_0);
4948 BEAST_EXPECT(
offers[2]->getFieldU32(sfSequence) == offerSeqId_1);
4958 BEAST_EXPECT(
offers.size() == 2);
4959 BEAST_EXPECT(
offers[0]->getFieldU32(sfSequence) == offerTixId_1);
4960 BEAST_EXPECT(
offers[1]->getFieldU32(sfSequence) == offerSeqId_1);
4973 BEAST_EXPECT(
offers.size() == 1);
4974 BEAST_EXPECT(
offers[0]->getFieldU32(sfSequence) == offerSeqId_1);
4991 testcase(
"incorrect assert fixed");
4992 using namespace jtx;
4995 auto const alice =
Account(
"alice");
4996 auto const USD = alice[
"USD"];
4998 env.fund(
XRP(10000), alice);
5000 env(
offer(alice,
XRP(100000000000), USD(100000000)));
5008 using namespace jtx;
5009 Env env(*
this, features);
5010 Account const issuer(
"issuer");
5013 auto const USD = issuer[
"USD"];
5014 auto const EUR = issuer[
"EUR"];
5017 env.
fund(
XRP(1'000), maker, taker);
5020 env.
trust(USD(1'000), maker, taker);
5021 env.
trust(EUR(1'000), maker, taker);
5024 env(
pay(issuer, maker, USD(1'000)));
5025 env(
pay(issuer, taker, USD(1'000)));
5026 env(
pay(issuer, maker, EUR(1'000)));
5029 auto makerUSDBalance = env.
balance(maker, USD).
value();
5030 auto takerUSDBalance = env.
balance(taker, USD).
value();
5031 auto makerEURBalance = env.
balance(maker, EUR).
value();
5032 auto takerEURBalance = env.
balance(taker, EUR).
value();
5041 env(
offer(maker,
XRP(100), USD(100)));
5044 env(
offer(taker, USD(100),
XRP(101)),
5049 makerXRPBalance -=
txfee(env, 1);
5050 takerXRPBalance -=
txfee(env, 1);
5053 makerUSDBalance -= USD(100);
5054 takerUSDBalance += USD(100);
5055 makerXRPBalance +=
XRP(100).value();
5056 takerXRPBalance -=
XRP(100).value();
5060 env(
offer(maker, USD(100),
XRP(100)));
5063 env(
offer(taker,
XRP(100), USD(101)),
5068 makerXRPBalance -=
txfee(env, 1);
5069 takerXRPBalance -=
txfee(env, 1);
5072 makerUSDBalance += USD(100);
5073 takerUSDBalance -= USD(100);
5074 makerXRPBalance -=
XRP(100).value();
5075 takerXRPBalance +=
XRP(100).value();
5079 env(
offer(maker, USD(100), EUR(100)));
5082 env(
offer(taker, EUR(100), USD(101)),
5087 makerXRPBalance -=
txfee(env, 1);
5088 takerXRPBalance -=
txfee(env, 1);
5091 makerUSDBalance += USD(100);
5092 takerUSDBalance -= USD(100);
5093 makerEURBalance -= EUR(100);
5094 takerEURBalance += EUR(100);
5101 env(
offer(maker,
XRP(101), USD(101)));
5104 env(
offer(taker, USD(100),
XRP(101)),
5108 makerUSDBalance -= USD(101);
5109 takerUSDBalance += USD(101);
5110 makerXRPBalance +=
XRP(101).value() -
txfee(env, 1);
5111 takerXRPBalance -=
XRP(101).value() +
txfee(env, 1);
5114 env(
offer(maker, USD(101),
XRP(101)));
5117 env(
offer(taker,
XRP(100), USD(101)),
5121 makerUSDBalance += USD(101);
5122 takerUSDBalance -= USD(101);
5123 makerXRPBalance -=
XRP(101).value() +
txfee(env, 1);
5124 takerXRPBalance +=
XRP(101).value() -
txfee(env, 1);
5127 env(
offer(maker, USD(101), EUR(101)));
5130 env(
offer(taker, EUR(100), USD(101)),
5134 makerUSDBalance += USD(101);
5135 takerUSDBalance -= USD(101);
5136 makerEURBalance -= EUR(101);
5137 takerEURBalance += EUR(101);
5138 makerXRPBalance -=
txfee(env, 1);
5139 takerXRPBalance -=
txfee(env, 1);
5146 env(
offer(maker,
XRP(100), USD(100)));
5149 env(
offer(taker, USD(100),
XRP(99)),
5154 makerXRPBalance -=
txfee(env, 1);
5155 takerXRPBalance -=
txfee(env, 1);
5158 env(
offer(maker, USD(100),
XRP(100)));
5161 env(
offer(taker,
XRP(100), USD(99)),
5166 makerXRPBalance -=
txfee(env, 1);
5167 takerXRPBalance -=
txfee(env, 1);
5170 env(
offer(maker, USD(100), EUR(100)));
5173 env(
offer(taker, EUR(100), USD(99)),
5178 makerXRPBalance -=
txfee(env, 1);
5179 takerXRPBalance -=
txfee(env, 1);
5184 env.
balance(maker, USD) == makerUSDBalance &&
5185 env.
balance(taker, USD) == takerUSDBalance &&
5186 env.
balance(maker, EUR) == makerEURBalance &&
5187 env.
balance(taker, EUR) == takerEURBalance &&
5188 env.
balance(maker,
XRP) == makerXRPBalance &&
5289 using namespace jtx;
5300BEAST_DEFINE_TESTSUITE_PRIO(OfferBaseUtil, app,
ripple, 2);
5301BEAST_DEFINE_TESTSUITE_PRIO(OfferWOSmallQOffers, app,
ripple, 2);
5302BEAST_DEFINE_TESTSUITE_PRIO(OfferAllFeatures, app,
ripple, 2);
5303BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(Offer_manual, app,
ripple, 20);
void pass()
Record a successful test condition.
testcase_t testcase
Memberspace for declaring test cases.
A currency issued by an account.
std::string getText() const override
Issue const & issue() const
void run() override
Runs the suite.
void testSelfCrossOffer2(FeatureBitset features)
void run() override
Runs the suite.
void testMissingAuth(FeatureBitset features)
void testSelfAuth(FeatureBitset features)
void testSelfCross(bool use_partner, FeatureBitset features)
void testCrossCurrencyBridged(FeatureBitset features)
void testAll(FeatureBitset features)
void testSelfIssueOffer(FeatureBitset features)
void testRCSmoketest(FeatureBitset features)
void testExpiration(FeatureBitset features)
void testUnfundedCross(FeatureBitset features)
void testCrossCurrencyStartXRP(FeatureBitset features)
static std::vector< std::shared_ptr< SLE const > > offersOnAccount(jtx::Env &env, jtx::Account account)
void testRmSmallIncreasedQOffersIOU(FeatureBitset features)
void testSellWithFillOrKill(FeatureBitset features)
void testTinyOffer(FeatureBitset features)
void testInsufficientReserve(FeatureBitset features)
void testDirectCross(FeatureBitset features)
void testOfferThresholdWithReducedFunds(FeatureBitset features)
void testRequireAuth(FeatureBitset features)
void verifyDefaultTrustline(jtx::Env &env, jtx::Account const &account, jtx::PrettyAmount const &expectBalance)
void testRmSmallIncreasedQOffersXRP(FeatureBitset features)
void testDirectToDirectPath(FeatureBitset features)
void testRmFundedOffer(FeatureBitset features)
void testOfferFeesConsumeFunds(FeatureBitset features)
void testTickSize(FeatureBitset features)
void testTicketOffer(FeatureBitset features)
void testOfferCreateThenCross(FeatureBitset features)
void testFillOrKill(FeatureBitset features)
void testSelfPayUnlimitedFunds(FeatureBitset features)
void testOfferCancelPastAndFuture(FeatureBitset features)
void testSellFlagBasic(FeatureBitset features)
void testBridgedCross(FeatureBitset features)
void testXRPDirectCross(FeatureBitset features)
void testDeletedOfferIssuer(FeatureBitset features)
void testXRPTinyPayment(FeatureBitset features)
void testTransferRateOffer(FeatureBitset features)
void testPartialCross(FeatureBitset features)
static std::vector< std::shared_ptr< SLE const > > sortedOffersOnAccount(jtx::Env &env, jtx::Account const &acct)
void testCurrencyConversionIntoDebt(FeatureBitset features)
void testMalformed(FeatureBitset features)
void testOfferCrossWithXRP(bool reverse_order, FeatureBitset features)
void testFillModes(FeatureBitset features)
void testOfferInScaling(FeatureBitset features)
void testOfferInScalingWithXferRate(FeatureBitset features)
static auto ledgerEntryOffer(jtx::Env &env, jtx::Account const &acct, std::uint32_t offer_seq)
void testCurrencyConversionEntire(FeatureBitset features)
void testSelfPayXferFeeOffer(FeatureBitset features)
void testCurrencyConversionInParts(FeatureBitset features)
void testBridgedSecondLegDry(FeatureBitset features)
void testSellOffer(FeatureBitset features)
void testCrossCurrencyEndXRP(FeatureBitset features)
void testGatewayCrossCurrency(FeatureBitset features)
void testNegativeBalance(FeatureBitset features)
static auto getBookOffers(jtx::Env &env, Issue const &taker_pays, Issue const &taker_gets)
void testSelfCrossOffer(FeatureBitset features)
std::uint32_t lastClose(jtx::Env &env)
void testSelfCrossOffer1(FeatureBitset features)
XRPAmount reserve(jtx::Env &env, std::uint32_t count)
void testOfferCrossWithLimitOverride(FeatureBitset features)
void testTicketCancelOffer(FeatureBitset features)
void testSelfCrossLowQualityOffer(FeatureBitset features)
FeatureBitset const allFeatures
void testOfferAcceptThenCancel(FeatureBitset features)
void testSellFlagExceedLimit(FeatureBitset features)
void testCanceledOffer(FeatureBitset features)
void testBadPathAssert(FeatureBitset features)
void testTinyPayment(FeatureBitset features)
void testEnforceNoRipple(FeatureBitset features)
void run() override
Runs the suite.
void run() override
Runs the suite.
Immutable cryptographic account descriptor.
AccountID id() const
Returns the Account ID.
std::string const & human() const
Returns the human readable public key.
A transaction testing environment.
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
void require(Args const &... args)
Check a set of requirements.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
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 fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
std::shared_ptr< SLE const > le(Account const &account) const
Return an account root.
Converts to IOU Issue or STAmount.
Match the number of items in the account's owner directory.
Set Paths, SendMax on a JTx.
Sets the QualityIn on a trust JTx.
Sets the QualityOut on a trust JTx as a percentage.
Check a set of conditions.
Sets the SendMax on a JTx.
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.
@ arrayValue
array value (ordered list)
Keylet line(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
Keylet account(AccountID const &id) noexcept
AccountID root.
Json::Value create(Account const &account, std::uint32_t count)
Create one of more tickets.
owner_count< ltRIPPLE_STATE > lines
Match the number of trust lines in the account's owner directory.
Json::Value ledgerEntryRoot(Env &env, Account const &acct)
owner_count< ltOFFER > offers
Match the number of offers in the account's owner directory.
bool expectOffers(Env &env, AccountID const &account, std::uint16_t size, std::vector< Amounts > const &toMatch)
PrettyAmount xrpMinusFee(Env const &env, std::int64_t xrpAmount)
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Json::Value ledgerEntryState(Env &env, Account const &acct_a, Account const &acct_b, std::string const ¤cy)
static epsilon_t const epsilon
FeatureBitset testable_amendments()
Json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
Json::Value acctdelete(Account const &account, Account const &dest)
Delete account.
owner_count< ltTICKET > tickets
Match the number of tickets on the account.
XRP_t const XRP
Converts to XRP Issue or STAmount.
XRPAmount txfee(Env const &env, std::uint16_t n)
Json::Value offer_cancel(Account const &account, std::uint32_t offerSeq)
Cancel an offer.
bool isOffer(jtx::Env &env, jtx::Account const &account, STAmount const &takerPays, STAmount const &takerGets)
An offer exists.
std::unique_ptr< WSClient > makeWSClient(Config const &cfg, bool v2, unsigned rpc_version, std::unordered_map< std::string, std::string > const &headers)
Returns a client operating through WebSockets/S.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
constexpr std::uint32_t tfFillOrKill
constexpr std::uint32_t tfPassive
constexpr std::uint32_t tfImmediateOrCancel
void forEachItem(ReadView const &view, Keylet const &root, std::function< void(std::shared_ptr< SLE const > const &)> const &f)
Iterate all items in the given directory.
constexpr std::uint32_t tfPartialPayment
constexpr std::uint32_t tfSetfAuth
constexpr std::uint32_t asfDefaultRipple
constexpr std::uint32_t tfNoRippleDirect
std::string to_string(base_uint< Bits, Tag > const &a)
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
constexpr std::uint32_t tfSell
constexpr std::uint32_t asfRequireAuth
Seed generateSeed(std::string const &passPhrase)
Generate a seed deterministically.
TERSubset< CanCvtToTER > TER
constexpr std::uint32_t tfSetNoRipple
Represents an XRP or IOU quantity This customizes the string conversion and supports XRP conversions ...
STAmount const & value() const