123 auto const gw =
Account(
"gateway");
130 auto test = [&](
auto&& issue1,
auto&& issue2) {
131 Env env(*
this, features);
133 env.
fund(
XRP(10'000), alice, bob, carol, gw);
136 auto const usd = issue1(
137 {.env = env, .token =
"USD", .issuer = gw, .holders = {alice, bob, carol}});
138 auto const btc = issue2(
139 {.env = env, .token =
"BTC", .issuer = gw, .holders = {alice, bob, carol}});
141 env(
pay(gw, alice, btc(50)));
142 env(
pay(gw, bob, usd(50)));
144 env(
offer(bob, btc(50), usd(50)));
152 BEAST_EXPECT(!
isOffer(env, bob, btc(50), usd(50)));
158 auto test = [&](
auto&& issue1,
auto&& issue2) {
159 Env env(*
this, features);
161 env.
fund(
XRP(10'000), alice, bob, carol, gw);
164 auto const usd = issue1(
165 {.env = env, .token =
"USD", .issuer = gw, .holders = {alice, bob, carol}});
166 auto const btc = issue2(
167 {.env = env, .token =
"BTC", .issuer = gw, .holders = {alice, bob, carol}});
169 env(
pay(gw, alice, btc(50)));
170 env(
pay(gw, bob, usd(50)));
181 BEAST_EXPECT(!
isOffer(env, bob,
XRP(50), usd(50)));
182 BEAST_EXPECT(!
isOffer(env, bob, btc(50),
XRP(50)));
188 Env env(*
this, features);
190 env.
fund(
XRP(10'000), alice, bob, carol, gw);
193 MPT const usd =
MPTTester({.env = env, .issuer = gw, .holders = {alice, bob, carol}});
194 MPT const btc =
MPTTester({.env = env, .issuer = gw, .holders = {alice, bob, carol}});
196 env(
pay(gw, bob, usd(50)));
208 BEAST_EXPECT(!
isOffer(env, bob,
XRP(50), usd(50)));
212 Env env(*
this, features);
214 env.
fund(
XRP(10'000), alice, bob, carol, gw);
217 MPT const usd =
MPTTester({.env = env, .issuer = gw, .holders = {alice, bob, carol}});
218 MPT const btc =
MPTTester({.env = env, .issuer = gw, .holders = {alice, bob, carol}});
220 env(
pay(gw, alice, usd(50)));
230 BEAST_EXPECT(!
isOffer(env, bob, usd(50),
XRP(50)));
234 auto test = [&](
auto&& issue1,
auto&& issue2,
auto&& issue3) {
235 Env env(*
this, features);
237 env.
fund(
XRP(10'000), alice, bob, carol, gw);
240 auto const usd = issue1(
241 {.env = env, .token =
"USD", .issuer = gw, .holders = {alice, bob, carol}});
242 auto const btc = issue2(
243 {.env = env, .token =
"BTC", .issuer = gw, .holders = {alice, bob, carol}});
244 auto const eur = issue3(
245 {.env = env, .token =
"EUR", .issuer = gw, .holders = {alice, bob, carol}});
247 env(
pay(gw, alice, btc(60)));
248 env(
pay(gw, bob, usd(50)));
249 env(
pay(gw, bob, eur(50)));
251 env(
offer(bob, btc(50), usd(50)));
252 env(
offer(bob, btc(40), eur(50)));
253 env(
offer(bob, eur(50), usd(50)));
256 env(
pay(bob, gw, eur(50)));
258 BEAST_EXPECT(
isOffer(env, bob, btc(50), usd(50)));
259 BEAST_EXPECT(
isOffer(env, bob, btc(40), eur(50)));
260 BEAST_EXPECT(
isOffer(env, bob, eur(50), usd(50)));
270 BEAST_EXPECT(!
isOffer(env, bob, btc(50), usd(50)));
272 BEAST_EXPECT(!
isOffer(env, bob, btc(40), eur(50)));
274 BEAST_EXPECT(
isOffer(env, bob, eur(50), usd(50)));
287 auto test = [&](
auto&& issue1,
auto&& issue2,
auto&& issue3) {
288 Env env(*
this, features);
290 env.
fund(
XRP(10'000), alice, bob, carol, gw);
293 auto const usd = issue1(
297 .holders = {alice, bob, carol},
299 auto const btc = issue2(
303 .holders = {alice, bob, carol},
305 auto const eur = issue3(
309 .holders = {alice, bob, carol},
312 env(
pay(gw, alice, btc(60)));
313 env(
pay(gw, bob, usd(6'000)));
314 env(
pay(gw, bob, eur(5'000)));
315 env(
pay(gw, carol, eur(100)));
317 env(
offer(bob, btc(50), usd(5'000)));
318 env(
offer(bob, btc(60), eur(5'000)));
319 env(
offer(carol, btc(1'000), eur(100)));
320 env(
offer(bob, eur(5'000), usd(5'000)));
323 env(
pay(bob, gw, eur(5'000)));
324 BEAST_EXPECT(
isOffer(env, bob, btc(50), usd(5'000)));
325 BEAST_EXPECT(
isOffer(env, bob, btc(60), eur(5'000)));
326 BEAST_EXPECT(
isOffer(env, carol, btc(1'000), eur(100)));
329 auto const flowResult = [&] {
366 BEAST_EXPECT(flowResult.removableOffers.size() == 1);
368 if (flowResult.removableOffers.empty())
371 for (
auto const& o : flowResult.removableOffers)
382 BEAST_EXPECT(
isOffer(env, bob, btc(50), usd(5'000)));
383 BEAST_EXPECT(
isOffer(env, carol, btc(1'000), eur(100)));
385 BEAST_EXPECT(!
isOffer(env, bob, btc(60), eur(5'000)));
398 auto test = [&](
auto&& issue1,
auto&& issue2) {
399 Env env(*
this, features);
400 env.
fund(
XRP(10'000), alice, bob, carol, gw);
402 auto const usd = issue1(
403 {.env = env, .token =
"USD", .issuer = gw, .holders = {alice, bob, carol}});
404 auto const eur = issue1(
405 {.env = env, .token =
"EUR", .issuer = gw, .holders = {alice, bob, carol}});
407 env(
pay(gw, alice, usd(1'000)));
408 env(
pay(gw, bob, eur(1'000)));
414 bool const reducedOffersV2 = features[fixReducedOffersV2];
422 env(
pay(alice, carol, eur(1)),
425 Txflags(tfNoRippleDirect | tfPartialPayment),
428 if (!reducedOffersV2)
436 if (BEAST_EXPECT(usdOffer))
443 bookDirStr.
erase(0, 48);
447 getRate(usdOffer->at(sfTakerGets), usdOffer->at(sfTakerPays));
454 BEAST_EXPECT(actualRate > bookRate);
1280 testcase(
"Max Flow/Self Payment Edge Cases");
1281 using namespace jtx;
1291 env.
fund(
XRP(1'000), gw, alice, carol);
1294 MPTTester({.env = env, .issuer = gw, .holders = {alice, carol}, .maxAmt = 100});
1296 env(
pay(gw, alice, usd(100)));
1298 env(
pay(alice, carol, usd(100)));
1300 BEAST_EXPECT(env.
balance(gw, usd) == usd(-100));
1301 BEAST_EXPECT(env.
balance(carol, usd) == usd(100));
1302 BEAST_EXPECT(env.
balance(alice, usd) == usd(0));
1310 env.
fund(
XRP(1'000), gw, alice, carol);
1313 MPTTester({.env = env, .issuer = gw, .holders = {alice, carol}, .maxAmt = 100});
1315 env(
pay(gw, alice, usd(80)));
1317 env(
pay(alice, carol, usd(100)),
Txflags(tfPartialPayment));
1319 BEAST_EXPECT(env.
balance(gw, usd) == usd(-80));
1320 BEAST_EXPECT(env.
balance(alice, usd) == usd(0));
1321 BEAST_EXPECT(env.
balance(carol, usd) == usd(80));
1330 env.
fund(
XRP(1'000), gw, alice, carol, bob);
1333 {.env = env, .issuer = gw, .holders = {alice, carol, bob}, .maxAmt = 100});
1335 env(
pay(gw, bob, usd(20)));
1336 env(
pay(gw, alice, usd(80)));
1338 env(
pay(alice, carol, usd(100)),
Txflags(tfPartialPayment));
1340 BEAST_EXPECT(env.
balance(gw, usd) == usd(-100));
1341 BEAST_EXPECT(env.
balance(alice, usd) == usd(0));
1342 BEAST_EXPECT(env.
balance(carol, usd) == usd(80));
1351 env.
fund(
XRP(1'000), gw, alice, carol, bob);
1354 MPTTester({.env = env, .issuer = gw, .holders = {alice, carol}, .maxAmt = 100});
1356 env(
pay(gw, alice, usd(100)));
1358 env(
offer(alice,
XRP(100), usd(100)));
1362 BEAST_EXPECT(env.
balance(gw, usd) == usd(-100));
1363 BEAST_EXPECT(env.
balance(alice, usd) == usd(0));
1364 BEAST_EXPECT(env.
balance(carol, usd) == usd(100));
1374 env.
fund(
XRP(1'000), gw, alice, carol);
1377 MPTTester({.env = env, .issuer = gw, .holders = {carol}, .maxAmt = 100});
1379 env(
pay(gw, carol, usd(100)));
1381 env(
offer(gw,
XRP(100), usd(100)));
1383 env(
pay(alice, carol, usd(100)),
1389 BEAST_EXPECT(env.
balance(gw, usd) == usd(-100));
1390 BEAST_EXPECT(env.
balance(carol, usd) == usd(100));
1399 env.
fund(
XRP(1'000), gw, alice, carol);
1402 MPTTester({.env = env, .issuer = gw, .holders = {carol}, .maxAmt = 100});
1404 env(
pay(gw, carol, usd(80)));
1406 env(
offer(gw,
XRP(100), usd(100)));
1408 env(
pay(alice, carol, usd(100)),
1413 BEAST_EXPECT(env.
balance(gw, usd) == usd(-100));
1414 BEAST_EXPECT(env.
balance(carol, usd) == usd(100));
1423 env.
fund(
XRP(1'000), gw, alice);
1426 MPTTester({.env = env, .issuer = gw, .holders = {alice}, .maxAmt = 100});
1428 env(
pay(gw, alice, usd(100)));
1430 env(
offer(alice, usd(100),
XRP(100)));
1434 BEAST_EXPECT(env.
balance(gw, usd) == usd(-100));
1435 BEAST_EXPECT(env.
balance(alice, usd) == usd(100));
1444 auto test = [&](
auto&& issue1,
auto&& issue2) {
1447 env.
fund(
XRP(1'000), gw, alice, carol);
1450 auto const usd = issue1(
1454 .holders = {alice, carol},
1457 auto const eur = issue2(
1461 .holders = {alice, carol},
1464 env(
pay(gw, alice, usd(100)));
1466 env(
offer(alice, eur(100), usd(100)));
1471 BEAST_EXPECT(env.
balance(gw, usd) == usd(-100));
1472 BEAST_EXPECT(env.
balance(alice, usd) == usd(0));
1473 BEAST_EXPECT(env.
balance(alice, eur) == eur(100));
1474 BEAST_EXPECT(env.
balance(carol, usd) == usd(100));
1484 env.
fund(
XRP(1'000), gw, alice, carol);
1487 MPTTester({.env = env, .issuer = gw, .holders = {carol}, .maxAmt = 120});
1489 env(
pay(gw, carol, usd(100)));
1491 env(
offer(carol,
XRP(100), usd(100)));
1493 env(
pay(alice, carol, usd(100)),
1498 BEAST_EXPECT(env.
balance(carol, usd) == usd(100));
1507 env.
fund(
XRP(1'000), gw, alice, carol);
1510 MPTTester({.env = env, .issuer = gw, .holders = {carol}, .maxAmt = 100});
1512 env(
pay(gw, carol, usd(100)));
1514 env(
offer(carol,
XRP(100), usd(100)));
1516 env(
pay(alice, carol, usd(100)),
1521 BEAST_EXPECT(env.
balance(carol, usd) == usd(100));
1527 auto test = [&](
auto&& issue1,
auto&& issue2) {
1530 env.
fund(
XRP(1'000), gw, alice, carol, bob);
1533 auto const usd = issue1(
1537 .holders = {alice, carol, bob},
1540 auto const eur = issue2(
1544 .holders = {alice, carol, bob},
1548 env(
pay(gw, alice, usd(600)));
1549 env(
pay(gw, carol, eur(700)));
1551 env(
offer(alice, eur(100), usd(105)));
1552 env(
offer(gw, eur(100), usd(104)));
1553 env(
offer(gw, eur(100), usd(103)));
1554 env(
offer(gw, eur(100), usd(102)));
1555 env(
offer(gw, eur(100), usd(101)));
1556 env(
offer(gw, eur(100), usd(100)));
1558 env(
pay(carol, bob, usd(2'000)),
1565 BEAST_EXPECT(env.
balance(gw, usd) == usd(-1'000));
1566 BEAST_EXPECT(env.
balance(alice, usd) == usd(495));
1567 BEAST_EXPECT(env.
balance(bob, usd) == usd(505));
1571 BEAST_EXPECT(env.
balance(gw, usd) == usd(0));
1572 BEAST_EXPECT(env.
balance(alice, usd) == usd(495));
1575 BEAST_EXPECT(env.
balance(bob, usd) == usd(615));
1581 BEAST_EXPECT(env.
balance(carol, eur) == eur(210));
1586 BEAST_EXPECT(env.
balance(carol, eur) == eur(100));
1592 env.
balance(carol, eur) ==
STAmount(eur, UINT64_C(209'9009900990099), -13));
1609 env.
fund(
XRP(1'000), gw, alice, carol);
1612 MPTTester({.env = env, .issuer = gw, .holders = {alice, carol}, .maxAmt = 2'000});
1614 env(
pay(gw, carol, usd(1'000)));
1615 env(
pay(gw, alice, usd(600)));
1619 env(
offer(carol,
XRP(7), usd(15)));
1620 env(
offer(carol,
XRP(17), usd(35)));
1621 env(
offer(carol,
XRP(23), usd(47)));
1622 env(
offer(alice,
XRP(10), usd(19)));
1623 env(
offer(alice,
XRP(15), usd(28)));
1624 env(
offer(alice,
XRP(25), usd(46)));
1628 BEAST_EXPECT(env.
balance(gw, usd) == usd(-1'624));
1629 BEAST_EXPECT(env.
balance(carol, usd) == usd(1'102));
1633 BEAST_EXPECT(
isOffer(env, alice,
XRP(8), usd(15)));
1640 env.
fund(
XRP(1'000), gw, alice, carol, bob);
1643 MPTTester({.env = env, .issuer = gw, .holders = {alice, carol, bob}, .maxAmt = 30});
1645 env(
pay(gw, alice, usd(12)));
1646 env(
pay(gw, bob, usd(5)));
1648 env(
offer(alice,
XRP(10), usd(12)));
1653 BEAST_EXPECT(env.
balance(gw, usd) == usd(-28));
1654 BEAST_EXPECT(env.
balance(alice, usd) == usd(0));
1656 BEAST_EXPECT(env.
balance(bob, usd) == usd(28));
1682 expOffersBob()
const
1684 return expBobSellUSD == 0 ? 1 : 0;
1690 return expEdBuyUSD < 100 ? 1 : 0;
1693 expOffersDan()
const
1695 return expDanBuyUSD == 0 ? 1 : 0;
1699 auto test = [&](TestData
const& d) {
1701 env.
fund(
XRP(1'000), gw, alice, carol, bob, dan, john, ed, sam, bill);
1705 {.env = env, .issuer = gw, .holders = {alice, carol, bob}, .maxAmt = d.maxAmt});
1706 auto const eur = gw[
"EUR"];
1708 env(
pay(gw, alice, usd(100)));
1709 env(
pay(gw, carol, usd(100)));
1710 env(
pay(gw, bob, usd(100)));
1712 BEAST_EXPECT(env.
balance(gw, usd) == usd(-300));
1714 env(
trust(john, eur(100)));
1715 env(
trust(dan, eur(100)));
1716 env(
trust(ed, eur(100)));
1717 env(
trust(bill, eur(d.dstTrustLimit)));
1719 env(
pay(gw, john, eur(100)));
1720 env(
pay(gw, dan, eur(100)));
1721 env(
pay(gw, ed, eur(100)));
1725 env(
offer(alice,
XRP(100), usd(100)));
1728 env(
offer(carol,
XRP(100), usd(100)));
1730 if (!d.lastGwBuyUSD)
1732 env(
offer(gw,
XRP(100), usd(100)));
1735 env(
offer(bob,
XRP(100), usd(100)));
1739 env(
offer(gw,
XRP(100), usd(100)));
1748 env(
offer(john, usd(100), eur(100)));
1750 env(
offer(gw, usd(100), eur(100)));
1752 env(
offer(dan, usd(100), eur(100)));
1754 env(
offer(ed, usd(100), eur(100)));
1761 env(
pay(sam, bill, eur(400)),
1764 Txflags(tfPartialPayment | tfNoRippleDirect));
1767 auto const baseFee = env.
current()->fees().base.drops();
1768 BEAST_EXPECT(env.
balance(bill, eur) == eur(d.dstExpectEUR));
1769 BEAST_EXPECT(env.
balance(john, usd) == usd(100));
1770 BEAST_EXPECT(env.
balance(dan, usd) == usd(d.expDanBuyUSD));
1771 BEAST_EXPECT(env.
balance(ed, usd) == usd(d.expEdBuyUSD));
1772 BEAST_EXPECT(env.
balance(gw, usd) == usd(-d.outstandingUSD));
1773 BEAST_EXPECT(env.
balance(alice, usd) == usd(0));
1774 BEAST_EXPECT(env.
balance(carol, usd) == usd(0));
1775 BEAST_EXPECT(env.
balance(bob, usd) == usd(100 - d.expBobSellUSD));
1776 BEAST_EXPECT(env.
balance(gw) ==
XRPAmount{d.expGwXRP * kDropsPerXrp - baseFee * 9});
1779 BEAST_EXPECT(
expectOffers(env, dan, d.expOffersDan()));
1783 BEAST_EXPECT(
expectOffers(env, bob, d.expOffersBob()));
1794 { .maxAmt=400, .sendMax=400, .dstTrustLimit=400, .dstExpectEUR=400, .outstandingUSD=300, .expEdBuyUSD=100, .expDanBuyUSD=100, .expBobSellUSD=100, .expGwXRP=1100, .expOffersGw=0, .lastGwBuyUSD=
false},
1803 { .maxAmt=350, .sendMax=400, .dstTrustLimit=400, .dstExpectEUR=350, .outstandingUSD=250, .expEdBuyUSD=50, .expDanBuyUSD=100, .expBobSellUSD=100, .expGwXRP=1050, .expOffersGw=0, .lastGwBuyUSD=
false},
1809 { .maxAmt=300, .sendMax=400, .dstTrustLimit=400, .dstExpectEUR=300, .outstandingUSD=200, .expEdBuyUSD=0, .expDanBuyUSD=100, .expBobSellUSD=100, .expGwXRP=1000, .expOffersGw=0, .lastGwBuyUSD=
false},
1812 { .maxAmt=300, .sendMax=400, .dstTrustLimit=300, .dstExpectEUR=300, .outstandingUSD=200, .expEdBuyUSD=0, .expDanBuyUSD=100, .expBobSellUSD=100, .expGwXRP=1000, .expOffersGw=0, .lastGwBuyUSD=
false},
1818 { .maxAmt=300, .sendMax=400, .dstTrustLimit=300, .dstExpectEUR=300, .outstandingUSD=200, .expEdBuyUSD=0, .expDanBuyUSD=100, .expBobSellUSD=100, .expGwXRP=1000, .expOffersGw=0, .lastGwBuyUSD=
true},
1825 { .maxAmt=300, .sendMax=200, .dstTrustLimit=300, .dstExpectEUR=200, .outstandingUSD=200, .expEdBuyUSD=0, .expDanBuyUSD=0, .expBobSellUSD=0, .expGwXRP=1000, .expOffersGw=0, .lastGwBuyUSD=
false},
1828 { .maxAmt=300, .sendMax=380, .dstTrustLimit=400, .dstExpectEUR=300, .outstandingUSD=200, .expEdBuyUSD=0, .expDanBuyUSD=100, .expBobSellUSD=100, .expGwXRP=1000, .expOffersGw=0, .lastGwBuyUSD=
false},
1831 for (
auto const& t :
tests)
1852 expOffersBob()
const
1855 return expBobBuyUSD < 100 ? 1 : 0;
1859 auto test = [&](TestData
const& d) {
1861 env.
fund(
XRP(1'000), gw, alice, carol, bob, ed);
1865 MPTTester({.env = env, .issuer = gw, .holders = {alice}, .maxAmt = d.maxAmt});
1867 env(
pay(gw, alice, usd(300)));
1870 env(
offer(carol, usd(100),
XRP(100)));
1872 if (!d.lastGwBuyUSD)
1874 env(
offer(gw, usd(d.gwOffer),
XRP(d.gwOffer)));
1877 env(
offer(bob, usd(100),
XRP(100)));
1881 env(
offer(gw, usd(d.gwOffer),
XRP(d.gwOffer)));
1888 BEAST_EXPECT(env.
balance(gw, usd) == usd(-300));
1890 env(
pay(alice, ed,
XRP(300)),
1893 Txflags(tfPartialPayment | tfNoRippleDirect));
1896 auto const baseFee = env.
current()->fees().base.drops();
1897 BEAST_EXPECT(env.
balance(alice, usd) == usd(300 - d.sendMax));
1898 BEAST_EXPECT(env.
balance(carol, usd) == usd(100));
1899 BEAST_EXPECT(env.
balance(bob, usd) == usd(d.expBobBuyUSD));
1900 BEAST_EXPECT(env.
balance(ed) ==
XRP(d.dstExpectXRP));
1901 BEAST_EXPECT(env.
balance(gw, usd) == usd(-d.outstandingUSD));
1902 BEAST_EXPECT(env.
balance(gw) ==
XRPAmount{d.expGwXRP * kDropsPerXrp - baseFee * 3});
1904 BEAST_EXPECT(
expectOffers(env, bob, d.expOffersBob()));
1914 { .maxAmt=300, .sendMax=300, .gwOffer=100, .dstExpectXRP=1300, .outstandingUSD=200, .expBobBuyUSD=100, .expGwXRP=900, .expOffersGw=0, .lastGwBuyUSD=
false},
1917 { .maxAmt=300, .sendMax=300, .gwOffer=100, .dstExpectXRP=1300, .outstandingUSD=200, .expBobBuyUSD=100, .expGwXRP=900, .expOffersGw=0, .lastGwBuyUSD=
true},
1922 { .maxAmt=300, .sendMax=300, .gwOffer=200, .dstExpectXRP=1300, .outstandingUSD=100, .expBobBuyUSD=0, .expGwXRP=800, .expOffersGw=0, .lastGwBuyUSD=
false},
1927 { .maxAmt=300, .sendMax=300, .gwOffer=200, .dstExpectXRP=1300, .outstandingUSD=200, .expBobBuyUSD=100, .expGwXRP=900, .expOffersGw=1, .lastGwBuyUSD=
true},
1933 { .maxAmt=300, .sendMax=250, .gwOffer=200, .dstExpectXRP=1250, .outstandingUSD=250, .expBobBuyUSD=100, .expGwXRP=950, .expOffersGw=1, .lastGwBuyUSD=
true},
1936 for (
auto const& t :
tests)
1959 expOffersBob()
const
1961 return expBobSellUSD > 0 && expBobSellUSD < 100 ? 1 : 0;
1965 auto test = [&](TestData
const& d) {
1967 env.
fund(
XRP(1'000), gw, alice, carol, bob, ed);
1971 {.env = env, .issuer = gw, .holders = {carol, bob, ed}, .maxAmt = d.maxAmt});
1974 env(
pay(gw, ed, usd(d.initDst)));
1975 env(
pay(gw, carol, usd(100)));
1976 env(
pay(gw, bob, usd(100)));
1979 env(
offer(carol,
XRP(100), usd(100)));
1981 if (!d.lastGwBuyUSD)
1983 env(
offer(gw,
XRP(d.gwOffer), usd(d.gwOffer)));
1986 env(
offer(bob,
XRP(100), usd(100)));
1990 env(
offer(gw,
XRP(d.gwOffer), usd(d.gwOffer)));
1997 BEAST_EXPECT(env.
balance(gw, usd) == usd(-200 - d.initDst));
1999 env(
pay(alice, ed, usd(300)),
2002 Txflags(tfPartialPayment | tfNoRippleDirect));
2005 auto const baseFee = env.
current()->fees().base.drops();
2008 BEAST_EXPECT(env.
balance(carol, usd) == usd(0));
2009 BEAST_EXPECT(env.
balance(bob, usd) == usd(100 - d.expBobSellUSD));
2010 BEAST_EXPECT(env.
balance(ed, usd) == usd(d.dstExpectUSD));
2011 BEAST_EXPECT(env.
balance(gw, usd) == usd(-d.outstandingUSD));
2015 d.expGwXRP * kDropsPerXrp - baseFee * (4 + (d.initDst != 0 ? 1 : 0))});
2017 BEAST_EXPECT(
expectOffers(env, bob, d.expOffersBob()));
2026 { .maxAmt=300, .sendMax=300, .initDst=0, .gwOffer=100, .dstExpectUSD=300, .outstandingUSD=300, .expAliceXRP=700, .expBobSellUSD=100, .expGwXRP=1100, .expOffersGw=0, .lastGwBuyUSD=
false},
2029 { .maxAmt=300, .sendMax=300, .initDst=0, .gwOffer=100, .dstExpectUSD=300, .outstandingUSD=300, .expAliceXRP=700, .expBobSellUSD=100, .expGwXRP=1100, .expOffersGw=0, .lastGwBuyUSD=
true},
2037 { .maxAmt=300, .sendMax=300, .initDst=50, .gwOffer=100, .dstExpectUSD=300, .outstandingUSD=300, .expAliceXRP=750, .expBobSellUSD=100, .expGwXRP=1050, .expOffersGw=0, .lastGwBuyUSD=
false},
2040 { .maxAmt=300, .sendMax=300, .initDst=50, .gwOffer=100, .dstExpectUSD=300, .outstandingUSD=300, .expAliceXRP=750, .expBobSellUSD=100, .expGwXRP=1050, .expOffersGw=0, .lastGwBuyUSD=
true},
2043 { .maxAmt=300, .sendMax=300, .initDst=50, .gwOffer=200, .dstExpectUSD=300, .outstandingUSD=300, .expAliceXRP=750, .expBobSellUSD=100, .expGwXRP=1050, .expOffersGw=0, .lastGwBuyUSD=
true},
2048 { .maxAmt=300, .sendMax=250, .initDst=0, .gwOffer=100, .dstExpectUSD=250, .outstandingUSD=300, .expAliceXRP=750, .expBobSellUSD=50, .expGwXRP=1100, .expOffersGw=0, .lastGwBuyUSD=
false},
2053 { .maxAmt=300, .sendMax=250, .initDst=0, .gwOffer=100, .dstExpectUSD=250, .outstandingUSD=250, .expAliceXRP=750, .expBobSellUSD=100, .expGwXRP=1050, .expOffersGw=1, .lastGwBuyUSD=
true},
2058 { .maxAmt=300, .sendMax=250, .initDst=50, .gwOffer=100, .dstExpectUSD=300, .outstandingUSD=300, .expAliceXRP=750, .expBobSellUSD=100, .expGwXRP=1050, .expOffersGw=0, .lastGwBuyUSD=
true},
2063 { .maxAmt=300, .sendMax=250, .initDst=100, .gwOffer=100, .dstExpectUSD=300, .outstandingUSD=300, .expAliceXRP=800, .expBobSellUSD=100, .expGwXRP=1000, .expOffersGw=0, .lastGwBuyUSD=
true},
2066 for (
auto const& t :
tests)
2075 env.
fund(
XRP(1'000), gw, alice, carol);
2077 MPT const usd =
MPTTester({.env = env, .issuer = gw, .maxAmt = 300});
2079 env(
offer(carol, usd(400),
XRP(400)));
2080 env(
offer(gw, usd(100),
XRP(100)));
2084 env(
pay(gw, alice,
XRP(500)),
2087 Txflags(tfPartialPayment | tfNoRippleDirect));
2089 BEAST_EXPECT(env.
balance(alice) ==
XRP(dstXRP));
2090 BEAST_EXPECT(env.
balance(gw, usd) == usd(-300));
2091 BEAST_EXPECT(env.
balance(carol, usd) == usd(300));
2101 test(500, 1'400, 0);
2109 test(350, 1'350, 1);