21 #include <test/jtx/WSClient.h>
22 #include <test/jtx/PathSet.h>
23 #include <ripple/protocol/Feature.h>
24 #include <ripple/protocol/jss.h>
25 #include <ripple/protocol/Quality.h>
34 return env.
current()->fees().accountReserve (count);
39 return env.
current()->info().parentCloseTime.time_since_epoch().count();
47 auto feeDrops = env.current()->fees().base;
56 jvParams[jss::ledger_index] =
"current";
57 jvParams[jss::ripple_state][jss::currency] = currency;
59 jvParams[jss::ripple_state][jss::accounts].
append(acct_a.
human());
60 jvParams[jss::ripple_state][jss::accounts].
append(acct_b.
human());
61 return env.
rpc (
"json",
"ledger_entry",
69 jvParams[jss::ledger_index] =
"current";
70 jvParams[jss::account_root] = acct.
human();
71 return env.
rpc (
"json",
"ledger_entry",
80 jvParams[jss::offer][jss::account] = acct.
human();
81 jvParams[jss::offer][jss::seq] = offer_seq;
82 return env.
rpc (
"json",
"ledger_entry",
88 Issue const& taker_pays,
Issue const& taker_gets)
91 jvbp[jss::ledger_index] =
"current";
96 return env.
rpc(
"json",
"book_offers",
to_string(jvbp)) [jss::result];
102 testcase (
"Incorrect Removal of Funded Offers");
114 Env env {*
this, features};
116 auto const gw =
Account {
"gateway"};
117 auto const USD = gw[
"USD"];
118 auto const BTC = gw[
"BTC"];
123 env.fund (
XRP (10000), alice, bob, carol, gw);
124 env.trust (USD (1000), alice, bob, carol);
125 env.trust (BTC (1000), alice, bob, carol);
127 env (
pay (gw, alice, BTC (1000)));
129 env (
pay (gw, carol, USD (1000)));
130 env (
pay (gw, carol, BTC (1000)));
135 env (
offer (carol, BTC (49),
XRP (49)));
136 env (
offer (carol, BTC (51),
XRP (51)));
140 env (
offer (carol,
XRP (50), USD (50)));
141 env (
offer (carol,
XRP (50), USD (50)));
144 env (
offer (carol, BTC (1), USD (100)));
151 env.require (
balance (bob, USD (100)));
152 BEAST_EXPECT(!
isOffer (env, carol, BTC (1), USD (100)) &&
158 testcase (
"Removing Canceled Offers");
161 Env env {*
this, features};
163 auto const gw =
Account {
"gateway"};
164 auto const alice =
Account {
"alice"};
165 auto const USD = gw[
"USD"];
167 env.fund (
XRP (10000), alice, gw);
169 env.trust (USD (100), alice);
172 env (
pay (gw, alice, USD (50)));
175 auto const offer1Seq = env.seq (alice);
177 env (
offer (alice,
XRP (500), USD (100)),
181 BEAST_EXPECT(
isOffer (env, alice,
XRP (500), USD (100)));
184 auto const offer2Seq = env.seq (alice);
186 env (
offer (alice,
XRP (300), USD (100)),
187 json (jss::OfferSequence, offer1Seq),
191 BEAST_EXPECT(
isOffer (env, alice,
XRP (300), USD (100)) &&
197 env (
offer (alice,
XRP (400), USD (200)),
198 json (jss::OfferSequence, offer1Seq),
202 BEAST_EXPECT(
isOffer (env, alice,
XRP (300), USD (100)) &&
206 auto const offer4Seq = env.seq (alice);
207 env (
offer (alice,
XRP (222), USD (111)),
211 BEAST_EXPECT(
isOffer (env, alice,
XRP (222), USD (111)));
214 cancelOffer[jss::Account] = alice.human();
215 cancelOffer[jss::OfferSequence] = offer4Seq;
216 cancelOffer[jss::TransactionType] = jss::OfferCancel;
220 BEAST_EXPECT(env.seq(alice) == offer4Seq + 2);
222 BEAST_EXPECT(!
isOffer (env, alice,
XRP (222), USD (111)));
226 env.require (
offers (alice, 2));
231 env (
offer (alice,
XRP (5), USD (2)),
233 json (jss::OfferSequence, offer2Seq),
237 env.require (
offers (alice, 2));
238 BEAST_EXPECT(
isOffer (env, alice,
XRP (300), USD (100)));
239 BEAST_EXPECT(!
isOffer (env, alice,
XRP (5), USD (2)));
244 testcase (
"Tiny payments");
248 using namespace std::chrono_literals;
249 auto const alice =
Account {
"alice"};
250 auto const bob =
Account {
"bob"};
251 auto const carol =
Account {
"carol"};
252 auto const gw =
Account {
"gw"};
254 auto const USD = gw[
"USD"];
255 auto const EUR = gw[
"EUR"];
257 Env env {*
this, features};
259 env.fund (
XRP (10000), alice, bob, carol, gw);
260 env.trust (USD (1000), alice, bob, carol);
261 env.trust (EUR (1000), alice, bob, carol);
262 env (
pay (gw, alice, USD (100)));
263 env (
pay (gw, carol, EUR (100)));
269 for (
int i = 0; i < 101; ++i)
270 env (
offer (carol, USD (1), EUR (2)));
272 env (
pay (alice, bob, EUR (epsilon)),
path (~EUR),
sendmax (USD (100)));
277 testcase (
"XRP Tiny payments");
295 using namespace std::chrono_literals;
296 auto const alice =
Account {
"alice"};
297 auto const bob =
Account {
"bob"};
298 auto const carol =
Account {
"carol"};
299 auto const dan =
Account {
"dan"};
300 auto const erin =
Account {
"erin"};
301 auto const gw =
Account {
"gw"};
303 auto const USD = gw[
"USD"];
304 Env env {*
this, features};
306 env.fund (
XRP (10000), alice, bob, carol, dan, erin, gw);
307 env.trust (USD (1000), alice, bob, carol, dan, erin);
308 env (
pay (gw, carol, USD (0.99999)));
309 env (
pay (gw, dan, USD (1)));
310 env (
pay (gw, erin, USD (1)));
320 env (
offer (dan,
XRP (100), USD (1)));
331 env (
pay (alice, bob, USD (1)),
path (~USD),
348 testcase (
"Enforce No Ripple");
352 auto const gw =
Account {
"gateway"};
353 auto const USD = gw[
"USD"];
354 auto const BTC = gw[
"BTC"];
355 auto const EUR = gw[
"EUR"];
363 Env env {*
this, features};
365 auto const gw1 =
Account {
"gw1"};
366 auto const USD1 = gw1[
"USD"];
367 auto const gw2 =
Account {
"gw2"};
368 auto const USD2 = gw2[
"USD"];
370 env.fund (
XRP (10000), alice,
noripple (bob), carol, dan, gw1, gw2);
371 env.trust (USD1 (1000), alice, carol, dan);
373 env.trust (USD2 (1000), alice, carol, dan);
376 env (
pay (gw1, dan, USD1 (50)));
377 env (
pay (gw1, bob, USD1 (50)));
378 env (
pay (gw2, bob, USD2 (50)));
380 env (
offer (dan,
XRP (50), USD1 (50)));
382 env (
pay (alice, carol, USD2 (50)),
path (~USD1, bob),
388 Env env {*
this, features};
390 auto const gw1 =
Account {
"gw1"};
391 auto const USD1 = gw1[
"USD"];
392 auto const gw2 =
Account {
"gw2"};
393 auto const USD2 = gw2[
"USD"];
395 env.fund (
XRP (10000), alice, bob, carol, dan, gw1, gw2);
396 env.trust (USD1 (1000), alice, bob, carol, dan);
397 env.trust (USD2 (1000), alice, bob, carol, dan);
399 env (
pay (gw1, dan, USD1 (50)));
400 env (
pay (gw1, bob, USD1 (50)));
401 env (
pay (gw2, bob, USD2 (50)));
403 env (
offer (dan,
XRP (50), USD1 (50)));
405 env (
pay (alice, carol, USD2 (50)),
path (~USD1, bob),
409 env.require (
balance (bob, USD1 (100)));
410 env.require (
balance (bob, USD2 (0)));
411 env.require (
balance (carol, USD2 (50)));
418 testcase (
"Insufficient Reserve");
428 auto const gw =
Account {
"gateway"};
429 auto const alice =
Account {
"alice"};
430 auto const bob =
Account {
"bob"};
431 auto const carol =
Account {
"carol"};
432 auto const USD = gw[
"USD"];
434 auto const usdOffer = USD (1000);
435 auto const xrpOffer =
XRP (1000);
439 Env env {*
this, features};
441 env.fund (
XRP (1000000), gw);
443 auto const f = env.current ()->fees ().
base;
444 auto const r =
reserve (env, 0);
446 env.fund (r + f, alice);
450 env (
offer (alice, xrpOffer, usdOffer),
460 Env env {*
this, features};
462 env.fund (
XRP (1000000), gw);
464 auto const f = env.current ()->fees ().
base;
465 auto const r =
reserve (env, 0);
467 auto const usdOffer2 = USD (500);
468 auto const xrpOffer2 =
XRP (500);
470 env.fund (r + f + xrpOffer, bob);
472 env.fund (r + f, alice);
478 balance (alice, r - f + xrpOffer2),
490 Env env {*
this, features};
492 env.fund (
XRP (1000000), gw);
494 auto const f = env.current ()->fees ().
base;
495 auto const r =
reserve (env, 0);
497 auto const usdOffer2 = USD (500);
498 auto const xrpOffer2 =
XRP (500);
500 env.fund (r + f + xrpOffer, bob, carol);
504 env.fund (r + f, alice);
510 balance (alice, r - f + xrpOffer),
516 balance (carol, r + xrpOffer2),
530 if (sle->getType() == ltOFFER)
531 result.push_back (sle);
539 testcase (
"Fill Modes");
543 auto const startBalance =
XRP (1000000);
544 auto const gw =
Account {
"gateway"};
545 auto const alice =
Account {
"alice"};
546 auto const bob =
Account {
"bob"};
547 auto const USD = gw[
"USD"];
555 for (
auto const tweakedFeatures :
558 Env env {*
this, tweakedFeatures};
560 auto const f = env.
current ()->fees ().base;
562 env.fund (startBalance, gw, alice, bob);
565 env (
offer (bob, USD (500),
XRP (500)),
587 TER const killedCode {tweakedFeatures[
fix1578] ?
589 env (
offer (alice,
XRP (1000), USD (1000)),
593 balance (alice, startBalance - (f * 2)),
597 balance (bob, startBalance - (f * 2)),
603 env (
offer (alice,
XRP (500), USD (500)),
607 balance (alice, startBalance - (f * 3) +
XRP (500)),
611 balance (bob, startBalance - (f * 2) -
XRP (500)),
620 Env env {*
this, features};
622 auto const f = env.current ()->fees ().
base;
624 env.fund (startBalance, gw, alice, bob);
630 env (
offer (alice,
XRP (1000), USD (1000)),
634 balance (alice, startBalance - f - f),
641 env (
offer (alice,
XRP (1000), USD (1000)),
645 balance (alice, startBalance - f - f - f +
XRP (50)),
656 env (
offer (alice,
XRP (50), USD (50)),
660 balance (alice, startBalance - f - f - f - f +
XRP (100)),
664 balance (bob, startBalance - f - f -
XRP (100)),
672 Env env (*
this, features);
674 env.
fund (startBalance, gw, alice, bob);
677 env (
trust (bob, USD(1000)));
680 env (
pay (gw, bob, USD(1000)));
683 env (
offer (alice, USD(1000),
XRP(2000)));
687 BEAST_EXPECT (aliceOffers.size() == 1);
688 for (
auto offerPtr : aliceOffers)
690 auto const&
offer = *offerPtr;
702 BEAST_EXPECT (bobOffers.size() == 1);
703 for (
auto offerPtr : bobOffers)
705 auto const&
offer = *offerPtr;
711 env (
offer (gw,
XRP(2000), USD(1000)));
717 env (
offer (gw, USD(1000),
XRP(2000)));
725 Env env (*
this, features);
727 env.
fund (startBalance, gw,
"alice",
"bob");
730 env (
trust (
"bob", USD(1000)));
733 env (
pay (gw,
"bob", USD(1000)));
734 env (
offer (
"alice", USD(500),
XRP(1001)));
737 env (
offer (
"alice", USD(500),
XRP(1000)));
741 BEAST_EXPECT (aliceOffers.size() == 2);
751 BEAST_EXPECT (bobOffers.size() == 1);
752 for (
auto offerPtr : bobOffers)
754 auto const&
offer = *offerPtr;
764 testcase (
"Malformed Detection");
768 auto const startBalance =
XRP(1000000);
769 auto const gw =
Account {
"gateway"};
770 auto const alice =
Account {
"alice"};
771 auto const USD = gw[
"USD"];
773 Env env {*
this, features};
775 env.fund (startBalance, gw, alice);
778 env (
offer (alice, USD (1000),
XRP (1000)),
786 env (
offer (alice, USD (1000),
XRP (1000)),
825 env (
offer (alice, USD (1000),
XRP (1000)),
835 env (
offer (alice, USD (1000),
XRP (1000)),
857 testcase (
"Offer Expiration");
861 auto const gw =
Account {
"gateway"};
862 auto const alice =
Account {
"alice"};
863 auto const bob =
Account {
"bob"};
864 auto const USD = gw[
"USD"];
866 auto const startBalance =
XRP (1000000);
867 auto const usdOffer = USD (1000);
868 auto const xrpOffer =
XRP (1000);
870 Env env {*
this, features};
872 env.fund (startBalance, gw, alice, bob);
875 auto const f = env.current ()->fees ().
base;
881 balance (alice, startBalance - f),
890 env (
offer (alice, xrpOffer, usdOffer),
895 balance (alice, startBalance - f - f),
902 env (
offer (alice, xrpOffer, usdOffer),
906 balance (alice, startBalance - f - f - f),
914 balance (alice, startBalance - f - f - f),
922 balance (alice, startBalance - f - f - f),
926 balance (bob, startBalance - f),
935 testcase (
"Unfunded Crossing");
939 auto const gw =
Account {
"gateway"};
940 auto const USD = gw[
"USD"];
942 auto const usdOffer = USD (1000);
943 auto const xrpOffer =
XRP (1000);
945 Env env {*
this, features};
947 env.fund (
XRP(1000000), gw);
950 auto const f = env.current()->fees().
base;
954 env.fund (
reserve (env, 0),
"alice");
962 env.fund (
reserve (env, 0) + f,
"bob");
971 env.fund (
reserve (env, 0) + f +
XRP(1),
"carol");
979 env.fund (
reserve (env, 1) + f,
"dan");
987 env.fund (
reserve (env, 1) + f + xrpOffer,
"eve");
998 (use_partner ?
", with partner account" :
""));
1000 using namespace jtx;
1002 auto const gw =
Account {
"gateway"};
1003 auto const partner =
Account {
"partner"};
1004 auto const USD = gw[
"USD"];
1005 auto const BTC = gw[
"BTC"];
1007 Env env {*
this, features};
1010 env.fund (
XRP (10000), gw);
1013 env.fund (
XRP (10000), partner);
1014 env (
trust (partner, USD (100)));
1015 env (
trust (partner, BTC (500)));
1016 env (
pay (gw, partner, USD(100)));
1017 env (
pay (gw, partner, BTC(500)));
1019 auto const& account_to_test = use_partner ? partner : gw;
1022 env.require (
offers (account_to_test, 0));
1027 env (
offer (account_to_test, BTC (250),
XRP (1000)));
1028 env.require (
offers(account_to_test, 1));
1031 BEAST_EXPECT(
isOffer(env, account_to_test, BTC(250),
XRP(1000)));
1033 auto const secondLegSeq = env.seq(account_to_test);
1034 env (
offer (account_to_test,
XRP(1000), USD (50)));
1035 env.require (
offers (account_to_test, 2));
1038 BEAST_EXPECT(
isOffer(env, account_to_test,
XRP(1000), USD(50)));
1042 env (
offer (account_to_test, USD (50), BTC (250)));
1045 BEAST_EXPECT(jrr[jss::offers].isArray());
1046 BEAST_EXPECT(jrr[jss::offers].size() == 0);
1049 BEAST_EXPECT(jrr[jss::offers].isArray());
1050 BEAST_EXPECT(jrr[jss::offers].size() == 0);
1061 bool const noStaleOffers {
1065 BEAST_EXPECT(acctOffers.size() == (noStaleOffers ? 0 : 1));
1066 for (
auto const& offerPtr : acctOffers)
1068 auto const&
offer = *offerPtr;
1079 cancelOffer[jss::Account] = account_to_test.human();
1080 cancelOffer[jss::OfferSequence] = secondLegSeq;
1081 cancelOffer[jss::TransactionType] = jss::OfferCancel;
1083 env.require (
offers (account_to_test, 0));
1088 env (
offer (account_to_test, BTC (250), USD (50)));
1089 env.require (
offers (account_to_test, 1));
1093 BEAST_EXPECT(
isOffer(env, account_to_test, BTC(250), USD(50)));
1096 BEAST_EXPECT(jrr[jss::offers].isArray());
1097 BEAST_EXPECT(jrr[jss::offers].size() == 0);
1101 env (
offer (account_to_test, USD (50), BTC (250)));
1102 env.require (
offers (account_to_test, 1));
1107 BEAST_EXPECT(jrr[jss::offers].isArray());
1108 BEAST_EXPECT(jrr[jss::offers].size() == 0);
1110 BEAST_EXPECT(
isOffer(env, account_to_test, USD(50), BTC(250)));
1118 testcase (
"Negative Balance");
1120 using namespace jtx;
1122 Env env {*
this, features};
1124 auto const gw =
Account {
"gateway"};
1125 auto const alice =
Account {
"alice"};
1126 auto const bob =
Account {
"bob"};
1127 auto const USD = gw[
"USD"];
1128 auto const BTC = gw[
"BTC"];
1132 auto const gw_initial_balance =
drops (1149999730);
1133 auto const alice_initial_balance =
drops (499946999680);
1134 auto const bob_initial_balance =
drops (10199999920);
1135 auto const small_amount =
1136 STAmount { bob[
"USD"].
issue(), UINT64_C(2710505431213761), -33};
1138 env.fund (gw_initial_balance, gw);
1139 env.fund (alice_initial_balance, alice);
1140 env.fund (bob_initial_balance, bob);
1142 env (
rate (gw, 1.005));
1144 env (
trust (alice, USD (500)));
1145 env (
trust (bob, USD (50)));
1146 env (
trust (gw, alice[
"USD"] (100)));
1148 env (
pay (gw, alice, alice[
"USD"] (50)));
1149 env (
pay (gw, bob, small_amount));
1151 env (
offer (alice, USD (50),
XRP (150000)));
1154 env (
pay (alice, gw, USD (100)));
1157 env (
trust (gw, alice[
"USD"] (0)));
1166 "-2710505431213761e-33");
1169 env (
offer (bob,
XRP (2000), USD (1)));
1182 BEAST_EXPECT(env.balance (alice,
xrpIssue()) ==
1183 alice_initial_balance -
1184 env.current ()->fees ().base * 3 - crossingDelta
1189 BEAST_EXPECT(env.balance (bob,
xrpIssue()) ==
1190 bob_initial_balance -
1191 env.current ()->fees ().base * 2 + crossingDelta
1198 testcase (
std::string(
"Offer Crossing with XRP, ") +
1199 (reverse_order ?
"Reverse" :
"Normal") +
1202 using namespace jtx;
1204 Env env {*
this, features};
1206 auto const gw =
Account {
"gateway"};
1207 auto const alice =
Account {
"alice"};
1208 auto const bob =
Account {
"bob"};
1209 auto const USD = gw[
"USD"];
1211 env.fund (
XRP (10000), gw, alice, bob);
1213 env (
trust (alice, USD (1000)));
1214 env (
trust (bob, USD (1000)));
1216 env (
pay (gw, alice, alice[
"USD"] (500)));
1219 env (
offer (bob, USD (1),
XRP (4000)));
1221 env (
offer (alice,
XRP (150000), USD (50)));
1223 if (! reverse_order)
1224 env (
offer (bob, USD (1),
XRP (4000)));
1237 XRP (reverse_order ? 4000 : 3000) -
1238 env.current ()->fees ().base * 2).xrp())
1248 XRP(reverse_order ? 4000 : 3000) -
1249 env.current ()->fees ().base * 2).xrp ())
1256 testcase (
"Offer Crossing with Limit Override");
1258 using namespace jtx;
1260 Env env {*
this, features};
1262 auto const gw =
Account {
"gateway"};
1263 auto const alice =
Account {
"alice"};
1264 auto const bob =
Account {
"bob"};
1265 auto const USD = gw[
"USD"];
1267 env.fund (
XRP (100000), gw, alice, bob);
1269 env (
trust (alice, USD (1000)));
1271 env (
pay (gw, alice, alice[
"USD"] (500)));
1273 env (
offer (alice,
XRP (150000), USD (50)));
1274 env (
offer (bob, USD (1),
XRP (3000)));
1284 env.current ()->fees ().base * 1).xrp ())
1295 env.current ()->fees ().base * 2).xrp ())
1302 testcase (
"Offer Accept then Cancel.");
1304 using namespace jtx;
1306 Env env {*
this, features};
1308 auto const USD = env.master[
"USD"];
1310 auto const nextOfferSeq = env.seq (env.master);
1311 env (
offer (env.master,
XRP (500), USD (100)));
1315 cancelOffer[jss::Account] = env.master.human();
1316 cancelOffer[jss::OfferSequence] = nextOfferSeq;
1317 cancelOffer[jss::TransactionType] = jss::OfferCancel;
1319 BEAST_EXPECT(env.seq (env.master) == nextOfferSeq + 2);
1324 BEAST_EXPECT(env.seq (env.master) == nextOfferSeq + 2);
1331 testcase (
"Offer Cancel Past and Future Sequence.");
1333 using namespace jtx;
1335 Env env {*
this, features};
1337 auto const alice =
Account {
"alice"};
1339 auto const nextOfferSeq = env.seq (env.master);
1340 env.fund (
XRP (10000), alice);
1343 cancelOffer[jss::Account] = env.master.human();
1344 cancelOffer[jss::OfferSequence] = nextOfferSeq;
1345 cancelOffer[jss::TransactionType] = jss::OfferCancel;
1348 cancelOffer[jss::OfferSequence] = env.seq (env.master);
1351 cancelOffer[jss::OfferSequence] = env.seq (env.master) + 1;
1361 testcase (
"Currency Conversion: Entire Offer");
1363 using namespace jtx;
1365 Env env {*
this, features};
1367 auto const gw =
Account {
"gateway"};
1368 auto const alice =
Account {
"alice"};
1369 auto const bob =
Account {
"bob"};
1370 auto const USD = gw[
"USD"];
1372 env.fund (
XRP (10000), gw, alice, bob);
1373 env.require (
owners (bob, 0));
1375 env (
trust (alice, USD (100)));
1376 env (
trust (bob, USD (1000)));
1382 env (
pay (gw, alice, alice[
"USD"] (100)));
1383 auto const bobOfferSeq = env.seq (bob);
1384 env (
offer (bob, USD (100),
XRP (500)));
1391 jro[jss::node][jss::TakerGets] ==
XRP (500).value ().getText ());
1393 jro[jss::node][jss::TakerPays] ==
1406 env.current ()->fees ().base * 2).xrp ())
1413 BEAST_EXPECT(jro[jss::error] ==
"entryNotFound");
1423 testcase (
"Currency Conversion: Offerer Into Debt");
1425 using namespace jtx;
1427 Env env {*
this, features};
1429 auto const alice =
Account {
"alice"};
1430 auto const bob =
Account {
"bob"};
1431 auto const carol =
Account {
"carol"};
1433 env.fund (
XRP (10000), alice, bob, carol);
1435 env (
trust (alice, carol[
"EUR"] (2000)));
1436 env (
trust (bob, alice[
"USD"] (100)));
1437 env (
trust (carol, bob[
"EUR"] (1000)));
1439 auto const bobOfferSeq = env.seq (bob);
1440 env (
offer (bob, alice[
"USD"] (50), carol[
"EUR"] (200)),
1443 env (
offer (alice, carol[
"EUR"] (200), alice[
"USD"] (50)));
1446 BEAST_EXPECT(jro[jss::error] ==
"entryNotFound");
1452 testcase (
"Currency Conversion: In Parts");
1454 using namespace jtx;
1456 Env env {*
this, features};
1458 auto const gw =
Account {
"gateway"};
1459 auto const alice =
Account {
"alice"};
1460 auto const bob =
Account {
"bob"};
1461 auto const USD = gw[
"USD"];
1463 env.fund (
XRP (10000), gw, alice, bob);
1465 env (
trust (alice, USD (200)));
1466 env (
trust (bob, USD (1000)));
1468 env (
pay (gw, alice, alice[
"USD"] (200)));
1470 auto const bobOfferSeq = env.seq (bob);
1471 env (
offer (bob, USD (100),
XRP (500)));
1478 jro[jss::node][jss::TakerGets] ==
XRP (300).value ().getText ());
1480 jro[jss::node][jss::TakerPays] ==
1494 env.current ()->fees ().base * 2).xrp ())
1513 BEAST_EXPECT(jro[jss::error] ==
"entryNotFound");
1529 env.current ()->fees ().base * 4).xrp ())
1541 testcase (
"Cross Currency Payment: Start with XRP");
1543 using namespace jtx;
1545 Env env {*
this, features};
1547 auto const gw =
Account {
"gateway"};
1548 auto const alice =
Account {
"alice"};
1549 auto const bob =
Account {
"bob"};
1550 auto const carol =
Account {
"carol"};
1551 auto const USD = gw[
"USD"];
1553 env.fund (
XRP (10000), gw, alice, bob, carol);
1555 env (
trust (carol, USD (1000)));
1556 env (
trust (bob, USD (2000)));
1558 env (
pay (gw, carol, carol[
"USD"] (500)));
1560 auto const carolOfferSeq = env.seq (carol);
1561 env (
offer (carol,
XRP (500), USD (50)));
1573 jro[jss::node][jss::TakerGets] ==
1576 jro[jss::node][jss::TakerPays] ==
XRP (250).value ().getText ());
1582 testcase (
"Cross Currency Payment: End with XRP");
1584 using namespace jtx;
1586 Env env {*
this, features};
1588 auto const gw =
Account {
"gateway"};
1589 auto const alice =
Account {
"alice"};
1590 auto const bob =
Account {
"bob"};
1591 auto const carol =
Account {
"carol"};
1592 auto const USD = gw[
"USD"];
1594 env.fund (
XRP (10000), gw, alice, bob, carol);
1596 env (
trust (alice, USD (1000)));
1597 env (
trust (carol, USD (2000)));
1599 env (
pay (gw, alice, alice[
"USD"] (500)));
1601 auto const carolOfferSeq = env.seq (carol);
1602 env (
offer (carol, USD (50),
XRP (500)));
1616 XRP (10000).value ().mantissa () +
1617 XRP (250).value ().mantissa ())
1622 jro[jss::node][jss::TakerGets] ==
XRP (250).value ().getText ());
1624 jro[jss::node][jss::TakerPays] ==
1631 testcase (
"Cross Currency Payment: Bridged");
1633 using namespace jtx;
1635 Env env {*
this, features};
1637 auto const gw1 =
Account {
"gateway_1"};
1638 auto const gw2 =
Account {
"gateway_2"};
1639 auto const alice =
Account {
"alice"};
1640 auto const bob =
Account {
"bob"};
1641 auto const carol =
Account {
"carol"};
1642 auto const dan =
Account {
"dan"};
1643 auto const USD = gw1[
"USD"];
1644 auto const EUR = gw2[
"EUR"];
1646 env.fund (
XRP (10000), gw1, gw2, alice, bob, carol, dan);
1648 env (
trust (alice, USD (1000)));
1649 env (
trust (bob, EUR (1000)));
1650 env (
trust (carol, USD (1000)));
1651 env (
trust (dan, EUR (1000)));
1653 env (
pay (gw1, alice, alice[
"USD"] (500)));
1654 env (
pay (gw2, dan, dan[
"EUR"] (400)));
1656 auto const carolOfferSeq = env.seq (carol);
1657 env (
offer (carol, USD (50),
XRP (500)));
1659 auto const danOfferSeq = env.seq (dan);
1660 env (
offer (dan,
XRP (500), EUR (50)));
1663 jtp[0u][0u][jss::currency] =
"XRP";
1664 env (
pay (alice, bob, EUR (30)),
1665 json (jss::Paths, jtp),
1682 jro[jss::node][jss::TakerGets] ==
XRP (200).value ().getText ());
1684 jro[jss::node][jss::TakerPays] ==
1689 jro[jss::node][jss::TakerGets] ==
1692 jro[jss::node][jss::TakerPays] ==
XRP (200).value ().getText ());
1701 testcase (
"Auto Bridged Second Leg Dry");
1703 using namespace jtx;
1704 Env env(*
this, features);
1706 Account const alice {
"alice"};
1708 Account const carol {
"carol"};
1710 auto const USD = gw[
"USD"];
1711 auto const EUR = gw[
"EUR"];
1713 env.
fund(
XRP(100000000), alice, bob, carol, gw);
1715 env.
trust(USD(10), alice);
1717 env(
pay(gw, alice, USD(10)));
1718 env.
trust(USD(10), carol);
1720 env(
pay(gw, carol, USD(3)));
1722 env (
offer (alice, EUR(2),
XRP(1)));
1723 env (
offer (alice, EUR(2),
XRP(1)));
1725 env (
offer (alice,
XRP(1), USD(4)));
1726 env (
offer (carol,
XRP(1), USD(3)));
1737 env.
trust(EUR(10), bob);
1739 env(
pay(gw, bob, EUR(10)));
1741 env(
offer(bob, USD(10), EUR(10)));
1758 int const emptyOfferCount {
1769 testcase (
"Offer Fees Consume Funds");
1771 using namespace jtx;
1773 Env env {*
this, features};
1775 auto const gw1 =
Account {
"gateway_1"};
1776 auto const gw2 =
Account {
"gateway_2"};
1777 auto const gw3 =
Account {
"gateway_3"};
1778 auto const alice =
Account {
"alice"};
1779 auto const bob =
Account {
"bob"};
1780 auto const USD1 = gw1[
"USD"];
1781 auto const USD2 = gw2[
"USD"];
1782 auto const USD3 = gw3[
"USD"];
1790 auto const starting_xrp =
XRP (100) +
1791 env.current ()->fees ().accountReserve (3) +
1792 env.current ()->fees ().base * 4;
1794 env.fund (starting_xrp, gw1, gw2, gw3, alice, bob);
1796 env (
trust (alice, USD1 (1000)));
1797 env (
trust (alice, USD2 (1000)));
1798 env (
trust (alice, USD3 (1000)));
1799 env (
trust (bob, USD1 (1000)));
1800 env (
trust (bob, USD2 (1000)));
1802 env (
pay (gw1, bob, bob[
"USD"] (500)));
1804 env (
offer (bob,
XRP (200), USD1 (200)));
1807 env (
offer (alice, USD1 (200),
XRP (200)));
1823 testcase (
"Offer Create, then Cross");
1825 using namespace jtx;
1827 Env env {*
this, features};
1829 auto const gw =
Account {
"gateway"};
1830 auto const alice =
Account {
"alice"};
1831 auto const bob =
Account {
"bob"};
1832 auto const USD = gw[
"USD"];
1834 env.fund (
XRP (10000), gw, alice, bob);
1836 env (
rate (gw, 1.005));
1838 env (
trust (alice, USD (1000)));
1839 env (
trust (bob, USD (1000)));
1840 env (
trust (gw, alice[
"USD"] (50)));
1842 env (
pay (gw, bob, bob[
"USD"] (1)));
1843 env (
pay (alice, gw, USD (50)));
1845 env (
trust (gw, alice[
"USD"] (0)));
1847 env (
offer (alice, USD (50),
XRP (150000)));
1848 env (
offer (bob,
XRP (100), USD (0.1)));
1851 BEAST_EXPECT(jrr[jss::node][
sfBalance.
fieldName][jss::value] ==
"49.96666666666667");
1853 BEAST_EXPECT(jrr[jss::node][
sfBalance.
fieldName][jss::value] ==
"-0.966500000033334");
1859 testcase (
"Offer tfSell: Basic Sell");
1861 using namespace jtx;
1863 Env env {*
this, features};
1865 auto const gw =
Account {
"gateway"};
1866 auto const alice =
Account {
"alice"};
1867 auto const bob =
Account {
"bob"};
1868 auto const USD = gw[
"USD"];
1870 auto const starting_xrp =
XRP (100) +
1871 env.current ()->fees ().accountReserve (1) +
1872 env.current ()->fees ().base * 2;
1874 env.fund (starting_xrp, gw, alice, bob);
1876 env (
trust (alice, USD (1000)));
1877 env (
trust (bob, USD (1000)));
1879 env (
pay (gw, bob, bob[
"USD"] (500)));
1901 testcase (
"Offer tfSell: 2x Sell Exceed Limit");
1903 using namespace jtx;
1905 Env env {*
this, features};
1907 auto const gw =
Account {
"gateway"};
1908 auto const alice =
Account {
"alice"};
1909 auto const bob =
Account {
"bob"};
1910 auto const USD = gw[
"USD"];
1912 auto const starting_xrp =
XRP (100) +
1913 env.current ()->fees ().accountReserve (1) +
1914 env.current ()->fees ().base * 2;
1916 env.fund (starting_xrp, gw, alice, bob);
1918 env (
trust (alice, USD (150)));
1919 env (
trust (bob, USD (1000)));
1921 env (
pay (gw, bob, bob[
"USD"] (500)));
1923 env (
offer (bob,
XRP (100), USD (200)));
1945 testcase (
"Client Issue #535: Gateway Cross Currency");
1947 using namespace jtx;
1949 Env env {*
this, features};
1951 auto const gw =
Account {
"gateway"};
1952 auto const alice =
Account {
"alice"};
1953 auto const bob =
Account {
"bob"};
1954 auto const XTS = gw[
"XTS"];
1955 auto const XXX = gw[
"XXX"];
1957 auto const starting_xrp =
XRP (100.1) +
1958 env.current ()->fees ().accountReserve (1) +
1959 env.current ()->fees ().base * 2;
1961 env.fund (starting_xrp, gw, alice, bob);
1963 env (
trust (alice, XTS (1000)));
1964 env (
trust (alice, XXX (1000)));
1965 env (
trust (bob, XTS (1000)));
1966 env (
trust (bob, XXX (1000)));
1968 env (
pay (gw, alice, alice[
"XTS"] (100)));
1969 env (
pay (gw, alice, alice[
"XXX"] (100)));
1970 env (
pay (gw, bob, bob[
"XTS"] (100)));
1971 env (
pay (gw, bob, bob[
"XXX"] (100)));
1973 env (
offer (alice, XTS (100), XXX (100)));
1980 payment[jss::id] = env.seq (bob);
1981 payment[jss::build_path] =
true;
1982 payment[jss::tx_json] =
pay (bob, bob, bob[
"XXX"] (1));
1983 payment[jss::tx_json][jss::Sequence] =
1984 env.current ()->read (
1986 payment[jss::tx_json][jss::Fee] =
1988 payment[jss::tx_json][jss::SendMax] =
1990 auto jrr = wsc->invoke(
"submit", payment);
1991 BEAST_EXPECT(jrr[jss::status] ==
"success");
1992 BEAST_EXPECT(jrr[jss::result][jss::engine_result] ==
"tesSUCCESS");
1993 if (wsc->version() == 2)
1995 BEAST_EXPECT(jrr.isMember(jss::jsonrpc) && jrr[jss::jsonrpc] ==
"2.0");
1996 BEAST_EXPECT(jrr.isMember(jss::ripplerpc) && jrr[jss::ripplerpc] ==
"2.0");
1997 BEAST_EXPECT(jrr.isMember(jss::id) && jrr[jss::id] == 5);
2021 auto const sleTrust =
2023 BEAST_EXPECT (sleTrust);
2027 bool const accountLow = account.id() < issue.
account;
2032 low.setIssuer (accountLow ? account.id() : issue.
account);
2033 high.setIssuer (accountLow ? issue.
account : account.id());
2035 BEAST_EXPECT (sleTrust->getFieldAmount (
sfLowLimit) == low);
2036 BEAST_EXPECT (sleTrust->getFieldAmount (
sfHighLimit) == high);
2042 BEAST_EXPECT (actualBalance == expectBalance);
2051 testcase (
"Partial Crossing");
2053 using namespace jtx;
2055 auto const gw =
Account(
"gateway");
2056 auto const USD = gw[
"USD"];
2058 Env env {*
this, features};
2060 env.fund (
XRP(10000000), gw);
2063 auto const f = env.current ()->fees ().
base;
2066 enum preTrustType {noPreTrust, gwPreTrust, acctPreTrust};
2072 preTrustType preTrust;
2081 TestData
const tests[]
2084 {
"ann",
reserve (env, 0) + 0*f, 1, noPreTrust, 1000,
tecUNFUNDED_OFFER, f, USD( 0), 0, 0},
2085 {
"bev",
reserve (env, 0) + 1*f, 1, noPreTrust, 1000,
tecUNFUNDED_OFFER, f, USD( 0), 0, 0},
2086 {
"cam",
reserve (env, 0) + 2*f, 0, noPreTrust, 1000,
tecINSUF_RESERVE_OFFER, f, USD( 0), 0, 0},
2087 {
"deb",
reserve (env, 0) + 2*f, 1, noPreTrust, 1000,
tesSUCCESS, 2*f, USD(0.00001), 0, 1},
2088 {
"eve",
reserve (env, 1) + 0*f, 0, noPreTrust, 1000,
tesSUCCESS, f, USD( 0), 1, 1},
2089 {
"flo",
reserve (env, 1) + 0*f, 1, noPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 0, 1},
2090 {
"gay",
reserve (env, 1) + 1*f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP( 50) + f, USD( 50), 0, 1},
2091 {
"hye",
XRP(1000) + 1*f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP( 800) + f, USD( 800), 0, 1},
2092 {
"ivy",
XRP( 1) +
reserve (env, 1) + 1*f, 1, noPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 0, 1},
2093 {
"joy",
XRP( 1) +
reserve (env, 2) + 1*f, 1, noPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 1, 2},
2094 {
"kim",
XRP( 900) +
reserve (env, 2) + 1*f, 999, noPreTrust, 1000,
tesSUCCESS,
XRP( 999) + f, USD( 999), 0, 1},
2095 {
"liz",
XRP( 998) +
reserve (env, 0) + 1*f, 999, noPreTrust, 1000,
tesSUCCESS,
XRP( 998) + f, USD( 998), 0, 1},
2096 {
"meg",
XRP( 998) +
reserve (env, 1) + 1*f, 999, noPreTrust, 1000,
tesSUCCESS,
XRP( 999) + f, USD( 999), 0, 1},
2097 {
"nia",
XRP( 998) +
reserve (env, 2) + 1*f, 999, noPreTrust, 1000,
tesSUCCESS,
XRP( 999) + f, USD( 999), 1, 2},
2098 {
"ova",
XRP( 999) +
reserve (env, 0) + 1*f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP( 999) + f, USD( 999), 0, 1},
2099 {
"pam",
XRP( 999) +
reserve (env, 1) + 1*f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP(1000) + f, USD( 1000), 0, 1},
2100 {
"rae",
XRP( 999) +
reserve (env, 2) + 1*f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP(1000) + f, USD( 1000), 0, 1},
2101 {
"sue",
XRP(1000) +
reserve (env, 2) + 1*f, 0, noPreTrust, 1000,
tesSUCCESS, f, USD( 0), 1, 1},
2104 {
"abe",
reserve (env, 0) + 0*f, 1, gwPreTrust, 1000,
tecUNFUNDED_OFFER, f, USD( 0), 0, 0},
2105 {
"bud",
reserve (env, 0) + 1*f, 1, gwPreTrust, 1000,
tecUNFUNDED_OFFER, f, USD( 0), 0, 0},
2106 {
"che",
reserve (env, 0) + 2*f, 0, gwPreTrust, 1000,
tecINSUF_RESERVE_OFFER, f, USD( 0), 0, 0},
2107 {
"dan",
reserve (env, 0) + 2*f, 1, gwPreTrust, 1000,
tesSUCCESS, 2*f, USD(0.00001), 0, 0},
2108 {
"eli",
XRP( 20) +
reserve (env, 0) + 1*f, 1000, gwPreTrust, 1000,
tesSUCCESS,
XRP(20) + 1*f, USD( 20), 0, 0},
2109 {
"fyn",
reserve (env, 1) + 0*f, 0, gwPreTrust, 1000,
tesSUCCESS, f, USD( 0), 1, 1},
2110 {
"gar",
reserve (env, 1) + 0*f, 1, gwPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 1, 1},
2111 {
"hal",
reserve (env, 1) + 1*f, 1, gwPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 1, 1},
2113 {
"ned",
reserve (env, 1) + 0*f, 1, acctPreTrust, 1000,
tecUNFUNDED_OFFER, 2*f, USD( 0), 0, 1},
2114 {
"ole",
reserve (env, 1) + 1*f, 1, acctPreTrust, 1000,
tecUNFUNDED_OFFER, 2*f, USD( 0), 0, 1},
2115 {
"pat",
reserve (env, 1) + 2*f, 0, acctPreTrust, 1000,
tecUNFUNDED_OFFER, 2*f, USD( 0), 0, 1},
2116 {
"quy",
reserve (env, 1) + 2*f, 1, acctPreTrust, 1000,
tecUNFUNDED_OFFER, 2*f, USD( 0), 0, 1},
2117 {
"ron",
reserve (env, 1) + 3*f, 0, acctPreTrust, 1000,
tecINSUF_RESERVE_OFFER, 2*f, USD( 0), 0, 1},
2118 {
"syd",
reserve (env, 1) + 3*f, 1, acctPreTrust, 1000,
tesSUCCESS, 3*f, USD(0.00001), 0, 1},
2119 {
"ted",
XRP( 20) +
reserve (env, 1) + 2*f, 1000, acctPreTrust, 1000,
tesSUCCESS,
XRP(20) + 2*f, USD( 20), 0, 1},
2120 {
"uli",
reserve (env, 2) + 0*f, 0, acctPreTrust, 1000,
tecINSUF_RESERVE_OFFER, 2*f, USD( 0), 0, 1},
2121 {
"vic",
reserve (env, 2) + 0*f, 1, acctPreTrust, 1000,
tesSUCCESS,
XRP( 1) + 2*f, USD( 1), 0, 1},
2122 {
"wes",
reserve (env, 2) + 1*f, 0, acctPreTrust, 1000,
tesSUCCESS, 2*f, USD( 0), 1, 2},
2123 {
"xan",
reserve (env, 2) + 1*f, 1, acctPreTrust, 1000,
tesSUCCESS,
XRP( 1) + 2*f, USD( 1), 1, 2},
2126 for (
auto const& t : tests)
2128 auto const acct =
Account(t.account);
2129 env.fund (t.fundXrp, acct);
2133 env.require (
offers (gw, 0));
2136 auto const book = t.bookAmount;
2138 env (
offer (gw,
XRP (book), USD (book)));
2143 if (t.preTrust == gwPreTrust)
2144 env (
trust (gw, acct[
"USD"] (1)));
2149 if (t.preTrust == acctPreTrust)
2150 env (
trust (acct, USD (1)));
2156 auto const acctOffer = t.offerAmount;
2157 env(
offer(acct, USD(acctOffer),
XRP(acctOffer)),
ter(t.tec));
2162 BEAST_EXPECT (env.balance (acct, USD.issue()) == t.balanceUsd);
2164 env.balance (acct,
xrpIssue()) == t.fundXrp - t.spentXrp);
2165 env.require (
offers (acct, t.offers));
2166 env.require (
owners (acct, t.owners));
2169 BEAST_EXPECT (acctOffers.size() == t.offers);
2170 if (acctOffers.size() && t.offers)
2172 auto const& acctOffer = *(acctOffers.front());
2174 auto const leftover = t.offerAmount - t.bookAmount;
2176 BEAST_EXPECT (acctOffer[
sfTakerPays] == USD (leftover));
2179 if (t.preTrust == noPreTrust)
2181 if (t.balanceUsd.value().signum())
2189 auto const sleTrust =
2191 BEAST_EXPECT (! sleTrust);
2206 testcase (
"XRP Direct Crossing");
2208 using namespace jtx;
2210 auto const gw =
Account(
"gateway");
2211 auto const alice =
Account(
"alice");
2212 auto const bob =
Account(
"bob");
2213 auto const USD = gw[
"USD"];
2215 auto const usdOffer = USD(1000);
2216 auto const xrpOffer =
XRP(1000);
2218 Env env {*
this, features};
2220 env.fund (
XRP(1000000), gw, bob);
2224 auto const fee = env.current ()->fees ().base;
2228 env.fund (
reserve (env, 2) +
fee * 2, alice);
2231 env (
trust(alice, usdOffer));
2235 env (
pay(gw, alice, usdOffer));
2245 auto const alicesXRP = env.balance (alice);
2246 auto const bobsXRP = env.balance (bob);
2248 env (
offer (alice, xrpOffer, usdOffer));
2250 env (
offer (bob, usdOffer, xrpOffer));
2264 env (
offer (alice, USD(999),
XRP(999)));
2265 env (
offer (bob, xrpOffer, usdOffer));
2268 env.require (
balance (alice, USD(999)));
2269 env.require (
balance (bob, USD(1)));
2270 env.require (
offers (alice, 0));
2274 BEAST_EXPECT (bobsOffers.size() == 1);
2275 auto const& bobsOffer = *(bobsOffers.front());
2286 testcase (
"Direct Crossing");
2288 using namespace jtx;
2290 auto const gw =
Account(
"gateway");
2291 auto const alice =
Account(
"alice");
2292 auto const bob =
Account(
"bob");
2293 auto const USD = gw[
"USD"];
2294 auto const EUR = gw[
"EUR"];
2296 auto const usdOffer = USD(1000);
2297 auto const eurOffer = EUR(1000);
2299 Env env {*
this, features};
2301 env.fund (
XRP(1000000), gw);
2305 auto const fee = env.current ()->fees ().base;
2309 env.fund (
reserve (env, 3) +
fee * 3, alice);
2313 env (
trust(alice, usdOffer));
2314 env (
trust(bob, eurOffer));
2317 env (
pay(gw, alice, usdOffer));
2318 env (
pay(gw, bob, eurOffer));
2328 env (
offer (alice, eurOffer, usdOffer));
2329 env (
offer (bob, usdOffer, eurOffer));
2346 env (
offer (bob, eurOffer, usdOffer));
2349 env (
offer (alice, USD(999), eurOffer));
2352 env.require (
offers (alice, 0));
2353 env.require (
offers (bob, 1));
2355 env.require (
balance (alice, USD(999)));
2356 env.require (
balance (alice, EUR(1)));
2357 env.require (
balance (bob, USD(1)));
2358 env.require (
balance (bob, EUR(999)));
2362 if (BEAST_EXPECT(bobsOffers.size() == 1))
2364 auto const& bobsOffer = *(bobsOffers.front());
2372 env (
offer (alice, USD(1), EUR(1)));
2375 env.require (
balance (alice, USD(1000)));
2378 env.require (
balance (bob, EUR(1000)));
2379 env.require (
offers (alice, 0));
2380 env.require (
offers (bob, 0));
2383 BEAST_EXPECT (! env.le (
keylet::line (alice.id(), EUR.issue())));
2384 BEAST_EXPECT (! env.le (
keylet::line (bob.id(), USD.issue())));
2388 env (
offer (alice, EUR(999), usdOffer));
2391 env (
offer (bob, usdOffer, eurOffer));
2394 env.require (
offers (alice, 0));
2395 env.require (
offers (bob, 0));
2397 env.require (
balance (alice, USD(0)));
2398 env.require (
balance (alice, EUR(999)));
2399 env.require (
balance (bob, USD(1000)));
2400 env.require (
balance (bob, EUR(1)));
2406 testcase (
"Bridged Crossing");
2408 using namespace jtx;
2410 auto const gw =
Account(
"gateway");
2411 auto const alice =
Account(
"alice");
2412 auto const bob =
Account(
"bob");
2413 auto const carol =
Account(
"carol");
2414 auto const USD = gw[
"USD"];
2415 auto const EUR = gw[
"EUR"];
2417 auto const usdOffer = USD(1000);
2418 auto const eurOffer = EUR(1000);
2420 Env env {*
this, features};
2422 env.fund (
XRP(1000000), gw, alice, bob, carol);
2425 env (
trust(alice, usdOffer));
2426 env (
trust(carol, eurOffer));
2428 env (
pay(gw, alice, usdOffer));
2429 env (
pay(gw, carol, eurOffer));
2438 env (
offer (alice,
XRP(1000), usdOffer));
2439 env (
offer (bob, eurOffer,
XRP(1000)));
2440 auto const bobXrpBalance = env.balance (bob);
2444 env (
offer (carol, USD(400), EUR(400)));
2457 BEAST_EXPECT (alicesOffers.size() == 1);
2458 auto const& alicesOffer = *(alicesOffers.front());
2461 BEAST_EXPECT (alicesOffer[
sfTakerGets] == USD (600));
2466 BEAST_EXPECT (bobsOffers.size() == 1);
2467 auto const& bobsOffer = *(bobsOffers.front());
2471 BEAST_EXPECT (bobsOffer[
sfTakerPays] == EUR (600));
2475 env (
offer (carol, USD(600), EUR(600)));
2490 if (alicesOffers.size() != 0)
2492 BEAST_EXPECT (alicesOffers.size() == 1);
2493 auto const& alicesOffer = *(alicesOffers.front());
2496 BEAST_EXPECT (alicesOffer[
sfTakerGets] == USD (0));
2507 testcase (
"Sell Offer");
2509 using namespace jtx;
2511 auto const gw =
Account(
"gateway");
2512 auto const USD = gw[
"USD"];
2514 Env env {*
this, features};
2516 env.fund (
XRP(10000000), gw);
2519 auto const f = env.current ()->fees ().
base;
2522 enum preTrustType {noPreTrust, gwPreTrust, acctPreTrust};
2556 : account (std::move(account_))
2557 , fundXrp (fundXrp_)
2558 , fundUSD (fundUSD_)
2561 , acctGets (acctGets_)
2562 , acctPays (acctPays_)
2564 , spentXrp (spentXrp_)
2565 , finalUsd (finalUsd_)
2568 , takerGets (takerGets_)
2569 , takerPays (takerPays_)
2586 : TestData (std::move(account_), fundXrp_, fundUSD_, gwGets_,
2587 gwPays_, acctGets_, acctPays_, tec_, spentXrp_, finalUsd_,
2592 TestData
const tests[]
2596 {
"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},
2597 {
"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)},
2598 {
"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},
2599 {
"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},
2600 {
"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},
2601 {
"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},
2602 {
"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},
2603 {
"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)},
2605 {
"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},
2606 {
"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)},
2607 {
"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},
2608 {
"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},
2609 {
"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},
2610 {
"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)},
2611 {
"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)},
2613 auto const zeroUsd = USD(0);
2614 for (
auto const& t : tests)
2617 env.require (
offers (gw, 0));
2619 auto const acct =
Account(t.account);
2621 env.fund (t.fundXrp, acct);
2627 if (t.fundUSD != zeroUsd)
2629 env (
trust (acct, t.fundUSD));
2631 env (
pay (gw, acct, t.fundUSD));
2635 env (
offer (gw, t.gwGets, t.gwPays));
2645 BEAST_EXPECT (env.balance (acct, USD.issue()) == t.finalUsd);
2647 env.balance (acct,
xrpIssue()) == t.fundXrp - t.spentXrp);
2648 env.require (
offers (acct, t.offers));
2649 env.require (
owners (acct, t.owners));
2654 if (acctOffers.size() > 0)
2656 BEAST_EXPECT (acctOffers.size() == 1);
2657 auto const& acctOffer = *(acctOffers.front());
2660 BEAST_EXPECT (acctOffer[
sfTakerGets] == t.takerGets);
2661 BEAST_EXPECT (acctOffer[
sfTakerPays] == t.takerPays);
2678 testcase (
"Combine tfSell with tfFillOrKill");
2680 using namespace jtx;
2682 auto const gw =
Account(
"gateway");
2683 auto const alice =
Account(
"alice");
2684 auto const bob =
Account(
"bob");
2685 auto const USD = gw[
"USD"];
2687 Env env {*
this, features};
2689 env.fund (
XRP(10000000), gw, alice, bob);
2692 TER const killedCode {
2696 env (
trust(bob, USD(200)));
2698 env (
pay(gw, bob, USD(100)));
2700 env (
offer(bob,
XRP(2000), USD(20)));
2704 env (
offer(alice, USD(21),
XRP(2100),
2708 env.require (
offers (alice, 0));
2709 env.require (
balance (bob, USD(100)));
2716 env.require (
balance (alice, USD(20)));
2717 env.require (
offers (alice, 0));
2718 env.require (
balance (bob, USD(80)));
2723 env (
offer(bob,
XRP(2000), USD(20)));
2727 env.require (
balance (alice, USD(35)));
2728 env.require (
offers (alice, 0));
2729 env.require (
balance (bob, USD(65)));
2738 env (
offer(alice, USD(1),
XRP(501),
2741 env.require (
balance (alice, USD(35)));
2742 env.require (
offers (alice, 0));
2743 env.require (
balance (bob, USD(65)));
2752 env.require (
balance (alice, USD(40)));
2753 env.require (
offers (alice, 0));
2754 env.require (
balance (bob, USD(60)));
2761 testcase (
"Transfer Rate Offer");
2763 using namespace jtx;
2765 auto const gw1 =
Account(
"gateway1");
2766 auto const USD = gw1[
"USD"];
2768 Env env {*
this, features};
2771 auto const fee = env.current ()->fees ().base;
2773 env.fund (
XRP(100000), gw1);
2776 env(
rate(gw1, 1.25));
2778 auto const ann =
Account(
"ann");
2779 auto const bob =
Account(
"bob");
2783 env (
trust(ann, USD(200)));
2784 env (
trust(bob, USD(200)));
2787 env (
pay (gw1, bob, USD(125)));
2796 env (
offer (bob,
XRP(1), USD(100)));
2799 env (
offer (ann, USD(100),
XRP(1)));
2802 env.require (
balance (ann, USD(100)));
2804 env.require (
offers (ann, 0));
2806 env.require (
balance (bob, USD( 0)));
2808 env.require (
offers (bob, 0));
2813 auto const che =
Account(
"che");
2814 auto const deb =
Account(
"deb");
2818 env (
trust(che, USD(200)));
2819 env (
trust(deb, USD(200)));
2822 env (
pay (gw1, deb, USD(125)));
2825 env (
offer (che, USD(100),
XRP(1)));
2828 env (
offer (deb,
XRP(1), USD(100)));
2831 env.require (
balance (che, USD(100)));
2833 env.require (
offers (che, 0));
2835 env.require (
balance (deb, USD( 0)));
2837 env.require (
offers (deb, 0));
2840 auto const eve =
Account(
"eve");
2841 auto const fyn =
Account(
"fyn");
2843 env.fund (
XRP(20000) + (
fee*2), eve, fyn);
2846 env (
trust (eve, USD(1000)));
2847 env (
trust (fyn, USD(1000)));
2850 env (
pay (gw1, eve, USD(100)));
2851 env (
pay (gw1, fyn, USD(100)));
2857 env (
offer (eve, USD(10),
XRP(4000)));
2861 env (
offer (fyn,
XRP(2000), USD(5)));
2864 env.require (
balance (eve, USD(105)));
2867 BEAST_EXPECT (evesOffers.size() == 1);
2868 if (evesOffers.size() != 0)
2870 auto const& evesOffer = *(evesOffers.front());
2877 env.require (
balance (fyn, USD(93.75)));
2879 env.require (
offers (fyn, 0));
2882 auto const gw2 =
Account(
"gateway2");
2883 auto const EUR = gw2[
"EUR"];
2885 env.fund (
XRP(100000), gw2);
2888 env(
rate(gw2, 1.5));
2893 auto const gay =
Account(
"gay");
2894 auto const hal =
Account(
"hal");
2895 env.fund (
reserve(env, 3) + (
fee*3), gay, hal);
2898 env (
trust(gay, USD(200)));
2899 env (
trust(gay, EUR(200)));
2900 env (
trust(hal, USD(200)));
2901 env (
trust(hal, EUR(200)));
2904 env (
pay (gw1, gay, USD(125)));
2905 env (
pay (gw2, hal, EUR(150)));
2908 env (
offer (gay, EUR(100), USD(100)));
2911 env (
offer (hal, USD(100), EUR(100)));
2914 env.require (
balance (gay, USD( 0)));
2915 env.require (
balance (gay, EUR(100)));
2917 env.require (
offers (gay, 0));
2919 env.require (
balance (hal, USD(100)));
2920 env.require (
balance (hal, EUR( 0)));
2922 env.require (
offers (hal, 0));
2926 auto const ivy =
Account(
"ivy");
2927 auto const joe =
Account(
"joe");
2928 env.fund (
reserve(env, 3) + (
fee*3), ivy, joe);
2937 env (
pay (gw1, ivy, USD(270)),
sendmax (USD(500)));
2938 env (
pay (gw2, joe, EUR(150)),
sendmax (EUR(300)));
2940 env.require (
balance (ivy, USD(300)));
2941 env.require (
balance (joe, EUR(250)));
2943 env (
offer (ivy, EUR(100), USD(200)));
2946 env (
offer (joe, USD(200), EUR(100)));
2949 env.require (
balance (ivy, USD( 50)));
2950 env.require (
balance (ivy, EUR(100)));
2952 env.require (
offers (ivy, 0));
2954 env.require (
balance (joe, USD(200)));
2955 env.require (
balance (joe, EUR(100)));
2957 env.require (
offers (joe, 0));
2961 auto const kim =
Account(
"kim");
2962 auto const K_BUX = kim[
"BUX"];
2963 auto const lex =
Account(
"lex");
2964 auto const meg =
Account(
"meg");
2965 auto const ned =
Account(
"ned");
2966 auto const N_BUX = ned[
"BUX"];
2969 env.fund (
reserve(env, 4) + (
fee*4), kim, lex, meg, ned);
2972 env (
trust (lex, K_BUX(400)));
2974 env (
trust (meg, N_BUX(100)));
2976 env (
pay (ned, lex, N_BUX(100)));
2978 env.require (
balance (lex, N_BUX(100)));
2981 N_BUX(60)),
path (lex, ned),
sendmax (K_BUX(200)));
2986 env.require (
balance (lex, K_BUX( 72)));
2987 env.require (
balance (lex, N_BUX( 40)));
2989 env.require (
balance (meg, N_BUX( 60)));
2994 env (
offer (lex, K_BUX(30), N_BUX(30)));
2997 env (
offer (kim, N_BUX(30), K_BUX(30)));
3001 env.require (
balance (kim, N_BUX( 30)));
3002 env.require (
balance (lex, K_BUX( 102)));
3003 env.require (
balance (lex, N_BUX( 10)));
3005 env.require (
balance (meg, N_BUX( 60)));
3006 env.require (
balance (ned, K_BUX( -30)));
3011 auto const ova =
Account(
"ova");
3012 auto const pat =
Account(
"pat");
3013 auto const qae =
Account(
"qae");
3014 env.fund (
XRP(2) +
reserve(env, 3) + (
fee*3), ova, pat, qae);
3020 env (
trust(ova, USD(200)));
3021 env (
trust(ova, EUR(200)));
3022 env (
trust(pat, USD(200)));
3023 env (
trust(pat, EUR(200)));
3024 env (
trust(qae, USD(200)));
3025 env (
trust(qae, EUR(200)));
3028 env (
pay (gw1, ova, USD(125)));
3029 env (
pay (gw2, qae, EUR(150)));
3032 env (
offer (ova,
XRP(2), USD(100)));
3033 env (
offer (pat, EUR(100),
XRP(2)));
3036 env (
offer (qae, USD(100), EUR(100)));
3039 env.require (
balance (ova, USD( 0)));
3040 env.require (
balance (ova, EUR( 0)));
3045 if (ovasOffers.size() != 0)
3047 BEAST_EXPECT (ovasOffers.size() == 1);
3048 auto const& ovasOffer = *(ovasOffers.front());
3055 env.require (
balance (pat, USD( 0)));
3056 env.require (
balance (pat, EUR(100)));
3058 env.require (
offers (pat, 0));
3060 env.require (
balance (qae, USD(100)));
3061 env.require (
balance (qae, EUR( 0)));
3063 env.require (
offers (qae, 0));
3084 using namespace jtx;
3086 auto const gw =
Account(
"gateway");
3087 auto const USD = gw[
"USD"];
3089 Env env {*
this, features};
3092 auto const fee = env.current ()->fees ().base;
3093 auto const startBalance =
XRP(1000000);
3095 env.fund (startBalance + (
fee*4), gw);
3098 env (
offer (gw, USD(60),
XRP(600)));
3100 env (
offer (gw, USD(60),
XRP(600)));
3102 env (
offer (gw, USD(60),
XRP(600)));
3105 env.require (
owners (gw, 3));
3106 env.require (
balance (gw, startBalance +
fee));
3109 BEAST_EXPECT (gwOffers.size() == 3);
3110 for (
auto const& offerPtr : gwOffers)
3112 auto const&
offer = *offerPtr;
3120 env (
offer (gw,
XRP(1000), USD(100)));
3122 env.require (
owners (gw, 1));
3123 env.require (
offers (gw, 1));
3124 env.require (
balance (gw, startBalance));
3127 BEAST_EXPECT (gwOffers.size() == 1);
3128 for (
auto const& offerPtr : gwOffers)
3130 auto const&
offer = *offerPtr;
3140 using namespace jtx;
3142 auto const gw1 =
Account(
"gateway1");
3143 auto const gw2 =
Account(
"gateway2");
3144 auto const alice =
Account(
"alice");
3145 auto const USD = gw1[
"USD"];
3146 auto const EUR = gw2[
"EUR"];
3148 Env env {*
this, features};
3150 env.fund (
XRP(1000000), gw1, gw2);
3154 auto const f = env.current ()->fees ().
base;
3167 TestData
const tests[]
3178 for (
auto const& t : tests)
3180 auto const acct =
Account {t.acct};
3181 env.fund (t.fundXRP, acct);
3184 env (
trust (acct, USD(1000)));
3185 env (
trust (acct, EUR(1000)));
3188 if (t.fundUSD > USD(0))
3189 env (
pay (gw1, acct, t.fundUSD));
3190 if (t.fundEUR > EUR(0))
3191 env (
pay (gw2, acct, t.fundEUR));
3194 env (
offer (acct, USD(500), EUR(600)),
ter (t.firstOfferTec));
3198 int offerCount = t.firstOfferTec ==
tesSUCCESS ? 1 : 0;
3199 env.require (
owners (acct, 2 + offerCount));
3200 env.require (
balance (acct, t.fundUSD));
3201 env.require (
balance (acct, t.fundEUR));
3204 BEAST_EXPECT (acctOffers.size() == offerCount);
3205 for (
auto const& offerPtr : acctOffers)
3207 auto const&
offer = *offerPtr;
3213 env (
offer (acct, EUR(600), USD(500)),
ter (t.secondOfferTec));
3217 offerCount = t.secondOfferTec ==
tesSUCCESS ? 1 : offerCount;
3218 env.require (
owners (acct, 2 + offerCount));
3219 env.require (
balance (acct, t.fundUSD));
3220 env.require (
balance (acct, t.fundEUR));
3223 BEAST_EXPECT (acctOffers.size() == offerCount);
3224 for (
auto const& offerPtr : acctOffers)
3226 auto const&
offer = *offerPtr;
3251 testcase (
"Self Cross Offer");
3263 using namespace jtx;
3265 Env env {*
this, features};
3267 auto const alice =
Account(
"alice");
3268 auto const bob =
Account(
"bob");
3269 auto const USD = bob[
"USD"];
3270 auto const f = env.current ()->fees ().base;
3272 env.fund(
XRP(50000) + f, alice, bob);
3275 env(
offer(alice, USD(5000),
XRP(50000)));
3279 env(
offer(bob,
XRP(50000), USD(5000)));
3285 env.require (
owners (alice, 1));
3286 env.require (
lines (alice, 1));
3291 BEAST_EXPECT(bobOffers.size() == 1);
3292 for (
auto const& offerPtr : bobOffers)
3294 auto const&
offer = *offerPtr;
3307 testcase (
"Bad path assert");
3309 using namespace jtx;
3316 auto const fee = env.current ()->fees ().base;
3319 auto const ann =
Account(
"ann");
3320 auto const A_BUX = ann[
"BUX"];
3321 auto const bob =
Account(
"bob");
3322 auto const cam =
Account(
"cam");
3323 auto const dan =
Account(
"dan");
3324 auto const D_BUX = dan[
"BUX"];
3327 env.fund (
reserve(env, 4) + (
fee*4), ann, bob, cam, dan);
3330 env (
trust (bob, A_BUX(400)));
3332 env (
trust (cam, D_BUX(100)));
3334 env (
pay (dan, bob, D_BUX(100)));
3336 env.require (
balance (bob, D_BUX(100)));
3338 env (
pay (ann, cam, D_BUX(60)),
3344 env.require (
balance (bob, A_BUX( 72)));
3345 env.require (
balance (bob, D_BUX( 40)));
3347 env.require (
balance (cam, D_BUX( 60)));
3351 env (
offer (bob, A_BUX(30), D_BUX(30)));
3354 env (
trust (ann, D_BUX(100)));
3358 env (
pay (ann, ann, D_BUX(30)),
3363 env.require (
balance (ann, D_BUX( 0)));
3364 env.require (
balance (bob, A_BUX( 72)));
3365 env.require (
balance (bob, D_BUX( 40)));
3367 env.require (
balance (cam, D_BUX( 60)));
3368 env.require (
balance (dan, A_BUX( 0)));
3379 testcase (
"Direct to Direct path");
3381 using namespace jtx;
3383 Env env {*
this, features};
3385 auto const ann =
Account(
"ann");
3386 auto const bob =
Account(
"bob");
3387 auto const cam =
Account(
"cam");
3388 auto const A_BUX = ann[
"BUX"];
3389 auto const B_BUX = bob[
"BUX"];
3391 auto const fee = env.current ()->fees ().base;
3392 env.fund (
reserve(env, 4) + (
fee*5), ann, bob, cam);
3395 env (
trust (ann, B_BUX(40)));
3396 env (
trust (cam, A_BUX(40)));
3397 env (
trust (cam, B_BUX(40)));
3400 env (
pay (ann, cam, A_BUX(35)));
3401 env (
pay (bob, cam, B_BUX(35)));
3403 env (
offer (bob, A_BUX(30), B_BUX(30)));
3411 env.require (
balance (cam, A_BUX(35)));
3412 env.require (
balance (cam, B_BUX(35)));
3413 env.require (
offers (cam, 1));
3416 env (
offer (cam, B_BUX(30), A_BUX(30)));
3419 env.require (
balance (bob, A_BUX(30)));
3420 env.require (
balance (cam, A_BUX( 5)));
3421 env.require (
balance (cam, B_BUX(65)));
3422 env.require (
offers (cam, 0));
3430 testcase (
"Self crossing low quality offer");
3432 using namespace jtx;
3434 Env env {*
this, features};
3436 auto const ann =
Account(
"ann");
3437 auto const gw =
Account(
"gateway");
3438 auto const BTC = gw[
"BTC"];
3440 auto const fee = env.current ()->fees ().base;
3445 env (
rate(gw, 1.002));
3446 env (
trust(ann, BTC(10)));
3449 env (
pay(gw, ann, BTC(2.856)));
3452 env (
offer(ann,
drops(365611702030), BTC(5.713)));
3466 testcase (
"Offer In Scaling");
3468 using namespace jtx;
3470 Env env {*
this, features};
3472 auto const gw =
Account(
"gateway");
3473 auto const alice =
Account(
"alice");
3474 auto const bob =
Account(
"bob");
3475 auto const CNY = gw[
"CNY"];
3477 auto const fee = env.current ()->fees ().base;
3478 env.fund (
reserve(env, 2) +
drops (400000000000) + (
fee), alice, bob);
3482 env (
trust(bob, CNY(500)));
3485 env (
pay(gw, bob, CNY(300)));
3488 env (
offer(bob,
drops(5400000000), CNY(216.054)));
3492 env (
offer(alice, CNY(13562.0001),
drops(339000000000)));
3496 BEAST_EXPECT(aliceOffers.size() == 1);
3497 for (
auto const& offerPtr : aliceOffers)
3499 auto const&
offer = *offerPtr;
3511 testcase (
"Offer In Scaling With Xfer Rate");
3513 using namespace jtx;
3515 Env env {*
this, features};
3517 auto const gw =
Account(
"gateway");
3518 auto const alice =
Account(
"alice");
3519 auto const bob =
Account(
"bob");
3520 auto const BTC = gw[
"BTC"];
3521 auto const JPY = gw[
"JPY"];
3523 auto const fee = env.current ()->fees ().base;
3524 env.fund (
reserve(env, 2) +
drops (400000000000) + (
fee), alice, bob);
3528 env (
rate(gw, 1.002));
3529 env (
trust(alice, JPY(4000)));
3530 env (
trust(bob, BTC(2)));
3533 env (
pay(gw, alice, JPY(3699.034802280317)));
3534 env (
pay(gw, bob, BTC(1.156722559140311)));
3537 env (
offer(bob, JPY(1241.913390770747), BTC(0.01969825690469254)));
3541 env (
offer(alice, BTC(0.05507568706427876), JPY(3472.696773391072)));
3545 BEAST_EXPECT(aliceOffers.size() == 1);
3546 for (
auto const& offerPtr : aliceOffers)
3548 auto const&
offer = *offerPtr;
3561 testcase (
"Offer Threshold With Reduced Funds");
3563 using namespace jtx;
3565 Env env {*
this, features};
3567 auto const gw1 =
Account(
"gw1");
3568 auto const gw2 =
Account(
"gw2");
3569 auto const alice =
Account(
"alice");
3570 auto const bob =
Account(
"bob");
3571 auto const USD = gw1[
"USD"];
3572 auto const JPY = gw2[
"JPY"];
3574 auto const fee = env.current ()->fees ().base;
3575 env.fund (
reserve(env, 2) +
drops (400000000000) + (
fee), alice, bob);
3576 env.fund (
reserve(env, 2) + (
fee*4), gw1, gw2);
3579 env (
rate(gw1, 1.002));
3580 env (
trust(alice, USD(1000)));
3581 env (
trust(bob, JPY(100000)));
3584 env (
pay(gw1, alice,
3602 BEAST_EXPECT(aliceOffers.size() == 1);
3603 for (
auto const& offerPtr : aliceOffers)
3605 auto const&
offer = *offerPtr;
3616 testcase (
"Tiny Offer");
3618 using namespace jtx;
3620 Env env {*
this, features};
3622 auto const gw =
Account(
"gw");
3623 auto const alice =
Account(
"alice");
3624 auto const bob =
Account(
"bob");
3625 auto const CNY = gw[
"CNY"];
3626 auto const fee = env.current()->fees().base;
3627 auto const startXrpBalance =
drops (400000000000) + (
fee * 2);
3629 env.fund (startXrpBalance, gw, alice, bob);
3632 env (
trust (bob, CNY(100000)));
3644 STAmount const bobsCnyStartBalance {
3646 env (
pay(gw, bob, bobsCnyStartBalance));
3653 env.require (
balance (alice, alicesCnyOffer));
3655 env.require (
balance (bob, bobsCnyStartBalance - alicesCnyOffer));
3661 testcase (
"Self Pay Xfer Fee");
3697 using namespace jtx;
3699 Env env {*
this, features};
3701 auto const gw =
Account(
"gw");
3702 auto const BTC = gw[
"BTC"];
3703 auto const USD = gw[
"USD"];
3704 auto const startXrpBalance =
XRP (4000000);
3706 env.fund (startXrpBalance, gw);
3709 env (
rate (gw, 1.25));
3734 TestData
const tests[]
3737 { 0, 0, 1, BTC(20), { {
"ann", 0,
drops(3899999999960), BTC(20.0), USD(3000)}, {
"abe", 0,
drops(4099999999970), BTC( 0), USD(750)} } },
3738 { 0, 1, 0, BTC(20), { {
"bev", 0,
drops(4099999999960), BTC( 7.5), USD(2000)}, {
"bob", 0,
drops(3899999999970), BTC(10), USD( 0)} } },
3739 { 0, 0, 0, BTC(20), { {
"cam", 0,
drops(3999999999950), BTC(20.0), USD(2000)} } },
3741 { 0, 1, 0, BTC( 5), { {
"eve", 1,
drops(4039999999960), BTC( 0.0), USD(2000)}, {
"eli", 1,
drops(3959999999970), BTC( 4), USD( 0)} } },
3745 for (
auto const& t : tests)
3747 Account const&
self = t.actors[t.self].acct;
3748 Account const& leg0 = t.actors[t.leg0].acct;
3749 Account const& leg1 = t.actors[t.leg1].acct;
3751 for (
auto const& actor : t.actors)
3753 env.fund (
XRP (4000000), actor.acct);
3756 env (
trust (actor.acct, BTC(40)));
3757 env (
trust (actor.acct, USD(8000)));
3761 env (
pay (gw,
self, t.btcStart));
3762 env (
pay (gw,
self, USD(2000)));
3763 if (
self.
id() != leg1.
id())
3764 env (
pay (gw, leg1, USD(2000)));
3778 env (
offer (
self, USD(1000), BTC(10)));
3783 for (
auto const& actor : t.actors)
3792 return (*offer)[sfTakerGets].signum() == 0;
3794 BEAST_EXPECT (offerCount == actor.offers);
3796 env.require (
balance (actor.acct, actor.xrp));
3797 env.require (
balance (actor.acct, actor.btc));
3798 env.require (
balance (actor.acct, actor.usd));
3813 testcase (
"Self Pay Unlimited Funds");
3845 using namespace jtx;
3847 Env env {*
this, features};
3849 auto const gw =
Account(
"gw");
3850 auto const BTC = gw[
"BTC"];
3851 auto const USD = gw[
"USD"];
3852 auto const startXrpBalance =
XRP (4000000);
3854 env.fund (startXrpBalance, gw);
3857 env (
rate (gw, 1.25));
3882 TestData
const takerTests[]
3885 { 0, 0, 1, BTC( 5), { {
"deb", 0,
drops(3899999999960), BTC(5), USD(3000)}, {
"dan", 0,
drops(4099999999970), BTC(0), USD( 750)} } },
3886 { 0, 0, 0, BTC( 5), { {
"flo", 0,
drops(3999999999950), BTC(5), USD(2000)} } }
3889 TestData
const flowTests[]
3892 { 0, 0, 1, BTC( 5), { {
"gay", 1,
drops(3949999999960), BTC(5), USD(2500)}, {
"gar", 1,
drops(4049999999970), BTC(0), USD(1375)} } },
3893 { 0, 0, 0, BTC( 5), { {
"hye", 2,
drops(3999999999950), BTC(5), USD(2000)} } }
3899 for (
auto const& t : tests)
3901 Account const&
self = t.actors[t.self].acct;
3902 Account const& leg0 = t.actors[t.leg0].acct;
3903 Account const& leg1 = t.actors[t.leg1].acct;
3905 for (
auto const& actor : t.actors)
3907 env.fund (
XRP (4000000), actor.acct);
3910 env (
trust (actor.acct, BTC(40)));
3911 env (
trust (actor.acct, USD(8000)));
3915 env (
pay (gw,
self, t.btcStart));
3916 env (
pay (gw,
self, USD(2000)));
3917 if (
self.
id() != leg1.
id())
3918 env (
pay (gw, leg1, USD(2000)));
3932 env (
offer (
self, USD(1000), BTC(10)));
3937 for (
auto const& actor : t.actors)
3946 return (*offer)[sfTakerGets].signum() == 0;
3948 BEAST_EXPECT (offerCount == actor.offers);
3950 env.require (
balance (actor.acct, actor.xrp));
3951 env.require (
balance (actor.acct, actor.btc));
3952 env.require (
balance (actor.acct, actor.usd));
3967 testcase (
"lsfRequireAuth");
3969 using namespace jtx;
3971 Env env {*
this, features};
3973 auto const gw =
Account(
"gw");
3974 auto const alice =
Account(
"alice");
3975 auto const bob =
Account(
"bob");
3976 auto const gwUSD = gw[
"USD"];
3977 auto const aliceUSD = alice[
"USD"];
3978 auto const bobUSD = bob[
"USD"];
3980 env.fund (
XRP(400000), gw, alice, bob);
3989 env (
trust (bob, gwUSD(100)));
3991 env (
trust (alice, gwUSD(100)));
3993 env (
offer (alice, gwUSD(40),
XRP(4000)));
3996 env.require (
offers (alice, 1));
3997 env.require (
balance (alice, gwUSD(0)));
3999 env (
pay(gw, bob, gwUSD(50)));
4002 env.require (
balance (bob, gwUSD(50)));
4005 env (
offer (bob,
XRP(4000), gwUSD(40)));
4008 env.require (
offers (alice, 0));
4009 env.require (
balance (alice, gwUSD(40)));
4011 env.require (
offers (bob, 0));
4012 env.require (
balance (bob, gwUSD(10)));
4017 testcase (
"Missing Auth");
4037 using namespace jtx;
4039 Env env {*
this, features};
4041 auto const gw =
Account(
"gw");
4042 auto const alice =
Account(
"alice");
4043 auto const bob =
Account(
"bob");
4044 auto const gwUSD = gw[
"USD"];
4045 auto const aliceUSD = alice[
"USD"];
4046 auto const bobUSD = bob[
"USD"];
4048 env.fund (
XRP(400000), gw, alice, bob);
4051 env (
offer (alice, gwUSD(40),
XRP(4000)));
4054 env.require (
offers (alice, 1));
4061 env (
trust (bob, gwUSD(100)));
4064 env (
pay(gw, bob, gwUSD(50)));
4066 env.require (
balance (bob, gwUSD(50)));
4074 env (
offer (bob,
XRP(4000), gwUSD(40)));
4080 env.require (
offers (alice, 0));
4085 env.require (
offers (bob, 1));
4086 env.require (
balance (bob, gwUSD(50)));
4091 env.require (
balance (alice, gwUSD(40)));
4092 env.require (
offers (bob, 0));
4093 env.require (
balance (bob, gwUSD(10)));
4105 env.require (
offers (alice, 0));
4108 env.require (
offers (bob, 1));
4109 env.require (
balance (bob, gwUSD(50)));
4113 env (
trust (gw, aliceUSD(100)));
4119 env.require (
offers (alice, 0));
4120 env.require (
balance (alice, gwUSD(0)));
4122 env.require (
offers (bob, 1));
4123 env.require (
balance (bob, gwUSD(50)));
4128 env.require (
offers (bob, 0));
4136 env (
offer (alice, gwUSD(40),
XRP(4000)));
4139 env.require (
offers (alice, 1));
4142 env (
offer (bob,
XRP(4000), gwUSD(40)));
4145 env.require (
offers (alice, 0));
4146 env.require (
balance (alice, gwUSD(40)));
4148 env.require (
offers (bob, 0));
4149 env.require (
balance (bob, gwUSD(10)));
4154 testcase(
"RippleConnect Smoketest payment flow");
4155 using namespace jtx;
4157 Env env {*
this, features};
4167 auto const hotUS =
Account(
"hotUS");
4168 auto const coldUS =
Account(
"coldUS");
4169 auto const hotEU =
Account(
"hotEU");
4170 auto const coldEU =
Account(
"coldEU");
4171 auto const mm =
Account(
"mm");
4173 auto const USD = coldUS[
"USD"];
4174 auto const EUR = coldEU[
"EUR"];
4176 env.fund (
XRP(100000), hotUS, coldUS, hotEU, coldEU, mm);
4180 for (
auto const& cold : {coldUS, coldEU})
4203 env (
pay(coldUS, hotUS, USD(5000000)));
4204 env (
pay(coldEU, hotEU, EUR(5000000)));
4205 env (
pay(coldUS, mm, USD(5000000)));
4206 env (
pay(coldEU, mm, EUR(5000000)));
4210 float const rate = 0.9f;
4211 env (
offer(mm, EUR(4000000 *
rate), USD(4000000)),
4214 float const reverseRate = 1.0f/
rate * 1.00101f;
4215 env (
offer(mm, USD(4000000 * reverseRate), EUR(4000000)),
4222 jvParams[jss::destination_account] = coldEU.human();
4223 jvParams[jss::destination_amount][jss::issuer] = coldEU.human();
4224 jvParams[jss::destination_amount][jss::currency] =
"EUR";
4225 jvParams[jss::destination_amount][jss::value] = 10;
4226 jvParams[jss::source_account] = hotUS.human();
4229 "json",
"ripple_path_find",
to_string(jvParams))[jss::result]};
4231 BEAST_EXPECT(jrr[jss::status] ==
"success");
4233 jrr[jss::alternatives].isArray() &&
4234 jrr[jss::alternatives].size() > 0);
4237 env (
pay (hotUS, coldEU, EUR(10)),
sendmax (USD(11.1223326)));
4242 testcase (
"Self Auth");
4244 using namespace jtx;
4246 Env env {*
this, features};
4248 auto const gw =
Account(
"gw");
4249 auto const alice =
Account(
"alice");
4250 auto const gwUSD = gw[
"USD"];
4251 auto const aliceUSD = alice[
"USD"];
4253 env.fund (
XRP(400000), gw, alice);
4257 env (
offer (gw, gwUSD(40),
XRP(4000)));
4260 env.require (
offers (gw, 1));
4269 env.require (
offers (gw, 0));
4281 env (
offer (gw, gwUSD(40),
XRP(4000)),
4285 env.require (
offers (gw, preauth ? 1 : 0));
4293 env (
trust (alice, gwUSD(100)));
4296 env (
pay(gw, alice, gwUSD(50)));
4299 env.require (
balance (alice, gwUSD(50)));
4302 env (
offer (alice,
XRP(4000), gwUSD(40)));
4305 env.require (
offers (alice, 0));
4306 env.require (
balance (alice, gwUSD(10)));
4308 env.require (
offers (gw, 0));
4314 using namespace jtx;
4316 testcase(
"Deleted offer issuer");
4318 auto trustLineExists = [](
jtx::Env const& env,
4329 auto const USD = gw[
"USD"];
4330 auto const BUX = alice[
"BUX"];
4332 Env env{*
this, features};
4335 env.
trust (USD(1000), becky);
4336 env (
pay (gw, becky, USD(5)));
4338 BEAST_EXPECT(trustLineExists(env, gw, becky, USD.currency));
4349 env(
pay(becky, gw, USD(5)));
4350 env.
trust(USD(0), becky);
4352 BEAST_EXPECT(!trustLineExists(env, gw, becky, USD.currency));
4353 BEAST_EXPECT(
isOffer(env, becky,
XRP(2), USD(2)));
4354 BEAST_EXPECT(
isOffer(env, becky, BUX(3), USD(3)));
4361 [&env, &gw, openLedgerSeq = env.
current()->seq()]() ->
int
4364 if (gwSeq + 255 > openLedgerSeq)
4365 return gwSeq - openLedgerSeq + 255;
4369 for (
int i = 0; i < delta; ++i)
4386 BEAST_EXPECT(
isOffer(env, becky,
XRP(2), USD(2)));
4387 BEAST_EXPECT(
isOffer(env, becky, BUX(3), USD(3)));
4393 BEAST_EXPECT(
isOffer(env, becky,
XRP(2), USD(2)));
4394 BEAST_EXPECT(
isOffer(env, becky, BUX(3), USD(3)));
4399 BEAST_EXPECT(!
isOffer(env, becky, BUX(3), USD(3)));
4403 env.
trust (BUX(1000), carol);
4404 env (
pay (alice, carol, BUX(2)));
4406 env (
offer (alice, BUX(2),
XRP(2)));
4413 BEAST_EXPECT(
isOffer(env, alice, BUX(2),
XRP(2)));
4414 BEAST_EXPECT(
isOffer(env, becky,
XRP(2), USD(2)));
4419 testcase (
"Tick Size");
4421 using namespace jtx;
4425 Env env {*
this, features};
4426 auto const gw =
Account {
"gateway"};
4427 env.fund (
XRP(10000), gw);
4429 auto txn =
noop(gw);
4436 == Quality::minTickSize);
4441 BEAST_EXPECT (! env.le(gw)->isFieldPresent (
sfTickSize));
4447 == Quality::maxTickSize - 1);
4455 BEAST_EXPECT (! env.le(gw)->isFieldPresent (
sfTickSize));
4458 Env env {*
this, features};
4459 auto const gw =
Account {
"gateway"};
4460 auto const alice =
Account {
"alice"};
4461 auto const XTS = gw[
"XTS"];
4462 auto const XXX = gw[
"XXX"];
4464 env.fund (
XRP (10000), gw, alice);
4468 auto txn =
noop(gw);
4471 BEAST_EXPECT ((*env.le(gw))[
sfTickSize] == 5);
4474 env (
trust (alice, XTS (1000)));
4475 env (
trust (alice, XXX (1000)));
4477 env (
pay (gw, alice, alice[
"XTS"] (100)));
4478 env (
pay (gw, alice, alice[
"XXX"] (100)));
4480 env (
offer (alice, XTS (10), XXX (30)));
4481 env (
offer (alice, XTS (30), XXX (10)));
4482 env (
offer (alice, XTS (10), XXX (30)),
4484 env (
offer (alice, XTS (30), XXX (10)),
4491 if (sle->getType() == ltOFFER)
4492 offers.emplace((*sle)[sfSequence],
4493 std::make_pair((*sle)[sfTakerPays],
4494 (*sle)[sfTakerGets]));
4498 auto it =
offers.begin();
4499 BEAST_EXPECT (it !=
offers.end());
4500 BEAST_EXPECT (it->second.first == XTS(10) &&
4501 it->second.second < XXX(30) &&
4502 it->second.second > XXX(29.9994));
4506 BEAST_EXPECT (it !=
offers.end());
4507 BEAST_EXPECT (it->second.first == XTS(30) &&
4508 it->second.second == XXX(10));
4512 BEAST_EXPECT (it !=
offers.end());
4513 BEAST_EXPECT (it->second.first == XTS(10.0002) &&
4514 it->second.second == XXX(30));
4519 BEAST_EXPECT (it !=
offers.end());
4520 BEAST_EXPECT (it->second.first == XTS(30) &&
4521 it->second.second == XXX(10));
4523 BEAST_EXPECT (++it ==
offers.end());
4530 testcase (
"false assert");
4531 using namespace jtx;
4534 auto const alice =
Account (
"alice");
4535 auto const USD = alice[
"USD"];
4537 env.fund (
XRP(10000), alice);
4539 env (
offer (alice,
XRP(100000000000), USD(100000000)));
4603 using namespace jtx;
4609 testAll(all - flowCross - takerDryOffer);
4620 using namespace jtx;
4626 testAll(all - flowCross - f1513);
4631 testAll(all - flowCross - takerDryOffer);