127 auto const gw =
Account(
"gateway");
134 auto test = [&](
auto&& issue1,
auto&& issue2) {
135 Env env(*
this, features);
137 env.
fund(
XRP(10'000), alice, bob, carol, gw);
140 auto const usd = issue1(
141 {.env = env, .token =
"USD", .issuer = gw, .holders = {alice, bob, carol}});
142 auto const btc = issue2(
143 {.env = env, .token =
"BTC", .issuer = gw, .holders = {alice, bob, carol}});
145 env(
pay(gw, alice, btc(50)));
146 env(
pay(gw, bob, usd(50)));
148 env(
offer(bob, btc(50), usd(50)));
156 BEAST_EXPECT(!
isOffer(env, bob, btc(50), usd(50)));
162 auto test = [&](
auto&& issue1,
auto&& issue2) {
163 Env env(*
this, features);
165 env.
fund(
XRP(10'000), alice, bob, carol, gw);
168 auto const usd = issue1(
169 {.env = env, .token =
"USD", .issuer = gw, .holders = {alice, bob, carol}});
170 auto const btc = issue2(
171 {.env = env, .token =
"BTC", .issuer = gw, .holders = {alice, bob, carol}});
173 env(
pay(gw, alice, btc(50)));
174 env(
pay(gw, bob, usd(50)));
185 BEAST_EXPECT(!
isOffer(env, bob,
XRP(50), usd(50)));
186 BEAST_EXPECT(!
isOffer(env, bob, btc(50),
XRP(50)));
192 Env env(*
this, features);
194 env.
fund(
XRP(10'000), alice, bob, carol, gw);
197 MPT const usd =
MPTTester({.env = env, .issuer = gw, .holders = {alice, bob, carol}});
198 MPT const btc =
MPTTester({.env = env, .issuer = gw, .holders = {alice, bob, carol}});
200 env(
pay(gw, bob, usd(50)));
212 BEAST_EXPECT(!
isOffer(env, bob,
XRP(50), usd(50)));
216 Env env(*
this, features);
218 env.
fund(
XRP(10'000), alice, bob, carol, gw);
221 MPT const usd =
MPTTester({.env = env, .issuer = gw, .holders = {alice, bob, carol}});
222 MPT const btc =
MPTTester({.env = env, .issuer = gw, .holders = {alice, bob, carol}});
224 env(
pay(gw, alice, usd(50)));
234 BEAST_EXPECT(!
isOffer(env, bob, usd(50),
XRP(50)));
238 auto test = [&](
auto&& issue1,
auto&& issue2,
auto&& issue3) {
239 Env env(*
this, features);
241 env.
fund(
XRP(10'000), alice, bob, carol, gw);
244 auto const usd = issue1(
245 {.env = env, .token =
"USD", .issuer = gw, .holders = {alice, bob, carol}});
246 auto const btc = issue2(
247 {.env = env, .token =
"BTC", .issuer = gw, .holders = {alice, bob, carol}});
248 auto const eur = issue3(
249 {.env = env, .token =
"EUR", .issuer = gw, .holders = {alice, bob, carol}});
251 env(
pay(gw, alice, btc(60)));
252 env(
pay(gw, bob, usd(50)));
253 env(
pay(gw, bob, eur(50)));
255 env(
offer(bob, btc(50), usd(50)));
256 env(
offer(bob, btc(40), eur(50)));
257 env(
offer(bob, eur(50), usd(50)));
260 env(
pay(bob, gw, eur(50)));
262 BEAST_EXPECT(
isOffer(env, bob, btc(50), usd(50)));
263 BEAST_EXPECT(
isOffer(env, bob, btc(40), eur(50)));
264 BEAST_EXPECT(
isOffer(env, bob, eur(50), usd(50)));
274 BEAST_EXPECT(!
isOffer(env, bob, btc(50), usd(50)));
276 BEAST_EXPECT(!
isOffer(env, bob, btc(40), eur(50)));
278 BEAST_EXPECT(
isOffer(env, bob, eur(50), usd(50)));
291 auto test = [&](
auto&& issue1,
auto&& issue2,
auto&& issue3) {
292 Env env(*
this, features);
294 env.
fund(
XRP(10'000), alice, bob, carol, gw);
297 auto const usd = issue1(
301 .holders = {alice, bob, carol},
303 auto const btc = issue2(
307 .holders = {alice, bob, carol},
309 auto const eur = issue3(
313 .holders = {alice, bob, carol},
316 env(
pay(gw, alice, btc(60)));
317 env(
pay(gw, bob, usd(6'000)));
318 env(
pay(gw, bob, eur(5'000)));
319 env(
pay(gw, carol, eur(100)));
321 env(
offer(bob, btc(50), usd(5'000)));
322 env(
offer(bob, btc(60), eur(5'000)));
323 env(
offer(carol, btc(1'000), eur(100)));
324 env(
offer(bob, eur(5'000), usd(5'000)));
327 env(
pay(bob, gw, eur(5'000)));
328 BEAST_EXPECT(
isOffer(env, bob, btc(50), usd(5'000)));
329 BEAST_EXPECT(
isOffer(env, bob, btc(60), eur(5'000)));
330 BEAST_EXPECT(
isOffer(env, carol, btc(1'000), eur(100)));
333 auto const flowResult = [&] {
370 BEAST_EXPECT(flowResult.removableOffers.size() == 1);
372 if (flowResult.removableOffers.empty())
375 for (
auto const& o : flowResult.removableOffers)
386 BEAST_EXPECT(
isOffer(env, bob, btc(50), usd(5'000)));
387 BEAST_EXPECT(
isOffer(env, carol, btc(1'000), eur(100)));
389 BEAST_EXPECT(!
isOffer(env, bob, btc(60), eur(5'000)));
402 auto test = [&](
auto&& issue1,
auto&& issue2) {
403 Env env(*
this, features);
404 env.
fund(
XRP(10'000), alice, bob, carol, gw);
406 auto const usd = issue1(
407 {.env = env, .token =
"USD", .issuer = gw, .holders = {alice, bob, carol}});
408 auto const eur = issue1(
409 {.env = env, .token =
"EUR", .issuer = gw, .holders = {alice, bob, carol}});
411 env(
pay(gw, alice, usd(1'000)));
412 env(
pay(gw, bob, eur(1'000)));
418 bool const reducedOffersV2 = features[fixReducedOffersV2];
426 env(
pay(alice, carol, eur(1)),
429 Txflags(tfNoRippleDirect | tfPartialPayment),
432 if (!reducedOffersV2)
440 if (BEAST_EXPECT(usdOffer))
447 bookDirStr.
erase(0, 48);
451 getRate(usdOffer->at(sfTakerGets), usdOffer->at(sfTakerPays));
458 BEAST_EXPECT(actualRate > bookRate);
1585 testcase(
"Max Flow/Self Payment Edge Cases");
1586 using namespace jtx;
1596 env.
fund(
XRP(1'000), gw, alice, carol);
1599 MPTTester({.env = env, .issuer = gw, .holders = {alice, carol}, .maxAmt = 100});
1601 env(
pay(gw, alice, usd(100)));
1603 env(
pay(alice, carol, usd(100)));
1605 BEAST_EXPECT(env.
balance(gw, usd) == usd(-100));
1606 BEAST_EXPECT(env.
balance(carol, usd) == usd(100));
1607 BEAST_EXPECT(env.
balance(alice, usd) == usd(0));
1615 env.
fund(
XRP(1'000), gw, alice, carol);
1618 MPTTester({.env = env, .issuer = gw, .holders = {alice, carol}, .maxAmt = 100});
1620 env(
pay(gw, alice, usd(80)));
1622 env(
pay(alice, carol, usd(100)),
Txflags(tfPartialPayment));
1624 BEAST_EXPECT(env.
balance(gw, usd) == usd(-80));
1625 BEAST_EXPECT(env.
balance(alice, usd) == usd(0));
1626 BEAST_EXPECT(env.
balance(carol, usd) == usd(80));
1635 env.
fund(
XRP(1'000), gw, alice, carol, bob);
1638 {.env = env, .issuer = gw, .holders = {alice, carol, bob}, .maxAmt = 100});
1640 env(
pay(gw, bob, usd(20)));
1641 env(
pay(gw, alice, usd(80)));
1643 env(
pay(alice, carol, usd(100)),
Txflags(tfPartialPayment));
1645 BEAST_EXPECT(env.
balance(gw, usd) == usd(-100));
1646 BEAST_EXPECT(env.
balance(alice, usd) == usd(0));
1647 BEAST_EXPECT(env.
balance(carol, usd) == usd(80));
1656 env.
fund(
XRP(1'000), gw, alice, carol, bob);
1659 MPTTester({.env = env, .issuer = gw, .holders = {alice, carol}, .maxAmt = 100});
1661 env(
pay(gw, alice, usd(100)));
1663 env(
offer(alice,
XRP(100), usd(100)));
1667 BEAST_EXPECT(env.
balance(gw, usd) == usd(-100));
1668 BEAST_EXPECT(env.
balance(alice, usd) == usd(0));
1669 BEAST_EXPECT(env.
balance(carol, usd) == usd(100));
1679 env.
fund(
XRP(1'000), gw, alice, carol);
1682 MPTTester({.env = env, .issuer = gw, .holders = {carol}, .maxAmt = 100});
1684 env(
pay(gw, carol, usd(100)));
1686 env(
offer(gw,
XRP(100), usd(100)));
1688 env(
pay(alice, carol, usd(100)),
1694 BEAST_EXPECT(env.
balance(gw, usd) == usd(-100));
1695 BEAST_EXPECT(env.
balance(carol, usd) == usd(100));
1704 env.
fund(
XRP(1'000), gw, alice, carol);
1707 MPTTester({.env = env, .issuer = gw, .holders = {carol}, .maxAmt = 100});
1709 env(
pay(gw, carol, usd(80)));
1711 env(
offer(gw,
XRP(100), usd(100)));
1713 env(
pay(alice, carol, usd(100)),
1718 BEAST_EXPECT(env.
balance(gw, usd) == usd(-100));
1719 BEAST_EXPECT(env.
balance(carol, usd) == usd(100));
1728 env.
fund(
XRP(1'000), gw, alice);
1731 MPTTester({.env = env, .issuer = gw, .holders = {alice}, .maxAmt = 100});
1733 env(
pay(gw, alice, usd(100)));
1735 env(
offer(alice, usd(100),
XRP(100)));
1739 BEAST_EXPECT(env.
balance(gw, usd) == usd(-100));
1740 BEAST_EXPECT(env.
balance(alice, usd) == usd(100));
1749 auto test = [&](
auto&& issue1,
auto&& issue2) {
1752 env.
fund(
XRP(1'000), gw, alice, carol);
1755 auto const usd = issue1(
1759 .holders = {alice, carol},
1762 auto const eur = issue2(
1766 .holders = {alice, carol},
1769 env(
pay(gw, alice, usd(100)));
1771 env(
offer(alice, eur(100), usd(100)));
1776 BEAST_EXPECT(env.
balance(gw, usd) == usd(-100));
1777 BEAST_EXPECT(env.
balance(alice, usd) == usd(0));
1778 BEAST_EXPECT(env.
balance(alice, eur) == eur(100));
1779 BEAST_EXPECT(env.
balance(carol, usd) == usd(100));
1789 env.
fund(
XRP(1'000), gw, alice, carol);
1792 MPTTester({.env = env, .issuer = gw, .holders = {carol}, .maxAmt = 120});
1794 env(
pay(gw, carol, usd(100)));
1796 env(
offer(carol,
XRP(100), usd(100)));
1798 env(
pay(alice, carol, usd(100)),
1803 BEAST_EXPECT(env.
balance(carol, usd) == usd(100));
1812 env.
fund(
XRP(1'000), gw, alice, carol);
1815 MPTTester({.env = env, .issuer = gw, .holders = {carol}, .maxAmt = 100});
1817 env(
pay(gw, carol, usd(100)));
1819 env(
offer(carol,
XRP(100), usd(100)));
1821 env(
pay(alice, carol, usd(100)),
1826 BEAST_EXPECT(env.
balance(carol, usd) == usd(100));
1832 auto test = [&](
auto&& issue1,
auto&& issue2) {
1835 env.
fund(
XRP(1'000), gw, alice, carol, bob);
1838 auto const usd = issue1(
1842 .holders = {alice, carol, bob},
1845 auto const eur = issue2(
1849 .holders = {alice, carol, bob},
1853 env(
pay(gw, alice, usd(600)));
1854 env(
pay(gw, carol, eur(700)));
1856 env(
offer(alice, eur(100), usd(105)));
1857 env(
offer(gw, eur(100), usd(104)));
1858 env(
offer(gw, eur(100), usd(103)));
1859 env(
offer(gw, eur(100), usd(102)));
1860 env(
offer(gw, eur(100), usd(101)));
1861 env(
offer(gw, eur(100), usd(100)));
1863 env(
pay(carol, bob, usd(2'000)),
1870 BEAST_EXPECT(env.
balance(gw, usd) == usd(-1'000));
1871 BEAST_EXPECT(env.
balance(alice, usd) == usd(495));
1872 BEAST_EXPECT(env.
balance(bob, usd) == usd(505));
1876 BEAST_EXPECT(env.
balance(gw, usd) == usd(0));
1877 BEAST_EXPECT(env.
balance(alice, usd) == usd(495));
1880 BEAST_EXPECT(env.
balance(bob, usd) == usd(615));
1886 BEAST_EXPECT(env.
balance(carol, eur) == eur(210));
1891 BEAST_EXPECT(env.
balance(carol, eur) == eur(100));
1897 env.
balance(carol, eur) ==
STAmount(eur, UINT64_C(209'9009900990099), -13));
1914 env.
fund(
XRP(1'000), gw, alice, carol);
1917 MPTTester({.env = env, .issuer = gw, .holders = {alice, carol}, .maxAmt = 2'000});
1919 env(
pay(gw, carol, usd(1'000)));
1920 env(
pay(gw, alice, usd(600)));
1924 env(
offer(carol,
XRP(7), usd(15)));
1925 env(
offer(carol,
XRP(17), usd(35)));
1926 env(
offer(carol,
XRP(23), usd(47)));
1927 env(
offer(alice,
XRP(10), usd(19)));
1928 env(
offer(alice,
XRP(15), usd(28)));
1929 env(
offer(alice,
XRP(25), usd(46)));
1933 BEAST_EXPECT(env.
balance(gw, usd) == usd(-1'624));
1934 BEAST_EXPECT(env.
balance(carol, usd) == usd(1'102));
1938 BEAST_EXPECT(
isOffer(env, alice,
XRP(8), usd(15)));
1945 env.
fund(
XRP(1'000), gw, alice, carol, bob);
1948 MPTTester({.env = env, .issuer = gw, .holders = {alice, carol, bob}, .maxAmt = 30});
1950 env(
pay(gw, alice, usd(12)));
1951 env(
pay(gw, bob, usd(5)));
1953 env(
offer(alice,
XRP(10), usd(12)));
1958 BEAST_EXPECT(env.
balance(gw, usd) == usd(-28));
1959 BEAST_EXPECT(env.
balance(alice, usd) == usd(0));
1961 BEAST_EXPECT(env.
balance(bob, usd) == usd(28));
1987 expOffersBob()
const
1989 return expBobSellUSD == 0 ? 1 : 0;
1995 return expEdBuyUSD < 100 ? 1 : 0;
1998 expOffersDan()
const
2000 return expDanBuyUSD == 0 ? 1 : 0;
2004 auto test = [&](TestData
const& d) {
2006 env.
fund(
XRP(1'000), gw, alice, carol, bob, dan, john, ed, sam, bill);
2010 {.env = env, .issuer = gw, .holders = {alice, carol, bob}, .maxAmt = d.maxAmt});
2011 auto const eur = gw[
"EUR"];
2013 env(
pay(gw, alice, usd(100)));
2014 env(
pay(gw, carol, usd(100)));
2015 env(
pay(gw, bob, usd(100)));
2017 BEAST_EXPECT(env.
balance(gw, usd) == usd(-300));
2019 env(
trust(john, eur(100)));
2020 env(
trust(dan, eur(100)));
2021 env(
trust(ed, eur(100)));
2022 env(
trust(bill, eur(d.dstTrustLimit)));
2024 env(
pay(gw, john, eur(100)));
2025 env(
pay(gw, dan, eur(100)));
2026 env(
pay(gw, ed, eur(100)));
2030 env(
offer(alice,
XRP(100), usd(100)));
2033 env(
offer(carol,
XRP(100), usd(100)));
2035 if (!d.lastGwBuyUSD)
2037 env(
offer(gw,
XRP(100), usd(100)));
2040 env(
offer(bob,
XRP(100), usd(100)));
2044 env(
offer(gw,
XRP(100), usd(100)));
2053 env(
offer(john, usd(100), eur(100)));
2055 env(
offer(gw, usd(100), eur(100)));
2057 env(
offer(dan, usd(100), eur(100)));
2059 env(
offer(ed, usd(100), eur(100)));
2066 env(
pay(sam, bill, eur(400)),
2069 Txflags(tfPartialPayment | tfNoRippleDirect));
2072 auto const baseFee = env.
current()->fees().base.drops();
2073 BEAST_EXPECT(env.
balance(bill, eur) == eur(d.dstExpectEUR));
2074 BEAST_EXPECT(env.
balance(john, usd) == usd(100));
2075 BEAST_EXPECT(env.
balance(dan, usd) == usd(d.expDanBuyUSD));
2076 BEAST_EXPECT(env.
balance(ed, usd) == usd(d.expEdBuyUSD));
2077 BEAST_EXPECT(env.
balance(gw, usd) == usd(-d.outstandingUSD));
2078 BEAST_EXPECT(env.
balance(alice, usd) == usd(0));
2079 BEAST_EXPECT(env.
balance(carol, usd) == usd(0));
2080 BEAST_EXPECT(env.
balance(bob, usd) == usd(100 - d.expBobSellUSD));
2081 BEAST_EXPECT(env.
balance(gw) ==
XRPAmount{d.expGwXRP * kDropsPerXrp - baseFee * 9});
2084 BEAST_EXPECT(
expectOffers(env, dan, d.expOffersDan()));
2088 BEAST_EXPECT(
expectOffers(env, bob, d.expOffersBob()));
2099 { .maxAmt=400, .sendMax=400, .dstTrustLimit=400, .dstExpectEUR=400, .outstandingUSD=300, .expEdBuyUSD=100, .expDanBuyUSD=100, .expBobSellUSD=100, .expGwXRP=1100, .expOffersGw=0, .lastGwBuyUSD=
false},
2108 { .maxAmt=350, .sendMax=400, .dstTrustLimit=400, .dstExpectEUR=350, .outstandingUSD=250, .expEdBuyUSD=50, .expDanBuyUSD=100, .expBobSellUSD=100, .expGwXRP=1050, .expOffersGw=0, .lastGwBuyUSD=
false},
2114 { .maxAmt=300, .sendMax=400, .dstTrustLimit=400, .dstExpectEUR=300, .outstandingUSD=200, .expEdBuyUSD=0, .expDanBuyUSD=100, .expBobSellUSD=100, .expGwXRP=1000, .expOffersGw=0, .lastGwBuyUSD=
false},
2117 { .maxAmt=300, .sendMax=400, .dstTrustLimit=300, .dstExpectEUR=300, .outstandingUSD=200, .expEdBuyUSD=0, .expDanBuyUSD=100, .expBobSellUSD=100, .expGwXRP=1000, .expOffersGw=0, .lastGwBuyUSD=
false},
2123 { .maxAmt=300, .sendMax=400, .dstTrustLimit=300, .dstExpectEUR=300, .outstandingUSD=200, .expEdBuyUSD=0, .expDanBuyUSD=100, .expBobSellUSD=100, .expGwXRP=1000, .expOffersGw=0, .lastGwBuyUSD=
true},
2130 { .maxAmt=300, .sendMax=200, .dstTrustLimit=300, .dstExpectEUR=200, .outstandingUSD=200, .expEdBuyUSD=0, .expDanBuyUSD=0, .expBobSellUSD=0, .expGwXRP=1000, .expOffersGw=0, .lastGwBuyUSD=
false},
2133 { .maxAmt=300, .sendMax=380, .dstTrustLimit=400, .dstExpectEUR=300, .outstandingUSD=200, .expEdBuyUSD=0, .expDanBuyUSD=100, .expBobSellUSD=100, .expGwXRP=1000, .expOffersGw=0, .lastGwBuyUSD=
false},
2136 for (
auto const& t :
tests)
2157 expOffersBob()
const
2160 return expBobBuyUSD < 100 ? 1 : 0;
2164 auto test = [&](TestData
const& d) {
2166 env.
fund(
XRP(1'000), gw, alice, carol, bob, ed);
2170 MPTTester({.env = env, .issuer = gw, .holders = {alice}, .maxAmt = d.maxAmt});
2172 env(
pay(gw, alice, usd(300)));
2175 env(
offer(carol, usd(100),
XRP(100)));
2177 if (!d.lastGwBuyUSD)
2179 env(
offer(gw, usd(d.gwOffer),
XRP(d.gwOffer)));
2182 env(
offer(bob, usd(100),
XRP(100)));
2186 env(
offer(gw, usd(d.gwOffer),
XRP(d.gwOffer)));
2193 BEAST_EXPECT(env.
balance(gw, usd) == usd(-300));
2195 env(
pay(alice, ed,
XRP(300)),
2198 Txflags(tfPartialPayment | tfNoRippleDirect));
2201 auto const baseFee = env.
current()->fees().base.drops();
2202 BEAST_EXPECT(env.
balance(alice, usd) == usd(300 - d.sendMax));
2203 BEAST_EXPECT(env.
balance(carol, usd) == usd(100));
2204 BEAST_EXPECT(env.
balance(bob, usd) == usd(d.expBobBuyUSD));
2205 BEAST_EXPECT(env.
balance(ed) ==
XRP(d.dstExpectXRP));
2206 BEAST_EXPECT(env.
balance(gw, usd) == usd(-d.outstandingUSD));
2207 BEAST_EXPECT(env.
balance(gw) ==
XRPAmount{d.expGwXRP * kDropsPerXrp - baseFee * 3});
2209 BEAST_EXPECT(
expectOffers(env, bob, d.expOffersBob()));
2219 { .maxAmt=300, .sendMax=300, .gwOffer=100, .dstExpectXRP=1300, .outstandingUSD=200, .expBobBuyUSD=100, .expGwXRP=900, .expOffersGw=0, .lastGwBuyUSD=
false},
2222 { .maxAmt=300, .sendMax=300, .gwOffer=100, .dstExpectXRP=1300, .outstandingUSD=200, .expBobBuyUSD=100, .expGwXRP=900, .expOffersGw=0, .lastGwBuyUSD=
true},
2227 { .maxAmt=300, .sendMax=300, .gwOffer=200, .dstExpectXRP=1300, .outstandingUSD=100, .expBobBuyUSD=0, .expGwXRP=800, .expOffersGw=0, .lastGwBuyUSD=
false},
2232 { .maxAmt=300, .sendMax=300, .gwOffer=200, .dstExpectXRP=1300, .outstandingUSD=200, .expBobBuyUSD=100, .expGwXRP=900, .expOffersGw=1, .lastGwBuyUSD=
true},
2238 { .maxAmt=300, .sendMax=250, .gwOffer=200, .dstExpectXRP=1250, .outstandingUSD=250, .expBobBuyUSD=100, .expGwXRP=950, .expOffersGw=1, .lastGwBuyUSD=
true},
2241 for (
auto const& t :
tests)
2264 expOffersBob()
const
2266 return expBobSellUSD > 0 && expBobSellUSD < 100 ? 1 : 0;
2270 auto test = [&](TestData
const& d) {
2272 env.
fund(
XRP(1'000), gw, alice, carol, bob, ed);
2276 {.env = env, .issuer = gw, .holders = {carol, bob, ed}, .maxAmt = d.maxAmt});
2279 env(
pay(gw, ed, usd(d.initDst)));
2280 env(
pay(gw, carol, usd(100)));
2281 env(
pay(gw, bob, usd(100)));
2284 env(
offer(carol,
XRP(100), usd(100)));
2286 if (!d.lastGwBuyUSD)
2288 env(
offer(gw,
XRP(d.gwOffer), usd(d.gwOffer)));
2291 env(
offer(bob,
XRP(100), usd(100)));
2295 env(
offer(gw,
XRP(d.gwOffer), usd(d.gwOffer)));
2302 BEAST_EXPECT(env.
balance(gw, usd) == usd(-200 - d.initDst));
2304 env(
pay(alice, ed, usd(300)),
2307 Txflags(tfPartialPayment | tfNoRippleDirect));
2310 auto const baseFee = env.
current()->fees().base.drops();
2313 BEAST_EXPECT(env.
balance(carol, usd) == usd(0));
2314 BEAST_EXPECT(env.
balance(bob, usd) == usd(100 - d.expBobSellUSD));
2315 BEAST_EXPECT(env.
balance(ed, usd) == usd(d.dstExpectUSD));
2316 BEAST_EXPECT(env.
balance(gw, usd) == usd(-d.outstandingUSD));
2320 d.expGwXRP * kDropsPerXrp - baseFee * (4 + (d.initDst != 0 ? 1 : 0))});
2322 BEAST_EXPECT(
expectOffers(env, bob, d.expOffersBob()));
2331 { .maxAmt=300, .sendMax=300, .initDst=0, .gwOffer=100, .dstExpectUSD=300, .outstandingUSD=300, .expAliceXRP=700, .expBobSellUSD=100, .expGwXRP=1100, .expOffersGw=0, .lastGwBuyUSD=
false},
2334 { .maxAmt=300, .sendMax=300, .initDst=0, .gwOffer=100, .dstExpectUSD=300, .outstandingUSD=300, .expAliceXRP=700, .expBobSellUSD=100, .expGwXRP=1100, .expOffersGw=0, .lastGwBuyUSD=
true},
2342 { .maxAmt=300, .sendMax=300, .initDst=50, .gwOffer=100, .dstExpectUSD=300, .outstandingUSD=300, .expAliceXRP=750, .expBobSellUSD=100, .expGwXRP=1050, .expOffersGw=0, .lastGwBuyUSD=
false},
2345 { .maxAmt=300, .sendMax=300, .initDst=50, .gwOffer=100, .dstExpectUSD=300, .outstandingUSD=300, .expAliceXRP=750, .expBobSellUSD=100, .expGwXRP=1050, .expOffersGw=0, .lastGwBuyUSD=
true},
2348 { .maxAmt=300, .sendMax=300, .initDst=50, .gwOffer=200, .dstExpectUSD=300, .outstandingUSD=300, .expAliceXRP=750, .expBobSellUSD=100, .expGwXRP=1050, .expOffersGw=0, .lastGwBuyUSD=
true},
2353 { .maxAmt=300, .sendMax=250, .initDst=0, .gwOffer=100, .dstExpectUSD=250, .outstandingUSD=300, .expAliceXRP=750, .expBobSellUSD=50, .expGwXRP=1100, .expOffersGw=0, .lastGwBuyUSD=
false},
2358 { .maxAmt=300, .sendMax=250, .initDst=0, .gwOffer=100, .dstExpectUSD=250, .outstandingUSD=250, .expAliceXRP=750, .expBobSellUSD=100, .expGwXRP=1050, .expOffersGw=1, .lastGwBuyUSD=
true},
2363 { .maxAmt=300, .sendMax=250, .initDst=50, .gwOffer=100, .dstExpectUSD=300, .outstandingUSD=300, .expAliceXRP=750, .expBobSellUSD=100, .expGwXRP=1050, .expOffersGw=0, .lastGwBuyUSD=
true},
2368 { .maxAmt=300, .sendMax=250, .initDst=100, .gwOffer=100, .dstExpectUSD=300, .outstandingUSD=300, .expAliceXRP=800, .expBobSellUSD=100, .expGwXRP=1000, .expOffersGw=0, .lastGwBuyUSD=
true},
2371 for (
auto const& t :
tests)
2380 env.
fund(
XRP(1'000), gw, alice, carol);
2382 MPT const usd =
MPTTester({.env = env, .issuer = gw, .maxAmt = 300});
2384 env(
offer(carol, usd(400),
XRP(400)));
2385 env(
offer(gw, usd(100),
XRP(100)));
2389 env(
pay(gw, alice,
XRP(500)),
2392 Txflags(tfPartialPayment | tfNoRippleDirect));
2394 BEAST_EXPECT(env.
balance(alice) ==
XRP(dstXRP));
2395 BEAST_EXPECT(env.
balance(gw, usd) == usd(-300));
2396 BEAST_EXPECT(env.
balance(carol, usd) == usd(300));
2406 test(500, 1'400, 0);
2414 test(350, 1'350, 1);