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 bool const featPreauth{features[featureDepositPreauth]};
188 json(jss::OfferSequence, offer2Seq),
192 env.require(
offers(alice, 2));
193 BEAST_EXPECT(
isOffer(env, alice,
XRP(300), USD(100)));
194 BEAST_EXPECT(!
isOffer(env, alice,
XRP(5), USD(2)));
204 using namespace std::chrono_literals;
205 auto const alice =
Account{
"alice"};
206 auto const bob =
Account{
"bob"};
207 auto const carol =
Account{
"carol"};
210 auto const USD = gw[
"USD"];
211 auto const EUR = gw[
"EUR"];
213 Env env{*
this, features};
215 env.fund(
XRP(10000), alice, bob, carol, gw);
217 env.trust(USD(1000), alice, bob, carol);
218 env.trust(EUR(1000), alice, bob, carol);
219 env(
pay(gw, alice, USD(100)));
220 env(
pay(gw, carol, EUR(100)));
226 for (
int i = 0; i < 101; ++i)
227 env(
offer(carol, USD(1), EUR(2)));
253 using namespace std::chrono_literals;
254 auto const alice =
Account{
"alice"};
255 auto const bob =
Account{
"bob"};
256 auto const carol =
Account{
"carol"};
257 auto const dan =
Account{
"dan"};
258 auto const erin =
Account{
"erin"};
261 auto const USD = gw[
"USD"];
262 Env env{*
this, features};
264 env.fund(
XRP(10000), alice, bob, carol, dan, erin, gw);
266 env.trust(USD(1000), alice, bob, carol, dan, erin);
268 env(
pay(gw, carol, USD(0.99999)));
269 env(
pay(gw, dan, USD(1)));
270 env(
pay(gw, erin, USD(1)));
292 env(
pay(alice, bob, USD(1)),
307 testcase(
"Rm small increased q offers XRP");
315 using namespace std::chrono_literals;
316 auto const alice =
Account{
"alice"};
317 auto const bob =
Account{
"bob"};
318 auto const carol =
Account{
"carol"};
321 auto const USD = gw[
"USD"];
324 for (
auto crossBothOffers : {
false,
true})
326 Env env{*
this, features};
328 env.fund(
XRP(10000), alice, bob, carol, gw);
330 env.trust(USD(1000), alice, bob, carol);
332 auto initialCarolUSD = USD(0.499);
333 env(
pay(gw, carol, initialCarolUSD));
334 env(
pay(gw, bob, USD(100)));
346 auto aliceTakerGets = crossBothOffers ?
drops(2) :
drops(1);
347 env(
offer(alice, USD(1), aliceTakerGets));
370 for (
auto partialPayment : {
false,
true})
372 Env env{*
this, features};
374 env.fund(
XRP(10000), alice, bob, carol, gw);
376 env.trust(USD(1000), alice, bob, carol);
378 auto const initialCarolUSD = USD(0.999);
379 env(
pay(gw, carol, initialCarolUSD));
381 env(
pay(gw, bob, USD(100)));
393 TER const expectedTer =
396 env(
pay(alice, bob, USD(5)),
405 env.require(
offers(carol, 0));
423 testcase(
"Rm small increased q offers IOU");
431 using namespace std::chrono_literals;
432 auto const alice =
Account{
"alice"};
433 auto const bob =
Account{
"bob"};
434 auto const carol =
Account{
"carol"};
437 auto const USD = gw[
"USD"];
438 auto const EUR = gw[
"EUR"];
449 for (
auto crossBothOffers : {
false,
true})
451 Env env{*
this, features};
453 env.fund(
XRP(10000), alice, bob, carol, gw);
455 env.trust(USD(1000), alice, bob, carol);
456 env.trust(EUR(1000), alice, bob, carol);
458 auto initialCarolUSD = tinyAmount(USD);
459 env(
pay(gw, carol, initialCarolUSD));
460 env(
pay(gw, bob, USD(100)));
461 env(
pay(gw, alice, EUR(100)));
464 env(
offer(carol, EUR(1), USD(10)));
474 auto aliceTakerGets = crossBothOffers ? EUR(0.2) : EUR(0.1);
475 env(
offer(alice, USD(1), aliceTakerGets));
498 for (
auto partialPayment : {
false,
true})
500 Env env{*
this, features};
502 env.fund(
XRP(10000), alice, bob, carol, gw);
504 env.trust(USD(1000), alice, bob, carol);
505 env.trust(EUR(1000), alice, bob, carol);
508 auto const initialCarolUSD = tinyAmount(USD);
509 env(
pay(gw, carol, initialCarolUSD));
510 env(
pay(gw, bob, USD(100)));
511 env(
pay(gw, alice, EUR(100)));
514 env(
offer(carol, EUR(1), USD(2)));
524 TER const expectedTer =
527 env(
pay(alice, bob, USD(5)),
536 env.require(
offers(carol, 0));
558 auto const gw =
Account{
"gateway"};
559 auto const USD = gw[
"USD"];
560 auto const BTC = gw[
"BTC"];
561 auto const EUR = gw[
"EUR"];
569 Env env{*
this, features};
571 auto const gw1 =
Account{
"gw1"};
572 auto const USD1 = gw1[
"USD"];
573 auto const gw2 =
Account{
"gw2"};
574 auto const USD2 = gw2[
"USD"];
576 env.fund(
XRP(10000), alice,
noripple(bob), carol, dan, gw1, gw2);
578 env.trust(USD1(1000), alice, carol, dan);
580 env.trust(USD2(1000), alice, carol, dan);
583 env(
pay(gw1, dan, USD1(50)));
584 env(
pay(gw1, bob, USD1(50)));
585 env(
pay(gw2, bob, USD2(50)));
589 env(
pay(alice, carol, USD2(50)),
597 Env env{*
this, features};
599 auto const gw1 =
Account{
"gw1"};
600 auto const USD1 = gw1[
"USD"];
601 auto const gw2 =
Account{
"gw2"};
602 auto const USD2 = gw2[
"USD"];
604 env.fund(
XRP(10000), alice, bob, carol, dan, gw1, gw2);
606 env.trust(USD1(1000), alice, bob, carol, dan);
607 env.trust(USD2(1000), alice, bob, carol, dan);
609 env(
pay(gw1, dan, USD1(50)));
610 env(
pay(gw1, bob, USD1(50)));
611 env(
pay(gw2, bob, USD2(50)));
615 env(
pay(alice, carol, USD2(50)),
621 env.require(
balance(bob, USD1(100)));
622 env.require(
balance(bob, USD2(0)));
623 env.require(
balance(carol, USD2(50)));
640 auto const gw =
Account{
"gateway"};
641 auto const alice =
Account{
"alice"};
642 auto const bob =
Account{
"bob"};
643 auto const carol =
Account{
"carol"};
644 auto const USD = gw[
"USD"];
646 auto const usdOffer = USD(1000);
647 auto const xrpOffer =
XRP(1000);
651 Env env{*
this, features};
653 env.fund(
XRP(1000000), gw);
655 auto const f = env.current()->fees().base;
656 auto const r =
reserve(env, 0);
658 env.fund(r + f, alice);
669 Env env{*
this, features};
671 env.fund(
XRP(1000000), gw);
673 auto const f = env.current()->fees().base;
674 auto const r =
reserve(env, 0);
676 auto const usdOffer2 = USD(500);
677 auto const xrpOffer2 =
XRP(500);
679 env.fund(r + f + xrpOffer, bob);
682 env.fund(r + f, alice);
689 balance(alice, r - f + xrpOffer2),
701 Env env{*
this, features};
703 env.fund(
XRP(1000000), gw);
705 auto const f = env.current()->fees().base;
706 auto const r =
reserve(env, 0);
708 auto const usdOffer2 = USD(500);
709 auto const xrpOffer2 =
XRP(500);
711 env.fund(r + f + xrpOffer, bob, carol);
716 env.fund(r + f, alice);
723 balance(alice, r - f + xrpOffer),
744 if (sle->getType() == ltOFFER)
745 result.push_back(sle);
757 auto const startBalance =
XRP(1000000);
758 auto const gw =
Account{
"gateway"};
759 auto const alice =
Account{
"alice"};
760 auto const bob =
Account{
"bob"};
761 auto const USD = gw[
"USD"];
767 Env env{*
this, features};
769 auto const f = env.current()->fees().base;
771 env.fund(startBalance, gw, alice, bob);
794 env(
offer(alice,
XRP(1000), USD(1000)),
799 balance(alice, startBalance - (f * 2)),
803 balance(bob, startBalance - (f * 2)),
809 env(
offer(alice,
XRP(500), USD(500)),
814 balance(alice, startBalance - (f * 3) +
XRP(500)),
818 balance(bob, startBalance - (f * 2) -
XRP(500)),
827 Env env{*
this, features};
829 auto const f = env.current()->fees().base;
831 env.fund(startBalance, gw, alice, bob);
840 env(
offer(alice,
XRP(1000), USD(1000)),
846 balance(alice, startBalance - f - f),
853 env(
offer(alice,
XRP(1000), USD(1000)),
858 balance(alice, startBalance - f - f - f +
XRP(50)),
874 balance(alice, startBalance - f - f - f - f +
XRP(100)),
878 balance(bob, startBalance - f - f -
XRP(100)),
886 Env env(*
this, features);
888 env.
fund(startBalance, gw, alice, bob);
891 env(
trust(bob, USD(1000)));
894 env(
pay(gw, bob, USD(1000)));
897 env(
offer(alice, USD(1000),
XRP(2000)));
901 BEAST_EXPECT(aliceOffers.size() == 1);
902 for (
auto offerPtr : aliceOffers)
904 auto const&
offer = *offerPtr;
905 BEAST_EXPECT(
offer[sfTakerGets] ==
XRP(2000));
906 BEAST_EXPECT(
offer[sfTakerPays] == USD(1000));
916 BEAST_EXPECT(bobOffers.size() == 1);
917 for (
auto offerPtr : bobOffers)
919 auto const&
offer = *offerPtr;
920 BEAST_EXPECT(
offer[sfTakerGets] == USD(1000));
921 BEAST_EXPECT(
offer[sfTakerPays] ==
XRP(2000));
925 env(
offer(gw,
XRP(2000), USD(1000)));
931 env(
offer(gw, USD(1000),
XRP(2000)));
939 Env env(*
this, features);
941 env.
fund(startBalance, gw,
"alice",
"bob");
944 env(
trust(
"bob", USD(1000)));
947 env(
pay(gw,
"bob", USD(1000)));
948 env(
offer(
"alice", USD(500),
XRP(1001)));
951 env(
offer(
"alice", USD(500),
XRP(1000)));
955 BEAST_EXPECT(aliceOffers.size() == 2);
965 BEAST_EXPECT(bobOffers.size() == 1);
966 for (
auto offerPtr : bobOffers)
968 auto const&
offer = *offerPtr;
969 BEAST_EXPECT(
offer[sfTakerGets] == USD(499.5));
970 BEAST_EXPECT(
offer[sfTakerPays] ==
XRP(999));
982 auto const startBalance =
XRP(1000000);
983 auto const gw =
Account{
"gateway"};
984 auto const alice =
Account{
"alice"};
985 auto const USD = gw[
"USD"];
987 Env env{*
this, features};
989 env.fund(startBalance, gw, alice);
993 env(
offer(alice, USD(1000),
XRP(1000)),
1000 env(
offer(alice, USD(1000),
XRP(1000)),
1030 env(
offer(alice, USD(1000),
XRP(1000)),
1038 env(
offer(alice, USD(1000),
XRP(1000)),
1058 using namespace jtx;
1060 auto const gw =
Account{
"gateway"};
1061 auto const alice =
Account{
"alice"};
1062 auto const bob =
Account{
"bob"};
1063 auto const USD = gw[
"USD"];
1065 auto const startBalance =
XRP(1000000);
1066 auto const usdOffer = USD(1000);
1067 auto const xrpOffer =
XRP(1000);
1069 Env env{*
this, features};
1071 env.fund(startBalance, gw, alice, bob);
1074 auto const f = env.current()->fees().base;
1080 balance(alice, startBalance - f),
1087 bool const featPreauth{features[featureDepositPreauth]};
1089 env(
offer(alice, xrpOffer, usdOffer),
1094 balance(alice, startBalance - f - f),
1101 env(
offer(alice, xrpOffer, usdOffer),
1105 balance(alice, startBalance - f - f - f),
1113 balance(alice, startBalance - f - f - f),
1121 balance(alice, startBalance - f - f - f),
1125 balance(bob, startBalance - f),
1136 using namespace jtx;
1138 auto const gw =
Account{
"gateway"};
1139 auto const USD = gw[
"USD"];
1141 auto const usdOffer = USD(1000);
1142 auto const xrpOffer =
XRP(1000);
1144 Env env{*
this, features};
1146 env.fund(
XRP(1000000), gw);
1150 auto const f = env.current()->fees().base;
1154 env.fund(
reserve(env, 0),
"alice");
1161 env.fund(
reserve(env, 0) + f,
"bob");
1169 env.fund(
reserve(env, 0) + f +
XRP(1),
"carol");
1177 env.fund(
reserve(env, 1) + f,
"dan");
1184 env.fund(
reserve(env, 1) + f + xrpOffer,
"eve");
1196 (use_partner ?
", with partner account" :
""));
1198 using namespace jtx;
1200 auto const gw =
Account{
"gateway"};
1201 auto const partner =
Account{
"partner"};
1202 auto const USD = gw[
"USD"];
1203 auto const BTC = gw[
"BTC"];
1205 Env env{*
this, features};
1208 env.fund(
XRP(10000), gw);
1211 env.fund(
XRP(10000), partner);
1213 env(
trust(partner, USD(100)));
1214 env(
trust(partner, BTC(500)));
1216 env(
pay(gw, partner, USD(100)));
1217 env(
pay(gw, partner, BTC(500)));
1219 auto const& account_to_test = use_partner ? partner : gw;
1222 env.require(
offers(account_to_test, 0));
1227 env(
offer(account_to_test, BTC(250),
XRP(1000)));
1228 env.require(
offers(account_to_test, 1));
1231 BEAST_EXPECT(
isOffer(env, account_to_test, BTC(250),
XRP(1000)));
1233 auto const secondLegSeq = env.seq(account_to_test);
1234 env(
offer(account_to_test,
XRP(1000), USD(50)));
1235 env.require(
offers(account_to_test, 2));
1238 BEAST_EXPECT(
isOffer(env, account_to_test,
XRP(1000), USD(50)));
1242 env(
offer(account_to_test, USD(50), BTC(250)));
1245 BEAST_EXPECT(jrr[jss::offers].isArray());
1246 BEAST_EXPECT(jrr[jss::offers].size() == 0);
1249 BEAST_EXPECT(jrr[jss::offers].isArray());
1250 BEAST_EXPECT(jrr[jss::offers].size() == 0);
1257 BEAST_EXPECT(acctOffers.size() == 0);
1258 for (
auto const& offerPtr : acctOffers)
1260 auto const&
offer = *offerPtr;
1261 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
1262 BEAST_EXPECT(
offer[sfTakerGets] == USD(0));
1263 BEAST_EXPECT(
offer[sfTakerPays] ==
XRP(0));
1271 env.require(
offers(account_to_test, 0));
1276 env(
offer(account_to_test, BTC(250), USD(50)));
1277 env.require(
offers(account_to_test, 1));
1281 BEAST_EXPECT(
isOffer(env, account_to_test, BTC(250), USD(50)));
1284 BEAST_EXPECT(jrr[jss::offers].isArray());
1285 BEAST_EXPECT(jrr[jss::offers].size() == 0);
1289 env(
offer(account_to_test, USD(50), BTC(250)));
1290 env.require(
offers(account_to_test, 1));
1295 BEAST_EXPECT(jrr[jss::offers].isArray());
1296 BEAST_EXPECT(jrr[jss::offers].size() == 0);
1298 BEAST_EXPECT(
isOffer(env, account_to_test, USD(50), BTC(250)));
1308 using namespace jtx;
1313 {features - fixReducedOffersV2, features | fixReducedOffersV2})
1315 Env env{*
this, localFeatures};
1317 auto const gw =
Account{
"gateway"};
1318 auto const alice =
Account{
"alice"};
1319 auto const bob =
Account{
"bob"};
1320 auto const USD = gw[
"USD"];
1321 auto const BTC = gw[
"BTC"];
1325 auto const gw_initial_balance =
drops(1149999730);
1326 auto const alice_initial_balance =
drops(499946999680);
1327 auto const bob_initial_balance =
drops(10199999920);
1328 auto const small_amount =
1329 STAmount{bob[
"USD"].
issue(), UINT64_C(2710505431213761), -33};
1331 env.fund(gw_initial_balance, gw);
1332 env.fund(alice_initial_balance, alice);
1333 env.fund(bob_initial_balance, bob);
1336 env(
rate(gw, 1.005));
1338 env(
trust(alice, USD(500)));
1339 env(
trust(bob, USD(50)));
1340 env(
trust(gw, alice[
"USD"](100)));
1342 env(
pay(gw, alice, alice[
"USD"](50)));
1343 env(
pay(gw, bob, small_amount));
1345 env(
offer(alice, USD(50),
XRP(150000)));
1348 env(
pay(alice, gw, USD(100)));
1351 env(
trust(gw, alice[
"USD"](0)));
1356 jrr[jss::node][sfBalance.fieldName][jss::value] ==
"50");
1360 jrr[jss::node][sfBalance.fieldName][jss::value] ==
1361 "-2710505431213761e-33");
1365 env(
offer(bob,
XRP(2000), USD(1)));
1367 if (localFeatures[fixReducedOffersV2])
1374 jrr[jss::node][sfBalance.fieldName][jss::value] ==
1375 "-2710505431213761e-33");
1379 BEAST_EXPECT(bobOffer[sfTakerGets.jsonName][jss::value] ==
"1");
1380 BEAST_EXPECT(bobOffer[sfTakerPays.jsonName] ==
"2000000000");
1391 auto const crossingDelta =
drops(1);
1395 jrr[jss::node][sfBalance.fieldName][jss::value] ==
"50");
1398 alice_initial_balance - env.current()->fees().base * 3 -
1403 jrr[jss::node][sfBalance.fieldName][jss::value] ==
"0");
1406 bob_initial_balance - env.current()->fees().base * 2 +
1416 (reverse_order ?
"Reverse" :
"Normal") +
" order");
1418 using namespace jtx;
1420 Env env{*
this, features};
1422 auto const gw =
Account{
"gateway"};
1423 auto const alice =
Account{
"alice"};
1424 auto const bob =
Account{
"bob"};
1425 auto const USD = gw[
"USD"];
1427 env.fund(
XRP(10000), gw, alice, bob);
1430 env(
trust(alice, USD(1000)));
1431 env(
trust(bob, USD(1000)));
1433 env(
pay(gw, alice, alice[
"USD"](500)));
1436 env(
offer(bob, USD(1),
XRP(4000)));
1438 env(
offer(alice,
XRP(150000), USD(50)));
1441 env(
offer(bob, USD(1),
XRP(4000)));
1448 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-1");
1451 jrr[jss::node][sfBalance.fieldName] ==
1453 env.current()->fees().base * 2)
1457 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-499");
1460 jrr[jss::node][sfBalance.fieldName] ==
1462 env.current()->fees().base * 2)
1469 testcase(
"Offer Crossing with Limit Override");
1471 using namespace jtx;
1473 Env env{*
this, features};
1475 auto const gw =
Account{
"gateway"};
1476 auto const alice =
Account{
"alice"};
1477 auto const bob =
Account{
"bob"};
1478 auto const USD = gw[
"USD"];
1480 env.fund(
XRP(100000), gw, alice, bob);
1483 env(
trust(alice, USD(1000)));
1485 env(
pay(gw, alice, alice[
"USD"](500)));
1487 env(
offer(alice,
XRP(150000), USD(50)));
1488 env(
offer(bob, USD(1),
XRP(3000)));
1491 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-1");
1494 jrr[jss::node][sfBalance.fieldName] ==
1499 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-499");
1502 jrr[jss::node][sfBalance.fieldName] ==
1510 testcase(
"Offer Accept then Cancel.");
1512 using namespace jtx;
1514 Env env{*
this, features};
1516 auto const USD = env.master[
"USD"];
1518 auto const nextOfferSeq = env.seq(env.master);
1519 env(
offer(env.master,
XRP(500), USD(100)));
1523 BEAST_EXPECT(env.seq(env.master) == nextOfferSeq + 2);
1528 BEAST_EXPECT(env.seq(env.master) == nextOfferSeq + 2);
1534 testcase(
"Offer Cancel Past and Future Sequence.");
1536 using namespace jtx;
1538 Env env{*
this, features};
1540 auto const alice =
Account{
"alice"};
1542 auto const nextOfferSeq = env.seq(env.master);
1543 env.fund(
XRP(10000), alice);
1560 testcase(
"Currency Conversion: Entire Offer");
1562 using namespace jtx;
1564 Env env{*
this, features};
1566 auto const gw =
Account{
"gateway"};
1567 auto const alice =
Account{
"alice"};
1568 auto const bob =
Account{
"bob"};
1569 auto const USD = gw[
"USD"];
1571 env.fund(
XRP(10000), gw, alice, bob);
1573 env.require(
owners(bob, 0));
1575 env(
trust(alice, USD(100)));
1576 env(
trust(bob, USD(1000)));
1580 env(
pay(gw, alice, alice[
"USD"](100)));
1581 auto const bobOfferSeq = env.seq(bob);
1582 env(
offer(bob, USD(100),
XRP(500)));
1587 jro[jss::node][jss::TakerGets] ==
XRP(500).value().getText());
1589 jro[jss::node][jss::TakerPays] ==
1595 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"0");
1598 jrr[jss::node][sfBalance.fieldName] ==
1603 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-100");
1606 BEAST_EXPECT(jro[jss::error] ==
"entryNotFound");
1614 testcase(
"Currency Conversion: Offerer Into Debt");
1616 using namespace jtx;
1618 Env env{*
this, features};
1620 auto const alice =
Account{
"alice"};
1621 auto const bob =
Account{
"bob"};
1622 auto const carol =
Account{
"carol"};
1624 env.fund(
XRP(10000), alice, bob, carol);
1627 env(
trust(alice, carol[
"EUR"](2000)));
1628 env(
trust(bob, alice[
"USD"](100)));
1629 env(
trust(carol, bob[
"EUR"](1000)));
1631 auto const bobOfferSeq = env.seq(bob);
1632 env(
offer(bob, alice[
"USD"](50), carol[
"EUR"](200)),
1635 env(
offer(alice, carol[
"EUR"](200), alice[
"USD"](50)));
1638 BEAST_EXPECT(jro[jss::error] ==
"entryNotFound");
1644 testcase(
"Currency Conversion: In Parts");
1646 using namespace jtx;
1648 Env env{*
this, features};
1650 auto const gw =
Account{
"gateway"};
1651 auto const alice =
Account{
"alice"};
1652 auto const bob =
Account{
"bob"};
1653 auto const USD = gw[
"USD"];
1655 env.fund(
XRP(10000), gw, alice, bob);
1658 env(
trust(alice, USD(200)));
1659 env(
trust(bob, USD(1000)));
1661 env(
pay(gw, alice, alice[
"USD"](200)));
1663 auto const bobOfferSeq = env.seq(bob);
1664 env(
offer(bob, USD(100),
XRP(500)));
1671 jro[jss::node][jss::TakerGets] ==
XRP(300).value().getText());
1673 jro[jss::node][jss::TakerPays] ==
1679 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-160");
1683 jrr[jss::node][sfBalance.fieldName] ==
1689 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-40");
1693 env(
pay(alice, alice,
XRP(600)),
1699 env(
pay(alice, alice,
XRP(600)),
1705 BEAST_EXPECT(jro[jss::error] ==
"entryNotFound");
1713 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-100");
1716 jrr[jss::node][sfBalance.fieldName] ==
1718 env.current()->fees().base * 4)
1724 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-100");
1730 testcase(
"Cross Currency Payment: Start with XRP");
1732 using namespace jtx;
1734 Env env{*
this, features};
1736 auto const gw =
Account{
"gateway"};
1737 auto const alice =
Account{
"alice"};
1738 auto const bob =
Account{
"bob"};
1739 auto const carol =
Account{
"carol"};
1740 auto const USD = gw[
"USD"];
1742 env.fund(
XRP(10000), gw, alice, bob, carol);
1745 env(
trust(carol, USD(1000)));
1746 env(
trust(bob, USD(2000)));
1748 env(
pay(gw, carol, carol[
"USD"](500)));
1750 auto const carolOfferSeq = env.seq(carol);
1751 env(
offer(carol,
XRP(500), USD(50)));
1756 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-25");
1759 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-475");
1763 jro[jss::node][jss::TakerGets] ==
1766 jro[jss::node][jss::TakerPays] ==
XRP(250).value().getText());
1772 testcase(
"Cross Currency Payment: End with XRP");
1774 using namespace jtx;
1776 Env env{*
this, features};
1778 auto const gw =
Account{
"gateway"};
1779 auto const alice =
Account{
"alice"};
1780 auto const bob =
Account{
"bob"};
1781 auto const carol =
Account{
"carol"};
1782 auto const USD = gw[
"USD"];
1784 env.fund(
XRP(10000), gw, alice, bob, carol);
1787 env(
trust(alice, USD(1000)));
1788 env(
trust(carol, USD(2000)));
1790 env(
pay(gw, alice, alice[
"USD"](500)));
1792 auto const carolOfferSeq = env.seq(carol);
1793 env(
offer(carol, USD(50),
XRP(500)));
1798 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-475");
1801 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-25");
1805 jrr[jss::node][sfBalance.fieldName] ==
1807 XRP(10000).value().mantissa() +
XRP(250).value().mantissa()));
1811 jro[jss::node][jss::TakerGets] ==
XRP(250).value().getText());
1813 jro[jss::node][jss::TakerPays] ==
1820 testcase(
"Cross Currency Payment: Bridged");
1822 using namespace jtx;
1824 Env env{*
this, features};
1826 auto const gw1 =
Account{
"gateway_1"};
1827 auto const gw2 =
Account{
"gateway_2"};
1828 auto const alice =
Account{
"alice"};
1829 auto const bob =
Account{
"bob"};
1830 auto const carol =
Account{
"carol"};
1831 auto const dan =
Account{
"dan"};
1832 auto const USD = gw1[
"USD"];
1833 auto const EUR = gw2[
"EUR"];
1835 env.fund(
XRP(10000), gw1, gw2, alice, bob, carol, dan);
1838 env(
trust(alice, USD(1000)));
1839 env(
trust(bob, EUR(1000)));
1840 env(
trust(carol, USD(1000)));
1841 env(
trust(dan, EUR(1000)));
1843 env(
pay(gw1, alice, alice[
"USD"](500)));
1844 env(
pay(gw2, dan, dan[
"EUR"](400)));
1846 auto const carolOfferSeq = env.seq(carol);
1847 env(
offer(carol, USD(50),
XRP(500)));
1849 auto const danOfferSeq = env.seq(dan);
1850 env(
offer(dan,
XRP(500), EUR(50)));
1853 jtp[0u][0u][jss::currency] =
"XRP";
1854 env(
pay(alice, bob, EUR(30)),
json(jss::Paths, jtp),
sendmax(USD(333)));
1857 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"470");
1860 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-30");
1863 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-30");
1866 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-370");
1870 jro[jss::node][jss::TakerGets] ==
XRP(200).value().getText());
1872 jro[jss::node][jss::TakerPays] ==
1877 jro[jss::node][jss::TakerGets] ==
1880 jro[jss::node][jss::TakerPays] ==
XRP(200).value().getText());
1889 testcase(
"Auto Bridged Second Leg Dry");
1891 using namespace jtx;
1892 Env env(*
this, features);
1898 auto const USD = gw[
"USD"];
1899 auto const EUR = gw[
"EUR"];
1901 env.
fund(
XRP(100000000), alice, bob, carol, gw);
1904 env.
trust(USD(10), alice);
1906 env(
pay(gw, alice, USD(10)));
1907 env.
trust(USD(10), carol);
1909 env(
pay(gw, carol, USD(3)));
1926 env.
trust(EUR(10), bob);
1928 env(
pay(gw, bob, EUR(10)));
1930 env(
offer(bob, USD(10), EUR(10)));
1953 testcase(
"Offer Fees Consume Funds");
1955 using namespace jtx;
1957 Env env{*
this, features};
1959 auto const gw1 =
Account{
"gateway_1"};
1960 auto const gw2 =
Account{
"gateway_2"};
1961 auto const gw3 =
Account{
"gateway_3"};
1962 auto const alice =
Account{
"alice"};
1963 auto const bob =
Account{
"bob"};
1964 auto const USD1 = gw1[
"USD"];
1965 auto const USD2 = gw2[
"USD"];
1966 auto const USD3 = gw3[
"USD"];
1974 auto const starting_xrp =
XRP(100) +
1975 env.current()->fees().accountReserve(3) +
1976 env.current()->fees().base * 4;
1978 env.fund(starting_xrp, gw1, gw2, gw3, alice, bob);
1981 env(
trust(alice, USD1(1000)));
1982 env(
trust(alice, USD2(1000)));
1983 env(
trust(alice, USD3(1000)));
1984 env(
trust(bob, USD1(1000)));
1985 env(
trust(bob, USD2(1000)));
1987 env(
pay(gw1, bob, bob[
"USD"](500)));
1989 env(
offer(bob,
XRP(200), USD1(200)));
1992 env(
offer(alice, USD1(200),
XRP(200)));
1995 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"100");
1998 jrr[jss::node][sfBalance.fieldName] ==
2002 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-400");
2008 testcase(
"Offer Create, then Cross");
2010 using namespace jtx;
2012 for (
auto NumberSwitchOver : {
false,
true})
2014 Env env{*
this, features};
2015 if (NumberSwitchOver)
2016 env.enableFeature(fixUniversalNumber);
2018 env.disableFeature(fixUniversalNumber);
2020 auto const gw =
Account{
"gateway"};
2021 auto const alice =
Account{
"alice"};
2022 auto const bob =
Account{
"bob"};
2023 auto const USD = gw[
"USD"];
2025 env.fund(
XRP(10000), gw, alice, bob);
2028 env(
rate(gw, 1.005));
2030 env(
trust(alice, USD(1000)));
2031 env(
trust(bob, USD(1000)));
2032 env(
trust(gw, alice[
"USD"](50)));
2034 env(
pay(gw, bob, bob[
"USD"](1)));
2035 env(
pay(alice, gw, USD(50)));
2037 env(
trust(gw, alice[
"USD"](0)));
2039 env(
offer(alice, USD(50),
XRP(150000)));
2040 env(
offer(bob,
XRP(100), USD(0.1)));
2044 jrr[jss::node][sfBalance.fieldName][jss::value] ==
2045 "49.96666666666667");
2049 jrr[jss::node][sfBalance.fieldName][jss::value];
2050 if (!NumberSwitchOver)
2052 BEAST_EXPECT(bobsUSD ==
"-0.966500000033334");
2056 BEAST_EXPECT(bobsUSD ==
"-0.9665000000333333");
2064 testcase(
"Offer tfSell: Basic Sell");
2066 using namespace jtx;
2068 Env env{*
this, features};
2070 auto const gw =
Account{
"gateway"};
2071 auto const alice =
Account{
"alice"};
2072 auto const bob =
Account{
"bob"};
2073 auto const USD = gw[
"USD"];
2075 auto const starting_xrp =
XRP(100) +
2076 env.current()->fees().accountReserve(1) +
2077 env.current()->fees().base * 2;
2079 env.fund(starting_xrp, gw, alice, bob);
2082 env(
trust(alice, USD(1000)));
2083 env(
trust(bob, USD(1000)));
2085 env(
pay(gw, bob, bob[
"USD"](500)));
2094 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-100");
2097 jrr[jss::node][sfBalance.fieldName] ==
2101 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-400");
2107 testcase(
"Offer tfSell: 2x Sell Exceed Limit");
2109 using namespace jtx;
2111 Env env{*
this, features};
2113 auto const gw =
Account{
"gateway"};
2114 auto const alice =
Account{
"alice"};
2115 auto const bob =
Account{
"bob"};
2116 auto const USD = gw[
"USD"];
2118 auto const starting_xrp =
XRP(100) +
2119 env.current()->fees().accountReserve(1) +
2120 env.current()->fees().base * 2;
2122 env.fund(starting_xrp, gw, alice, bob);
2125 env(
trust(alice, USD(150)));
2126 env(
trust(bob, USD(1000)));
2128 env(
pay(gw, bob, bob[
"USD"](500)));
2130 env(
offer(bob,
XRP(100), USD(200)));
2139 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-200");
2142 jrr[jss::node][sfBalance.fieldName] ==
2146 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-300");
2152 testcase(
"Client Issue #535: Gateway Cross Currency");
2154 using namespace jtx;
2156 Env env{*
this, features};
2158 auto const gw =
Account{
"gateway"};
2159 auto const alice =
Account{
"alice"};
2160 auto const bob =
Account{
"bob"};
2161 auto const XTS = gw[
"XTS"];
2162 auto const XXX = gw[
"XXX"];
2164 auto const starting_xrp =
XRP(100.1) +
2165 env.current()->fees().accountReserve(1) +
2166 env.current()->fees().base * 2;
2168 env.fund(starting_xrp, gw, alice, bob);
2171 env(
trust(alice, XTS(1000)));
2172 env(
trust(alice, XXX(1000)));
2173 env(
trust(bob, XTS(1000)));
2174 env(
trust(bob, XXX(1000)));
2176 env(
pay(gw, alice, alice[
"XTS"](100)));
2177 env(
pay(gw, alice, alice[
"XXX"](100)));
2178 env(
pay(gw, bob, bob[
"XTS"](100)));
2179 env(
pay(gw, bob, bob[
"XXX"](100)));
2181 env(
offer(alice, XTS(100), XXX(100)));
2188 payment[jss::id] = env.seq(bob);
2189 payment[jss::build_path] =
true;
2190 payment[jss::tx_json] =
pay(bob, bob, bob[
"XXX"](1));
2191 payment[jss::tx_json][jss::Sequence] =
2194 ->getFieldU32(sfSequence);
2195 payment[jss::tx_json][jss::Fee] =
to_string(env.current()->fees().base);
2196 payment[jss::tx_json][jss::SendMax] =
2198 auto jrr = wsc->invoke(
"submit", payment);
2199 BEAST_EXPECT(jrr[jss::status] ==
"success");
2200 BEAST_EXPECT(jrr[jss::result][jss::engine_result] ==
"tesSUCCESS");
2201 if (wsc->version() == 2)
2204 jrr.isMember(jss::jsonrpc) && jrr[jss::jsonrpc] ==
"2.0");
2206 jrr.isMember(jss::ripplerpc) && jrr[jss::ripplerpc] ==
"2.0");
2207 BEAST_EXPECT(jrr.isMember(jss::id) && jrr[jss::id] == 5);
2211 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-101");
2213 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-99");
2216 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-99");
2218 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-101");
2233 auto const sleTrust =
2235 BEAST_EXPECT(sleTrust);
2239 bool const accountLow = account.id() < issue.
account;
2244 low.setIssuer(accountLow ? account.id() : issue.
account);
2245 high.setIssuer(accountLow ? issue.
account : account.id());
2247 BEAST_EXPECT(sleTrust->getFieldAmount(sfLowLimit) == low);
2248 BEAST_EXPECT(sleTrust->getFieldAmount(sfHighLimit) == high);
2250 STAmount actualBalance{sleTrust->getFieldAmount(sfBalance)};
2254 BEAST_EXPECT(actualBalance == expectBalance);
2266 using namespace jtx;
2268 auto const gw =
Account(
"gateway");
2269 auto const USD = gw[
"USD"];
2271 Env env{*
this, features};
2273 env.fund(
XRP(10000000), gw);
2277 auto const f = env.current()->fees().base;
2280 enum preTrustType { noPreTrust, gwPreTrust, acctPreTrust };
2286 preTrustType preTrust;
2296 TestData
const tests[]{
2298 {
"ann",
reserve(env, 0) + 0 * f, 1, noPreTrust, 1000,
tecUNFUNDED_OFFER, f, USD( 0), 0, 0},
2299 {
"bev",
reserve(env, 0) + 1 * f, 1, noPreTrust, 1000,
tecUNFUNDED_OFFER, f, USD( 0), 0, 0},
2300 {
"cam",
reserve(env, 0) + 2 * f, 0, noPreTrust, 1000,
tecINSUF_RESERVE_OFFER, f, USD( 0), 0, 0},
2301 {
"deb",
drops(10) +
reserve(env, 0) + 1 * f, 1, noPreTrust, 1000,
tesSUCCESS,
drops(10) + f, USD(0.00001), 0, 1},
2302 {
"eve",
reserve(env, 1) + 0 * f, 0, noPreTrust, 1000,
tesSUCCESS, f, USD( 0), 1, 1},
2303 {
"flo",
reserve(env, 1) + 0 * f, 1, noPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 0, 1},
2304 {
"gay",
reserve(env, 1) + 1 * f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP( 50) + f, USD( 50), 0, 1},
2305 {
"hye",
XRP(1000) + 1 * f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP( 800) + f, USD( 800), 0, 1},
2306 {
"ivy",
XRP( 1) +
reserve(env, 1) + 1 * f, 1, noPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 0, 1},
2307 {
"joy",
XRP( 1) +
reserve(env, 2) + 1 * f, 1, noPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 1, 2},
2308 {
"kim",
XRP( 900) +
reserve(env, 2) + 1 * f, 999, noPreTrust, 1000,
tesSUCCESS,
XRP( 999) + f, USD( 999), 0, 1},
2309 {
"liz",
XRP( 998) +
reserve(env, 0) + 1 * f, 999, noPreTrust, 1000,
tesSUCCESS,
XRP( 998) + f, USD( 998), 0, 1},
2310 {
"meg",
XRP( 998) +
reserve(env, 1) + 1 * f, 999, noPreTrust, 1000,
tesSUCCESS,
XRP( 999) + f, USD( 999), 0, 1},
2311 {
"nia",
XRP( 998) +
reserve(env, 2) + 1 * f, 999, noPreTrust, 1000,
tesSUCCESS,
XRP( 999) + f, USD( 999), 1, 2},
2312 {
"ova",
XRP( 999) +
reserve(env, 0) + 1 * f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP( 999) + f, USD( 999), 0, 1},
2313 {
"pam",
XRP( 999) +
reserve(env, 1) + 1 * f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP(1000) + f, USD( 1000), 0, 1},
2314 {
"rae",
XRP( 999) +
reserve(env, 2) + 1 * f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP(1000) + f, USD( 1000), 0, 1},
2315 {
"sue",
XRP(1000) +
reserve(env, 2) + 1 * f, 0, noPreTrust, 1000,
tesSUCCESS, f, USD( 0), 1, 1},
2317 {
"abe",
reserve(env, 0) + 0 * f, 1, gwPreTrust, 1000,
tecUNFUNDED_OFFER, f, USD( 0), 0, 0},
2318 {
"bud",
reserve(env, 0) + 1 * f, 1, gwPreTrust, 1000,
tecUNFUNDED_OFFER, f, USD( 0), 0, 0},
2319 {
"che",
reserve(env, 0) + 2 * f, 0, gwPreTrust, 1000,
tecINSUF_RESERVE_OFFER, f, USD( 0), 0, 0},
2320 {
"dan",
drops(10) +
reserve(env, 0) + 1 * f, 1, gwPreTrust, 1000,
tesSUCCESS,
drops(10) + f, USD(0.00001), 0, 0},
2321 {
"eli",
XRP( 20) +
reserve(env, 0) + 1 * f, 1000, gwPreTrust, 1000,
tesSUCCESS,
XRP(20) + 1 * f, USD( 20), 0, 0},
2322 {
"fyn",
reserve(env, 1) + 0 * f, 0, gwPreTrust, 1000,
tesSUCCESS, f, USD( 0), 1, 1},
2323 {
"gar",
reserve(env, 1) + 0 * f, 1, gwPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 1, 1},
2324 {
"hal",
reserve(env, 1) + 1 * f, 1, gwPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 1, 1},
2326 {
"ned",
reserve(env, 1) + 0 * f, 1, acctPreTrust, 1000,
tecUNFUNDED_OFFER, 2 * f, USD( 0), 0, 1},
2327 {
"ole",
reserve(env, 1) + 1 * f, 1, acctPreTrust, 1000,
tecUNFUNDED_OFFER, 2 * f, USD( 0), 0, 1},
2328 {
"pat",
reserve(env, 1) + 2 * f, 0, acctPreTrust, 1000,
tecUNFUNDED_OFFER, 2 * f, USD( 0), 0, 1},
2329 {
"quy",
reserve(env, 1) + 2 * f, 1, acctPreTrust, 1000,
tecUNFUNDED_OFFER, 2 * f, USD( 0), 0, 1},
2330 {
"ron",
reserve(env, 1) + 3 * f, 0, acctPreTrust, 1000,
tecINSUF_RESERVE_OFFER, 2 * f, USD( 0), 0, 1},
2331 {
"syd",
drops(10) +
reserve(env, 1) + 2 * f, 1, acctPreTrust, 1000,
tesSUCCESS,
drops(10) + 2 * f, USD(0.00001), 0, 1},
2332 {
"ted",
XRP( 20) +
reserve(env, 1) + 2 * f, 1000, acctPreTrust, 1000,
tesSUCCESS,
XRP(20) + 2 * f, USD( 20), 0, 1},
2333 {
"uli",
reserve(env, 2) + 0 * f, 0, acctPreTrust, 1000,
tecINSUF_RESERVE_OFFER, 2 * f, USD( 0), 0, 1},
2334 {
"vic",
reserve(env, 2) + 0 * f, 1, acctPreTrust, 1000,
tesSUCCESS,
XRP( 1) + 2 * f, USD( 1), 0, 1},
2335 {
"wes",
reserve(env, 2) + 1 * f, 0, acctPreTrust, 1000,
tesSUCCESS, 2 * f, USD( 0), 1, 2},
2336 {
"xan",
reserve(env, 2) + 1 * f, 1, acctPreTrust, 1000,
tesSUCCESS,
XRP( 1) + 2 * f, USD( 1), 1, 2},
2340 for (
auto const& t : tests)
2342 auto const acct =
Account(t.account);
2343 env.fund(t.fundXrp, acct);
2347 env.require(
offers(gw, 0));
2350 auto const book = t.bookAmount;
2352 env(
offer(gw,
XRP(book), USD(book)));
2357 if (t.preTrust == gwPreTrust)
2358 env(
trust(gw, acct[
"USD"](1)));
2364 if (t.preTrust == acctPreTrust)
2365 env(
trust(acct, USD(1)));
2370 auto const acctOffer = t.offerAmount;
2371 env(
offer(acct, USD(acctOffer),
XRP(acctOffer)),
ter(t.tec));
2376 BEAST_EXPECT(env.balance(acct, USD.issue()) == t.balanceUsd);
2378 env.balance(acct,
xrpIssue()) == t.fundXrp - t.spentXrp);
2379 env.require(
offers(acct, t.offers));
2380 env.require(
owners(acct, t.owners));
2383 BEAST_EXPECT(acctOffers.size() == t.offers);
2384 if (acctOffers.size() && t.offers)
2386 auto const& acctOffer = *(acctOffers.front());
2388 auto const leftover = t.offerAmount - t.bookAmount;
2389 BEAST_EXPECT(acctOffer[sfTakerGets] ==
XRP(leftover));
2390 BEAST_EXPECT(acctOffer[sfTakerPays] == USD(leftover));
2393 if (t.preTrust == noPreTrust)
2395 if (t.balanceUsd.value().signum())
2403 auto const sleTrust =
2405 BEAST_EXPECT(!sleTrust);
2422 using namespace jtx;
2424 auto const gw =
Account(
"gateway");
2425 auto const alice =
Account(
"alice");
2426 auto const bob =
Account(
"bob");
2427 auto const USD = gw[
"USD"];
2429 auto const usdOffer = USD(1000);
2430 auto const xrpOffer =
XRP(1000);
2432 Env env{*
this, features};
2434 env.fund(
XRP(1000000), gw, bob);
2438 auto const fee = env.current()->fees().base;
2445 env(
trust(alice, usdOffer));
2449 env(
pay(gw, alice, usdOffer));
2456 auto const alicesXRP = env.balance(alice);
2457 auto const bobsXRP = env.balance(bob);
2459 env(
offer(alice, xrpOffer, usdOffer));
2461 env(
offer(bob, usdOffer, xrpOffer));
2475 env(
offer(alice, USD(999),
XRP(999)));
2476 env(
offer(bob, xrpOffer, usdOffer));
2479 env.require(
balance(alice, USD(999)));
2480 env.require(
balance(bob, USD(1)));
2481 env.require(
offers(alice, 0));
2485 BEAST_EXPECT(bobsOffers.size() == 1);
2486 auto const& bobsOffer = *(bobsOffers.front());
2488 BEAST_EXPECT(bobsOffer[sfLedgerEntryType] == ltOFFER);
2489 BEAST_EXPECT(bobsOffer[sfTakerGets] == USD(1));
2490 BEAST_EXPECT(bobsOffer[sfTakerPays] ==
XRP(1));
2499 using namespace jtx;
2501 auto const gw =
Account(
"gateway");
2502 auto const alice =
Account(
"alice");
2503 auto const bob =
Account(
"bob");
2504 auto const USD = gw[
"USD"];
2505 auto const EUR = gw[
"EUR"];
2507 auto const usdOffer = USD(1000);
2508 auto const eurOffer = EUR(1000);
2510 Env env{*
this, features};
2512 env.fund(
XRP(1000000), gw);
2516 auto const fee = env.current()->fees().base;
2524 env(
trust(alice, usdOffer));
2525 env(
trust(bob, eurOffer));
2528 env(
pay(gw, alice, usdOffer));
2529 env(
pay(gw, bob, eurOffer));
2537 env(
offer(alice, eurOffer, usdOffer));
2538 env(
offer(bob, usdOffer, eurOffer));
2555 env(
offer(bob, eurOffer, usdOffer));
2558 env(
offer(alice, USD(999), eurOffer));
2561 env.require(
offers(alice, 0));
2562 env.require(
offers(bob, 1));
2564 env.require(
balance(alice, USD(999)));
2565 env.require(
balance(alice, EUR(1)));
2566 env.require(
balance(bob, USD(1)));
2567 env.require(
balance(bob, EUR(999)));
2571 if (BEAST_EXPECT(bobsOffers.size() == 1))
2573 auto const& bobsOffer = *(bobsOffers.front());
2575 BEAST_EXPECT(bobsOffer[sfTakerGets] == USD(1));
2576 BEAST_EXPECT(bobsOffer[sfTakerPays] == EUR(1));
2581 env(
offer(alice, USD(1), EUR(1)));
2584 env.require(
balance(alice, USD(1000)));
2587 env.require(
balance(bob, EUR(1000)));
2588 env.require(
offers(alice, 0));
2589 env.require(
offers(bob, 0));
2592 BEAST_EXPECT(!env.le(
keylet::line(alice.id(), EUR.issue())));
2593 BEAST_EXPECT(!env.le(
keylet::line(bob.id(), USD.issue())));
2597 env(
offer(alice, EUR(999), usdOffer));
2600 env(
offer(bob, usdOffer, eurOffer));
2603 env.require(
offers(alice, 0));
2604 env.require(
offers(bob, 0));
2606 env.require(
balance(alice, USD(0)));
2607 env.require(
balance(alice, EUR(999)));
2608 env.require(
balance(bob, USD(1000)));
2609 env.require(
balance(bob, EUR(1)));
2617 using namespace jtx;
2619 auto const gw =
Account(
"gateway");
2620 auto const alice =
Account(
"alice");
2621 auto const bob =
Account(
"bob");
2622 auto const carol =
Account(
"carol");
2623 auto const USD = gw[
"USD"];
2624 auto const EUR = gw[
"EUR"];
2626 auto const usdOffer = USD(1000);
2627 auto const eurOffer = EUR(1000);
2629 Env env{*
this, features};
2631 env.fund(
XRP(1000000), gw, alice, bob, carol);
2634 env(
trust(alice, usdOffer));
2635 env(
trust(carol, eurOffer));
2637 env(
pay(gw, alice, usdOffer));
2638 env(
pay(gw, carol, eurOffer));
2647 env(
offer(alice,
XRP(1000), usdOffer));
2648 env(
offer(bob, eurOffer,
XRP(1000)));
2649 auto const bobXrpBalance = env.balance(bob);
2653 env(
offer(carol, USD(400), EUR(400)));
2666 BEAST_EXPECT(alicesOffers.size() == 1);
2667 auto const& alicesOffer = *(alicesOffers.front());
2669 BEAST_EXPECT(alicesOffer[sfLedgerEntryType] == ltOFFER);
2670 BEAST_EXPECT(alicesOffer[sfTakerGets] == USD(600));
2671 BEAST_EXPECT(alicesOffer[sfTakerPays] ==
XRP(600));
2675 BEAST_EXPECT(bobsOffers.size() == 1);
2676 auto const& bobsOffer = *(bobsOffers.front());
2678 BEAST_EXPECT(bobsOffer[sfLedgerEntryType] == ltOFFER);
2679 BEAST_EXPECT(bobsOffer[sfTakerGets] ==
XRP(600));
2680 BEAST_EXPECT(bobsOffer[sfTakerPays] == EUR(600));
2684 env(
offer(carol, USD(600), EUR(600)));
2699 if (alicesOffers.size() != 0)
2701 BEAST_EXPECT(alicesOffers.size() == 1);
2702 auto const& alicesOffer = *(alicesOffers.front());
2704 BEAST_EXPECT(alicesOffer[sfLedgerEntryType] == ltOFFER);
2705 BEAST_EXPECT(alicesOffer[sfTakerGets] == USD(0));
2706 BEAST_EXPECT(alicesOffer[sfTakerPays] ==
XRP(0));
2718 using namespace jtx;
2720 auto const gw =
Account(
"gateway");
2721 auto const USD = gw[
"USD"];
2723 Env env{*
this, features};
2725 env.fund(
XRP(10000000), gw);
2729 auto const f = env.current()->fees().base;
2732 enum preTrustType { noPreTrust, gwPreTrust, acctPreTrust };
2766 : account(std::move(account_))
2771 , acctGets(acctGets_)
2772 , acctPays(acctPays_)
2774 , spentXrp(spentXrp_)
2775 , finalUsd(finalUsd_)
2778 , takerGets(takerGets_)
2779 , takerPays(takerPays_)
2798 std::move(account_),
2817 TestData
const tests[]{
2820 {
"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},
2821 {
"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)},
2822 {
"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},
2823 {
"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},
2824 {
"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},
2825 {
"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},
2826 {
"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},
2827 {
"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)},
2829 {
"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},
2830 {
"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)},
2831 {
"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},
2832 {
"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},
2833 {
"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},
2834 {
"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)},
2835 {
"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)},
2839 auto const zeroUsd = USD(0);
2840 for (
auto const& t : tests)
2843 env.require(
offers(gw, 0));
2845 auto const acct =
Account(t.account);
2847 env.fund(t.fundXrp, acct);
2853 if (t.fundUSD != zeroUsd)
2855 env(
trust(acct, t.fundUSD));
2857 env(
pay(gw, acct, t.fundUSD));
2861 env(
offer(gw, t.gwGets, t.gwPays));
2871 BEAST_EXPECT(env.balance(acct, USD.issue()) == t.finalUsd);
2873 env.balance(acct,
xrpIssue()) == t.fundXrp - t.spentXrp);
2874 env.require(
offers(acct, t.offers));
2875 env.require(
owners(acct, t.owners));
2880 if (acctOffers.size() > 0)
2882 BEAST_EXPECT(acctOffers.size() == 1);
2883 auto const& acctOffer = *(acctOffers.front());
2885 BEAST_EXPECT(acctOffer[sfLedgerEntryType] == ltOFFER);
2886 BEAST_EXPECT(acctOffer[sfTakerGets] == t.takerGets);
2887 BEAST_EXPECT(acctOffer[sfTakerPays] == t.takerPays);
2904 testcase(
"Combine tfSell with tfFillOrKill");
2906 using namespace jtx;
2908 auto const gw =
Account(
"gateway");
2909 auto const alice =
Account(
"alice");
2910 auto const bob =
Account(
"bob");
2911 auto const USD = gw[
"USD"];
2913 Env env{*
this, features};
2915 env.fund(
XRP(10000000), gw, alice, bob);
2922 env(
trust(bob, USD(200)));
2924 env(
pay(gw, bob, USD(100)));
2926 env(
offer(bob,
XRP(2000), USD(20)));
2934 env.require(
offers(alice, 0));
2935 env.require(
balance(bob, USD(100)));
2942 env.require(
balance(alice, USD(20)));
2943 env.require(
offers(alice, 0));
2944 env.require(
balance(bob, USD(80)));
2949 env(
offer(bob,
XRP(2000), USD(20)));
2953 env.require(
balance(alice, USD(35)));
2954 env.require(
offers(alice, 0));
2955 env.require(
balance(bob, USD(65)));
2967 env.require(
balance(alice, USD(35)));
2968 env.require(
offers(alice, 0));
2969 env.require(
balance(bob, USD(65)));
2978 env.require(
balance(alice, USD(40)));
2979 env.require(
offers(alice, 0));
2980 env.require(
balance(bob, USD(60)));
2989 using namespace jtx;
2991 auto const gw1 =
Account(
"gateway1");
2992 auto const USD = gw1[
"USD"];
2994 Env env{*
this, features};
2997 auto const fee = env.current()->fees().base;
2999 env.fund(
XRP(100000), gw1);
3002 env(
rate(gw1, 1.25));
3004 auto const ann =
Account(
"ann");
3005 auto const bob =
Account(
"bob");
3009 env(
trust(ann, USD(200)));
3010 env(
trust(bob, USD(200)));
3013 env(
pay(gw1, bob, USD(125)));
3028 env.require(
balance(ann, USD(100)));
3030 env.require(
offers(ann, 0));
3032 env.require(
balance(bob, USD(0)));
3034 env.require(
offers(bob, 0));
3039 auto const che =
Account(
"che");
3040 auto const deb =
Account(
"deb");
3044 env(
trust(che, USD(200)));
3045 env(
trust(deb, USD(200)));
3048 env(
pay(gw1, deb, USD(125)));
3057 env.require(
balance(che, USD(100)));
3059 env.require(
offers(che, 0));
3061 env.require(
balance(deb, USD(0)));
3063 env.require(
offers(deb, 0));
3066 auto const eve =
Account(
"eve");
3067 auto const fyn =
Account(
"fyn");
3069 env.fund(
XRP(20000) + (
fee * 2), eve, fyn);
3072 env(
trust(eve, USD(1000)));
3073 env(
trust(fyn, USD(1000)));
3076 env(
pay(gw1, eve, USD(100)));
3077 env(
pay(gw1, fyn, USD(100)));
3083 env(
offer(eve, USD(10),
XRP(4000)));
3087 env(
offer(fyn,
XRP(2000), USD(5)));
3090 env.require(
balance(eve, USD(105)));
3093 BEAST_EXPECT(evesOffers.size() == 1);
3094 if (evesOffers.size() != 0)
3096 auto const& evesOffer = *(evesOffers.front());
3097 BEAST_EXPECT(evesOffer[sfLedgerEntryType] == ltOFFER);
3098 BEAST_EXPECT(evesOffer[sfTakerGets] ==
XRP(2000));
3099 BEAST_EXPECT(evesOffer[sfTakerPays] == USD(5));
3103 env.require(
balance(fyn, USD(93.75)));
3105 env.require(
offers(fyn, 0));
3108 auto const gw2 =
Account(
"gateway2");
3109 auto const EUR = gw2[
"EUR"];
3111 env.fund(
XRP(100000), gw2);
3114 env(
rate(gw2, 1.5));
3119 auto const gay =
Account(
"gay");
3120 auto const hal =
Account(
"hal");
3121 env.fund(
reserve(env, 3) + (
fee * 3), gay, hal);
3124 env(
trust(gay, USD(200)));
3125 env(
trust(gay, EUR(200)));
3126 env(
trust(hal, USD(200)));
3127 env(
trust(hal, EUR(200)));
3130 env(
pay(gw1, gay, USD(125)));
3131 env(
pay(gw2, hal, EUR(150)));
3134 env(
offer(gay, EUR(100), USD(100)));
3137 env(
offer(hal, USD(100), EUR(100)));
3140 env.require(
balance(gay, USD(0)));
3141 env.require(
balance(gay, EUR(100)));
3143 env.require(
offers(gay, 0));
3145 env.require(
balance(hal, USD(100)));
3146 env.require(
balance(hal, EUR(0)));
3148 env.require(
offers(hal, 0));
3152 auto const ivy =
Account(
"ivy");
3153 auto const joe =
Account(
"joe");
3154 env.fund(
reserve(env, 3) + (
fee * 3), ivy, joe);
3163 env(
pay(gw1, ivy, USD(270)),
sendmax(USD(500)));
3164 env(
pay(gw2, joe, EUR(150)),
sendmax(EUR(300)));
3166 env.require(
balance(ivy, USD(300)));
3167 env.require(
balance(joe, EUR(250)));
3169 env(
offer(ivy, EUR(100), USD(200)));
3172 env(
offer(joe, USD(200), EUR(100)));
3175 env.require(
balance(ivy, USD(50)));
3176 env.require(
balance(ivy, EUR(100)));
3178 env.require(
offers(ivy, 0));
3180 env.require(
balance(joe, USD(200)));
3181 env.require(
balance(joe, EUR(100)));
3183 env.require(
offers(joe, 0));
3187 auto const kim =
Account(
"kim");
3188 auto const K_BUX = kim[
"BUX"];
3189 auto const lex =
Account(
"lex");
3190 auto const meg =
Account(
"meg");
3191 auto const ned =
Account(
"ned");
3192 auto const N_BUX = ned[
"BUX"];
3195 env.fund(
reserve(env, 4) + (
fee * 4), kim, lex, meg, ned);
3198 env(
trust(lex, K_BUX(400)));
3200 env(
trust(meg, N_BUX(100)));
3202 env(
pay(ned, lex, N_BUX(100)));
3204 env.require(
balance(lex, N_BUX(100)));
3206 env(
pay(kim, meg, N_BUX(60)),
path(lex, ned),
sendmax(K_BUX(200)));
3211 env.require(
balance(lex, K_BUX(72)));
3212 env.require(
balance(lex, N_BUX(40)));
3214 env.require(
balance(meg, N_BUX(60)));
3219 env(
offer(lex, K_BUX(30), N_BUX(30)));
3222 env(
offer(kim, N_BUX(30), K_BUX(30)));
3226 env.require(
balance(kim, N_BUX(30)));
3227 env.require(
balance(lex, K_BUX(102)));
3228 env.require(
balance(lex, N_BUX(10)));
3230 env.require(
balance(meg, N_BUX(60)));
3231 env.require(
balance(ned, K_BUX(-30)));
3236 auto const ova =
Account(
"ova");
3237 auto const pat =
Account(
"pat");
3238 auto const qae =
Account(
"qae");
3239 env.fund(
XRP(2) +
reserve(env, 3) + (
fee * 3), ova, pat, qae);
3245 env(
trust(ova, USD(200)));
3246 env(
trust(ova, EUR(200)));
3247 env(
trust(pat, USD(200)));
3248 env(
trust(pat, EUR(200)));
3249 env(
trust(qae, USD(200)));
3250 env(
trust(qae, EUR(200)));
3253 env(
pay(gw1, ova, USD(125)));
3254 env(
pay(gw2, qae, EUR(150)));
3261 env(
offer(qae, USD(100), EUR(100)));
3264 env.require(
balance(ova, USD(0)));
3265 env.require(
balance(ova, EUR(0)));
3270 if (ovasOffers.size() != 0)
3272 BEAST_EXPECT(ovasOffers.size() == 1);
3273 auto const& ovasOffer = *(ovasOffers.front());
3275 BEAST_EXPECT(ovasOffer[sfLedgerEntryType] == ltOFFER);
3276 BEAST_EXPECT(ovasOffer[sfTakerGets] == USD(0));
3277 BEAST_EXPECT(ovasOffer[sfTakerPays] ==
XRP(0));
3280 env.require(
balance(pat, USD(0)));
3281 env.require(
balance(pat, EUR(100)));
3283 env.require(
offers(pat, 0));
3285 env.require(
balance(qae, USD(100)));
3286 env.require(
balance(qae, EUR(0)));
3288 env.require(
offers(qae, 0));
3309 using namespace jtx;
3311 auto const gw =
Account(
"gateway");
3312 auto const USD = gw[
"USD"];
3314 Env env{*
this, features};
3317 auto const fee = env.current()->fees().base;
3318 auto const startBalance =
XRP(1000000);
3320 env.fund(startBalance + (
fee * 4), gw);
3330 env.require(
owners(gw, 3));
3331 env.require(
balance(gw, startBalance +
fee));
3334 BEAST_EXPECT(gwOffers.size() == 3);
3335 for (
auto const& offerPtr : gwOffers)
3337 auto const&
offer = *offerPtr;
3338 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
3339 BEAST_EXPECT(
offer[sfTakerGets] ==
XRP(600));
3340 BEAST_EXPECT(
offer[sfTakerPays] == USD(60));
3345 env(
offer(gw,
XRP(1000), USD(100)));
3347 env.require(
owners(gw, 1));
3348 env.require(
offers(gw, 1));
3349 env.require(
balance(gw, startBalance));
3352 BEAST_EXPECT(gwOffers.size() == 1);
3353 for (
auto const& offerPtr : gwOffers)
3355 auto const&
offer = *offerPtr;
3356 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
3357 BEAST_EXPECT(
offer[sfTakerGets] == USD(100));
3358 BEAST_EXPECT(
offer[sfTakerPays] ==
XRP(1000));
3365 using namespace jtx;
3367 auto const gw1 =
Account(
"gateway1");
3368 auto const gw2 =
Account(
"gateway2");
3369 auto const alice =
Account(
"alice");
3370 auto const USD = gw1[
"USD"];
3371 auto const EUR = gw2[
"EUR"];
3373 Env env{*
this, features};
3375 env.fund(
XRP(1000000), gw1, gw2);
3379 auto const f = env.current()->fees().base;
3393 TestData
const tests[]{
3404 for (
auto const& t : tests)
3406 auto const acct =
Account{t.acct};
3407 env.fund(t.fundXRP, acct);
3410 env(
trust(acct, USD(1000)));
3411 env(
trust(acct, EUR(1000)));
3414 if (t.fundUSD > USD(0))
3415 env(
pay(gw1, acct, t.fundUSD));
3416 if (t.fundEUR > EUR(0))
3417 env(
pay(gw2, acct, t.fundEUR));
3420 env(
offer(acct, USD(500), EUR(600)),
ter(t.firstOfferTec));
3424 int offerCount = t.firstOfferTec ==
tesSUCCESS ? 1 : 0;
3425 env.require(
owners(acct, 2 + offerCount));
3426 env.require(
balance(acct, t.fundUSD));
3427 env.require(
balance(acct, t.fundEUR));
3430 BEAST_EXPECT(acctOffers.size() == offerCount);
3431 for (
auto const& offerPtr : acctOffers)
3433 auto const&
offer = *offerPtr;
3434 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
3435 BEAST_EXPECT(
offer[sfTakerGets] == EUR(600));
3436 BEAST_EXPECT(
offer[sfTakerPays] == USD(500));
3439 env(
offer(acct, EUR(600), USD(500)),
ter(t.secondOfferTec));
3443 offerCount = t.secondOfferTec ==
tesSUCCESS ? 1 : offerCount;
3444 env.require(
owners(acct, 2 + offerCount));
3445 env.require(
balance(acct, t.fundUSD));
3446 env.require(
balance(acct, t.fundEUR));
3449 BEAST_EXPECT(acctOffers.size() == offerCount);
3450 for (
auto const& offerPtr : acctOffers)
3452 auto const&
offer = *offerPtr;
3453 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
3454 if (
offer[sfSequence] == firstOfferSeq)
3456 BEAST_EXPECT(
offer[sfTakerGets] == EUR(600));
3457 BEAST_EXPECT(
offer[sfTakerPays] == USD(500));
3461 BEAST_EXPECT(
offer[sfTakerGets] == USD(500));
3462 BEAST_EXPECT(
offer[sfTakerPays] == EUR(600));
3489 using namespace jtx;
3491 Env env{*
this, features};
3493 auto const alice =
Account(
"alice");
3494 auto const bob =
Account(
"bob");
3495 auto const USD = bob[
"USD"];
3496 auto const f = env.current()->fees().base;
3498 env.fund(
XRP(50000) + f, alice, bob);
3501 env(
offer(alice, USD(5000),
XRP(50000)));
3505 env(
offer(bob,
XRP(50000), USD(5000)));
3511 env.require(
owners(alice, 1));
3512 env.require(
lines(alice, 1));
3517 BEAST_EXPECT(bobOffers.size() == 1);
3518 for (
auto const& offerPtr : bobOffers)
3520 auto const&
offer = *offerPtr;
3521 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
3522 BEAST_EXPECT(
offer[sfTakerGets] == USD(25));
3523 BEAST_EXPECT(
offer[sfTakerPays] ==
XRP(250));
3535 using namespace jtx;
3537 Env env{*
this, features};
3540 auto const fee = env.current()->fees().base;
3543 auto const ann =
Account(
"ann");
3544 auto const A_BUX = ann[
"BUX"];
3545 auto const bob =
Account(
"bob");
3546 auto const cam =
Account(
"cam");
3547 auto const dan =
Account(
"dan");
3548 auto const D_BUX = dan[
"BUX"];
3551 env.fund(
reserve(env, 4) + (
fee * 4), ann, bob, cam, dan);
3554 env(
trust(bob, A_BUX(400)));
3556 env(
trust(cam, D_BUX(100)));
3558 env(
pay(dan, bob, D_BUX(100)));
3560 env.require(
balance(bob, D_BUX(100)));
3562 env(
pay(ann, cam, D_BUX(60)),
path(bob, dan),
sendmax(A_BUX(200)));
3567 env.require(
balance(bob, A_BUX(72)));
3568 env.require(
balance(bob, D_BUX(40)));
3570 env.require(
balance(cam, D_BUX(60)));
3574 env(
offer(bob, A_BUX(30), D_BUX(30)));
3577 env(
trust(ann, D_BUX(100)));
3581 env(
pay(ann, ann, D_BUX(30)),
3588 env.require(
balance(ann, D_BUX(0)));
3589 env.require(
balance(bob, A_BUX(72)));
3590 env.require(
balance(bob, D_BUX(40)));
3592 env.require(
balance(cam, D_BUX(60)));
3593 env.require(
balance(dan, A_BUX(0)));
3607 using namespace jtx;
3609 Env env{*
this, features};
3611 auto const ann =
Account(
"ann");
3612 auto const bob =
Account(
"bob");
3613 auto const cam =
Account(
"cam");
3614 auto const A_BUX = ann[
"BUX"];
3615 auto const B_BUX = bob[
"BUX"];
3617 auto const fee = env.current()->fees().base;
3618 env.fund(
reserve(env, 4) + (
fee * 5), ann, bob, cam);
3621 env(
trust(ann, B_BUX(40)));
3622 env(
trust(cam, A_BUX(40)));
3623 env(
trust(cam, B_BUX(40)));
3626 env(
pay(ann, cam, A_BUX(35)));
3627 env(
pay(bob, cam, B_BUX(35)));
3629 env(
offer(bob, A_BUX(30), B_BUX(30)));
3637 env.require(
balance(cam, A_BUX(35)));
3638 env.require(
balance(cam, B_BUX(35)));
3639 env.require(
offers(cam, 1));
3642 env(
offer(cam, B_BUX(30), A_BUX(30)));
3645 env.require(
balance(bob, A_BUX(30)));
3646 env.require(
balance(cam, A_BUX(5)));
3647 env.require(
balance(cam, B_BUX(65)));
3648 env.require(
offers(cam, 0));
3657 testcase(
"Self crossing low quality offer");
3659 using namespace jtx;
3661 Env env{*
this, features};
3663 auto const ann =
Account(
"ann");
3664 auto const gw =
Account(
"gateway");
3665 auto const BTC = gw[
"BTC"];
3667 auto const fee = env.current()->fees().base;
3672 env(
rate(gw, 1.002));
3673 env(
trust(ann, BTC(10)));
3676 env(
pay(gw, ann, BTC(2.856)));
3679 env(
offer(ann,
drops(365611702030), BTC(5.713)));
3683 env(
offer(ann, BTC(0.687),
drops(20000000000)),
3696 using namespace jtx;
3698 Env env{*
this, features};
3700 auto const gw =
Account(
"gateway");
3701 auto const alice =
Account(
"alice");
3702 auto const bob =
Account(
"bob");
3703 auto const CNY = gw[
"CNY"];
3705 auto const fee = env.current()->fees().base;
3710 env(
trust(bob, CNY(500)));
3713 env(
pay(gw, bob, CNY(300)));
3716 env(
offer(bob,
drops(5400000000), CNY(216.054)));
3720 env(
offer(alice, CNY(13562.0001),
drops(339000000000)));
3724 BEAST_EXPECT(aliceOffers.size() == 1);
3725 for (
auto const& offerPtr : aliceOffers)
3727 auto const&
offer = *offerPtr;
3728 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
3729 BEAST_EXPECT(
offer[sfTakerGets] ==
drops(333599446582));
3730 BEAST_EXPECT(
offer[sfTakerPays] == CNY(13345.9461));
3740 testcase(
"Offer In Scaling With Xfer Rate");
3742 using namespace jtx;
3744 Env env{*
this, features};
3746 auto const gw =
Account(
"gateway");
3747 auto const alice =
Account(
"alice");
3748 auto const bob =
Account(
"bob");
3749 auto const BTC = gw[
"BTC"];
3750 auto const JPY = gw[
"JPY"];
3752 auto const fee = env.current()->fees().base;
3757 env(
rate(gw, 1.002));
3758 env(
trust(alice, JPY(4000)));
3759 env(
trust(bob, BTC(2)));
3762 env(
pay(gw, alice, JPY(3699.034802280317)));
3763 env(
pay(gw, bob, BTC(1.156722559140311)));
3766 env(
offer(bob, JPY(1241.913390770747), BTC(0.01969825690469254)));
3770 env(
offer(alice, BTC(0.05507568706427876), JPY(3472.696773391072)));
3774 BEAST_EXPECT(aliceOffers.size() == 1);
3775 for (
auto const& offerPtr : aliceOffers)
3777 auto const&
offer = *offerPtr;
3778 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
3780 offer[sfTakerGets] ==
3782 BEAST_EXPECT(
offer[sfTakerPays] == BTC(0.035378));
3792 testcase(
"Offer Threshold With Reduced Funds");
3794 using namespace jtx;
3796 Env env{*
this, features};
3798 auto const gw1 =
Account(
"gw1");
3799 auto const gw2 =
Account(
"gw2");
3800 auto const alice =
Account(
"alice");
3801 auto const bob =
Account(
"bob");
3802 auto const USD = gw1[
"USD"];
3803 auto const JPY = gw2[
"JPY"];
3805 auto const fee = env.current()->fees().base;
3807 env.fund(
reserve(env, 2) + (
fee * 4), gw1, gw2);
3810 env(
rate(gw1, 1.002));
3811 env(
trust(alice, USD(1000)));
3812 env(
trust(bob, JPY(100000)));
3839 BEAST_EXPECT(aliceOffers.size() == 1);
3840 for (
auto const& offerPtr : aliceOffers)
3842 auto const&
offer = *offerPtr;
3843 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
3845 offer[sfTakerGets] ==
3848 offer[sfTakerPays] ==
3858 using namespace jtx;
3860 Env env{*
this, features};
3862 auto const gw =
Account(
"gw");
3863 auto const alice =
Account(
"alice");
3864 auto const bob =
Account(
"bob");
3865 auto const CNY = gw[
"CNY"];
3866 auto const fee = env.current()->fees().base;
3867 auto const startXrpBalance =
drops(400000000000) + (
fee * 2);
3869 env.fund(startXrpBalance, gw, alice, bob);
3872 env(
trust(bob, CNY(100000)));
3884 STAmount const bobsCnyStartBalance{
3886 env(
pay(gw, bob, bobsCnyStartBalance));
3895 env.require(
balance(alice, alicesCnyOffer));
3897 env.require(
balance(bob, bobsCnyStartBalance - alicesCnyOffer));
3940 using namespace jtx;
3942 Env env{*
this, features};
3943 auto const baseFee = env.current()->fees().base.drops();
3945 auto const gw =
Account(
"gw");
3946 auto const BTC = gw[
"BTC"];
3947 auto const USD = gw[
"USD"];
3948 auto const startXrpBalance =
XRP(4000000);
3950 env.fund(startXrpBalance, gw);
3953 env(
rate(gw, 1.25));
3979 TestData
const tests[]{
3981 {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)}}},
3982 {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)}}},
3983 {0, 0, 0, BTC(20), {{
"cam", 0,
drops(4000000'000000 - 5 * baseFee), BTC(20.0), USD(2000)} }},
3984 {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)}}},
3988 for (
auto const& t : tests)
3990 Account const& self = t.actors[t.self].acct;
3991 Account const& leg0 = t.actors[t.leg0].acct;
3992 Account const& leg1 = t.actors[t.leg1].acct;
3994 for (
auto const& actor : t.actors)
3996 env.fund(
XRP(4000000), actor.acct);
3999 env(
trust(actor.acct, BTC(40)));
4000 env(
trust(actor.acct, USD(8000)));
4004 env(
pay(gw, self, t.btcStart));
4005 env(
pay(gw, self, USD(2000)));
4006 if (self.
id() != leg1.
id())
4007 env(
pay(gw, leg1, USD(2000)));
4021 env(
offer(self, USD(1000), BTC(10)));
4026 for (
auto const& actor : t.actors)
4032 actorOffers.begin(),
4034 actorOffers.begin(),
4037 return (*offer)[sfTakerGets].signum() == 0;
4039 BEAST_EXPECT(offerCount == actor.offers);
4041 env.require(
balance(actor.acct, actor.xrp));
4042 env.require(
balance(actor.acct, actor.btc));
4043 env.require(
balance(actor.acct, actor.usd));
4059 testcase(
"Self Pay Unlimited Funds");
4091 using namespace jtx;
4093 Env env{*
this, features};
4094 auto const baseFee = env.current()->fees().base.drops();
4096 auto const gw =
Account(
"gw");
4097 auto const BTC = gw[
"BTC"];
4098 auto const USD = gw[
"USD"];
4099 auto const startXrpBalance =
XRP(4000000);
4101 env.fund(startXrpBalance, gw);
4104 env(
rate(gw, 1.25));
4130 TestData
const tests[]{
4132 {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)}}},
4133 {0, 0, 0, BTC(5), {{
"hye", 2,
drops(4000000'000000 - 5 * baseFee), BTC(5), USD(2000)} }}
4137 for (
auto const& t : tests)
4139 Account const& self = t.actors[t.self].acct;
4140 Account const& leg0 = t.actors[t.leg0].acct;
4141 Account const& leg1 = t.actors[t.leg1].acct;
4143 for (
auto const& actor : t.actors)
4145 env.fund(
XRP(4000000), actor.acct);
4148 env(
trust(actor.acct, BTC(40)));
4149 env(
trust(actor.acct, USD(8000)));
4153 env(
pay(gw, self, t.btcStart));
4154 env(
pay(gw, self, USD(2000)));
4155 if (self.
id() != leg1.
id())
4156 env(
pay(gw, leg1, USD(2000)));
4170 env(
offer(self, USD(1000), BTC(10)));
4175 for (
auto const& actor : t.actors)
4181 actorOffers.begin(),
4183 actorOffers.begin(),
4186 return (*offer)[sfTakerGets].signum() == 0;
4188 BEAST_EXPECT(offerCount == actor.offers);
4190 env.require(
balance(actor.acct, actor.xrp));
4191 env.require(
balance(actor.acct, actor.btc));
4192 env.require(
balance(actor.acct, actor.usd));
4210 using namespace jtx;
4212 Env env{*
this, features};
4214 auto const gw =
Account(
"gw");
4215 auto const alice =
Account(
"alice");
4216 auto const bob =
Account(
"bob");
4217 auto const gwUSD = gw[
"USD"];
4218 auto const aliceUSD = alice[
"USD"];
4219 auto const bobUSD = bob[
"USD"];
4221 env.fund(
XRP(400000), gw, alice, bob);
4230 env(
trust(bob, gwUSD(100)));
4232 env(
trust(alice, gwUSD(100)));
4234 env(
offer(alice, gwUSD(40),
XRP(4000)));
4237 env.require(
offers(alice, 1));
4238 env.require(
balance(alice, gwUSD(0)));
4240 env(
pay(gw, bob, gwUSD(50)));
4243 env.require(
balance(bob, gwUSD(50)));
4246 env(
offer(bob,
XRP(4000), gwUSD(40)));
4249 env.require(
offers(alice, 0));
4250 env.require(
balance(alice, gwUSD(40)));
4252 env.require(
offers(bob, 0));
4253 env.require(
balance(bob, gwUSD(10)));
4278 using namespace jtx;
4280 Env env{*
this, features};
4282 auto const gw =
Account(
"gw");
4283 auto const alice =
Account(
"alice");
4284 auto const bob =
Account(
"bob");
4285 auto const gwUSD = gw[
"USD"];
4286 auto const aliceUSD = alice[
"USD"];
4287 auto const bobUSD = bob[
"USD"];
4289 env.fund(
XRP(400000), gw, alice, bob);
4292 env(
offer(alice, gwUSD(40),
XRP(4000)));
4295 env.require(
offers(alice, 1));
4302 env(
trust(bob, gwUSD(100)));
4305 env(
pay(gw, bob, gwUSD(50)));
4307 env.require(
balance(bob, gwUSD(50)));
4314 env(
offer(bob,
XRP(4000), gwUSD(40)));
4318 env.require(
offers(alice, 0));
4321 env.require(
offers(bob, 1));
4322 env.require(
balance(bob, gwUSD(50)));
4330 env.require(
offers(alice, 0));
4333 env.require(
offers(bob, 1));
4334 env.require(
balance(bob, gwUSD(50)));
4338 env(
trust(gw, aliceUSD(100)));
4344 env.require(
offers(alice, 0));
4345 env.require(
balance(alice, gwUSD(0)));
4347 env.require(
offers(bob, 1));
4348 env.require(
balance(bob, gwUSD(50)));
4353 env.require(
offers(bob, 0));
4361 env(
offer(alice, gwUSD(40),
XRP(4000)));
4364 env.require(
offers(alice, 1));
4367 env(
offer(bob,
XRP(4000), gwUSD(40)));
4370 env.require(
offers(alice, 0));
4371 env.require(
balance(alice, gwUSD(40)));
4373 env.require(
offers(bob, 0));
4374 env.require(
balance(bob, gwUSD(10)));
4380 testcase(
"RippleConnect Smoketest payment flow");
4381 using namespace jtx;
4383 Env env{*
this, features};
4393 auto const hotUS =
Account(
"hotUS");
4394 auto const coldUS =
Account(
"coldUS");
4395 auto const hotEU =
Account(
"hotEU");
4396 auto const coldEU =
Account(
"coldEU");
4397 auto const mm =
Account(
"mm");
4399 auto const USD = coldUS[
"USD"];
4400 auto const EUR = coldEU[
"EUR"];
4402 env.fund(
XRP(100000), hotUS, coldUS, hotEU, coldEU, mm);
4406 for (
auto const& cold : {coldUS, coldEU})
4429 env(
pay(coldUS, hotUS, USD(5000000)));
4430 env(
pay(coldEU, hotEU, EUR(5000000)));
4431 env(
pay(coldUS, mm, USD(5000000)));
4432 env(
pay(coldEU, mm, EUR(5000000)));
4436 float const rate = 0.9f;
4437 env(
offer(mm, EUR(4000000 *
rate), USD(4000000)),
4440 float const reverseRate = 1.0f /
rate * 1.00101f;
4441 env(
offer(mm, USD(4000000 * reverseRate), EUR(4000000)),
4448 jvParams[jss::destination_account] = coldEU.human();
4449 jvParams[jss::destination_amount][jss::issuer] = coldEU.human();
4450 jvParams[jss::destination_amount][jss::currency] =
"EUR";
4451 jvParams[jss::destination_amount][jss::value] = 10;
4452 jvParams[jss::source_account] = hotUS.human();
4455 "json",
"ripple_path_find",
to_string(jvParams))[jss::result]};
4457 BEAST_EXPECT(jrr[jss::status] ==
"success");
4459 jrr[jss::alternatives].isArray() &&
4460 jrr[jss::alternatives].size() > 0);
4463 env(
pay(hotUS, coldEU, EUR(10)),
sendmax(USD(11.1223326)));
4471 using namespace jtx;
4473 Env env{*
this, features};
4475 auto const gw =
Account(
"gw");
4476 auto const alice =
Account(
"alice");
4477 auto const gwUSD = gw[
"USD"];
4478 auto const aliceUSD = alice[
"USD"];
4480 env.fund(
XRP(400000), gw, alice);
4484 env(
offer(gw, gwUSD(40),
XRP(4000)));
4487 env.require(
offers(gw, 1));
4496 env.require(
offers(gw, 0));
4503 bool const preauth = features[featureDepositPreauth];
4508 env(
offer(gw, gwUSD(40),
XRP(4000)),
4512 env.require(
offers(gw, preauth ? 1 : 0));
4520 env(
trust(alice, gwUSD(100)));
4523 env(
pay(gw, alice, gwUSD(50)));
4526 env.require(
balance(alice, gwUSD(50)));
4529 env(
offer(alice,
XRP(4000), gwUSD(40)));
4532 env.require(
offers(alice, 0));
4533 env.require(
balance(alice, gwUSD(10)));
4535 env.require(
offers(gw, 0));
4542 using namespace jtx;
4546 auto trustLineExists = [](
jtx::Env const& env,
4557 auto const USD = gw[
"USD"];
4558 auto const BUX = alice[
"BUX"];
4560 Env env{*
this, features};
4564 env.
trust(USD(1000), becky);
4565 env(
pay(gw, becky, USD(5)));
4567 BEAST_EXPECT(trustLineExists(env, gw, becky, USD.currency));
4578 env(
pay(becky, gw, USD(5)));
4579 env.
trust(USD(0), becky);
4581 BEAST_EXPECT(!trustLineExists(env, gw, becky, USD.currency));
4582 BEAST_EXPECT(
isOffer(env, becky,
XRP(2), USD(2)));
4583 BEAST_EXPECT(
isOffer(env, becky, BUX(3), USD(3)));
4590 [&env, &gw, openLedgerSeq = env.
current()->seq()]() ->
int {
4592 if (gwSeq + 255 > openLedgerSeq)
4593 return gwSeq - openLedgerSeq + 255;
4597 for (
int i = 0; i < delta; ++i)
4614 BEAST_EXPECT(
isOffer(env, becky,
XRP(2), USD(2)));
4615 BEAST_EXPECT(
isOffer(env, becky, BUX(3), USD(3)));
4621 BEAST_EXPECT(
isOffer(env, becky,
XRP(2), USD(2)));
4622 BEAST_EXPECT(
isOffer(env, becky, BUX(3), USD(3)));
4627 BEAST_EXPECT(!
isOffer(env, becky, BUX(3), USD(3)));
4631 env.
trust(BUX(1000), carol);
4632 env(
pay(alice, carol, BUX(2)));
4641 BEAST_EXPECT(
isOffer(env, alice, BUX(2),
XRP(2)));
4642 BEAST_EXPECT(
isOffer(env, becky,
XRP(2), USD(2)));
4650 using namespace jtx;
4654 Env env{*
this, features};
4655 auto const gw =
Account{
"gateway"};
4656 env.fund(
XRP(10000), gw);
4659 auto txn =
noop(gw);
4660 txn[sfTickSize.fieldName] = Quality::minTickSize - 1;
4663 txn[sfTickSize.fieldName] = Quality::minTickSize;
4665 BEAST_EXPECT((*env.le(gw))[sfTickSize] == Quality::minTickSize);
4668 txn[sfTickSize.fieldName] = Quality::maxTickSize;
4670 BEAST_EXPECT(!env.le(gw)->isFieldPresent(sfTickSize));
4673 txn[sfTickSize.fieldName] = Quality::maxTickSize - 1;
4675 BEAST_EXPECT((*env.le(gw))[sfTickSize] == Quality::maxTickSize - 1);
4678 txn[sfTickSize.fieldName] = Quality::maxTickSize + 1;
4681 txn[sfTickSize.fieldName] = 0;
4683 BEAST_EXPECT(!env.le(gw)->isFieldPresent(sfTickSize));
4686 Env env{*
this, features};
4687 auto const gw =
Account{
"gateway"};
4688 auto const alice =
Account{
"alice"};
4689 auto const XTS = gw[
"XTS"];
4690 auto const XXX = gw[
"XXX"];
4692 env.fund(
XRP(10000), gw, alice);
4697 auto txn =
noop(gw);
4698 txn[sfTickSize.fieldName] = 5;
4700 BEAST_EXPECT((*env.le(gw))[sfTickSize] == 5);
4703 env(
trust(alice, XTS(1000)));
4704 env(
trust(alice, XXX(1000)));
4706 env(
pay(gw, alice, alice[
"XTS"](100)));
4707 env(
pay(gw, alice, alice[
"XXX"](100)));
4709 env(
offer(alice, XTS(10), XXX(30)));
4710 env(
offer(alice, XTS(30), XXX(10)));
4717 if (sle->getType() == ltOFFER)
4721 (*sle)[sfTakerPays], (*sle)[sfTakerGets]));
4725 auto it =
offers.begin();
4726 BEAST_EXPECT(it !=
offers.end());
4728 it->second.first == XTS(10) && it->second.second < XXX(30) &&
4729 it->second.second > XXX(29.9994));
4733 BEAST_EXPECT(it !=
offers.end());
4735 it->second.first == XTS(30) && it->second.second == XXX(10));
4739 BEAST_EXPECT(it !=
offers.end());
4741 it->second.first == XTS(10.0002) && it->second.second == XXX(30));
4746 BEAST_EXPECT(it !=
offers.end());
4748 it->second.first == XTS(30) && it->second.second == XXX(10));
4750 BEAST_EXPECT(++it ==
offers.end());
4764 return (*rhs)[sfSequence] < (*lhs)[sfSequence];
4774 using namespace jtx;
4782 Env env{*
this, features};
4783 auto const gw =
Account{
"gateway"};
4784 auto const alice =
Account{
"alice"};
4785 auto const bob =
Account{
"bob"};
4786 auto const USD = gw[
"USD"];
4788 env.fund(
XRP(10000), gw, alice, bob);
4791 env(
trust(alice, USD(1000)));
4792 env(
trust(bob, USD(1000)));
4795 env(
pay(gw, alice, USD(200)));
4802 env(
offer(alice,
XRP(50), USD(50)));
4812 BEAST_EXPECT(offerId_1 == offerId_0 + 4);
4813 env(
offer(alice,
XRP(50), USD(50)));
4829 BEAST_EXPECT(
offers.size() == 4);
4830 BEAST_EXPECT(
offers[0]->getFieldU32(sfSequence) == offerId_0);
4831 BEAST_EXPECT(
offers[1]->getFieldU32(sfSequence) == offerId_3);
4832 BEAST_EXPECT(
offers[2]->getFieldU32(sfSequence) == offerId_2);
4833 BEAST_EXPECT(
offers[3]->getFieldU32(sfSequence) == offerId_1);
4834 env.require(
balance(alice, USD(200)));
4835 env.require(
owners(alice, 5));
4845 BEAST_EXPECT(
offers.size() == 3);
4846 BEAST_EXPECT(
offers[0]->getFieldU32(sfSequence) == offerId_3);
4847 BEAST_EXPECT(
offers[1]->getFieldU32(sfSequence) == offerId_2);
4848 BEAST_EXPECT(
offers[2]->getFieldU32(sfSequence) == offerId_1);
4858 BEAST_EXPECT(
offers.size() == 2);
4859 BEAST_EXPECT(
offers[0]->getFieldU32(sfSequence) == offerId_3);
4860 BEAST_EXPECT(
offers[1]->getFieldU32(sfSequence) == offerId_2);
4870 BEAST_EXPECT(
offers.size() == 1);
4871 BEAST_EXPECT(
offers[0]->getFieldU32(sfSequence) == offerId_3);
4881 BEAST_EXPECT(
offers.size() == 0);
4883 env.require(
balance(alice, USD(0)));
4884 env.require(
owners(alice, 1));
4885 env.require(
balance(bob, USD(200)));
4886 env.require(
owners(bob, 1));
4894 using namespace jtx;
4898 Env env{*
this, features};
4899 auto const gw =
Account{
"gateway"};
4900 auto const alice =
Account{
"alice"};
4901 auto const USD = gw[
"USD"];
4903 env.fund(
XRP(10000), gw, alice);
4906 env(
trust(alice, USD(1000)));
4910 env(
pay(gw, alice, USD(200)));
4915 env(
offer(alice,
XRP(50), USD(50)));
4927 BEAST_EXPECT(offerSeqId_1 == offerSeqId_0 + 6);
4928 env(
offer(alice,
XRP(50), USD(50)));
4944 BEAST_EXPECT(
offers.size() == 4);
4945 BEAST_EXPECT(
offers[0]->getFieldU32(sfSequence) == offerSeqId_0);
4946 BEAST_EXPECT(
offers[1]->getFieldU32(sfSequence) == offerTixId_1);
4947 BEAST_EXPECT(
offers[2]->getFieldU32(sfSequence) == offerTixId_0);
4948 BEAST_EXPECT(
offers[3]->getFieldU32(sfSequence) == offerSeqId_1);
4949 env.require(
balance(alice, USD(200)));
4950 env.require(
owners(alice, 7));
4960 BEAST_EXPECT(
offers.size() == 3);
4961 BEAST_EXPECT(
offers[0]->getFieldU32(sfSequence) == offerTixId_1);
4962 BEAST_EXPECT(
offers[1]->getFieldU32(sfSequence) == offerTixId_0);
4963 BEAST_EXPECT(
offers[2]->getFieldU32(sfSequence) == offerSeqId_1);
4973 BEAST_EXPECT(
offers.size() == 2);
4974 BEAST_EXPECT(
offers[0]->getFieldU32(sfSequence) == offerTixId_1);
4975 BEAST_EXPECT(
offers[1]->getFieldU32(sfSequence) == offerSeqId_1);
4988 BEAST_EXPECT(
offers.size() == 1);
4989 BEAST_EXPECT(
offers[0]->getFieldU32(sfSequence) == offerSeqId_1);
5006 testcase(
"incorrect assert fixed");
5007 using namespace jtx;
5010 auto const alice =
Account(
"alice");
5011 auto const USD = alice[
"USD"];
5013 env.fund(
XRP(10000), alice);
5015 env(
offer(alice,
XRP(100000000000), USD(100000000)));
5023 using namespace jtx;
5024 Env env(*
this, features);
5025 Account const issuer(
"issuer");
5028 auto const USD = issuer[
"USD"];
5029 auto const EUR = issuer[
"EUR"];
5032 env.
fund(
XRP(1'000), maker, taker);
5035 env.
trust(USD(1'000), maker, taker);
5036 env.
trust(EUR(1'000), maker, taker);
5039 env(
pay(issuer, maker, USD(1'000)));
5040 env(
pay(issuer, taker, USD(1'000)));
5041 env(
pay(issuer, maker, EUR(1'000)));
5044 auto makerUSDBalance = env.
balance(maker, USD).
value();
5045 auto takerUSDBalance = env.
balance(taker, USD).
value();
5046 auto makerEURBalance = env.
balance(maker, EUR).
value();
5047 auto takerEURBalance = env.
balance(taker, EUR).
value();
5056 env(
offer(maker,
XRP(100), USD(100)));
5059 env(
offer(taker, USD(100),
XRP(101)),
5064 makerXRPBalance -=
txfee(env, 1);
5065 takerXRPBalance -=
txfee(env, 1);
5068 makerUSDBalance -= USD(100);
5069 takerUSDBalance += USD(100);
5070 makerXRPBalance +=
XRP(100).value();
5071 takerXRPBalance -=
XRP(100).value();
5075 env(
offer(maker, USD(100),
XRP(100)));
5078 env(
offer(taker,
XRP(100), USD(101)),
5083 makerXRPBalance -=
txfee(env, 1);
5084 takerXRPBalance -=
txfee(env, 1);
5087 makerUSDBalance += USD(100);
5088 takerUSDBalance -= USD(100);
5089 makerXRPBalance -=
XRP(100).value();
5090 takerXRPBalance +=
XRP(100).value();
5094 env(
offer(maker, USD(100), EUR(100)));
5097 env(
offer(taker, EUR(100), USD(101)),
5102 makerXRPBalance -=
txfee(env, 1);
5103 takerXRPBalance -=
txfee(env, 1);
5106 makerUSDBalance += USD(100);
5107 takerUSDBalance -= USD(100);
5108 makerEURBalance -= EUR(100);
5109 takerEURBalance += EUR(100);
5116 env(
offer(maker,
XRP(101), USD(101)));
5119 env(
offer(taker, USD(100),
XRP(101)),
5123 makerUSDBalance -= USD(101);
5124 takerUSDBalance += USD(101);
5125 makerXRPBalance +=
XRP(101).value() -
txfee(env, 1);
5126 takerXRPBalance -=
XRP(101).value() +
txfee(env, 1);
5129 env(
offer(maker, USD(101),
XRP(101)));
5132 env(
offer(taker,
XRP(100), USD(101)),
5136 makerUSDBalance += USD(101);
5137 takerUSDBalance -= USD(101);
5138 makerXRPBalance -=
XRP(101).value() +
txfee(env, 1);
5139 takerXRPBalance +=
XRP(101).value() -
txfee(env, 1);
5142 env(
offer(maker, USD(101), EUR(101)));
5145 env(
offer(taker, EUR(100), USD(101)),
5149 makerUSDBalance += USD(101);
5150 takerUSDBalance -= USD(101);
5151 makerEURBalance -= EUR(101);
5152 takerEURBalance += EUR(101);
5153 makerXRPBalance -=
txfee(env, 1);
5154 takerXRPBalance -=
txfee(env, 1);
5161 env(
offer(maker,
XRP(100), USD(100)));
5164 env(
offer(taker, USD(100),
XRP(99)),
5169 makerXRPBalance -=
txfee(env, 1);
5170 takerXRPBalance -=
txfee(env, 1);
5173 env(
offer(maker, USD(100),
XRP(100)));
5176 env(
offer(taker,
XRP(100), USD(99)),
5181 makerXRPBalance -=
txfee(env, 1);
5182 takerXRPBalance -=
txfee(env, 1);
5185 env(
offer(maker, USD(100), EUR(100)));
5188 env(
offer(taker, EUR(100), USD(99)),
5193 makerXRPBalance -=
txfee(env, 1);
5194 takerXRPBalance -=
txfee(env, 1);
5199 env.
balance(maker, USD) == makerUSDBalance &&
5200 env.
balance(taker, USD) == takerUSDBalance &&
5201 env.
balance(maker, EUR) == makerEURBalance &&
5202 env.
balance(taker, EUR) == takerEURBalance &&
5203 env.
balance(maker,
XRP) == makerXRPBalance &&
5304 using namespace jtx;
5315BEAST_DEFINE_TESTSUITE_PRIO(OfferBaseUtil, app,
ripple, 2);
5316BEAST_DEFINE_TESTSUITE_PRIO(OfferWOSmallQOffers, app,
ripple, 2);
5317BEAST_DEFINE_TESTSUITE_PRIO(OfferAllFeatures, app,
ripple, 2);
5318BEAST_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