2080 using namespace jtx;
2082 auto const gw =
Account(
"gateway");
2083 auto const USD = gw[
"USD"];
2085 Env env{*
this, features};
2087 env.fund(
XRP(10000000), gw);
2091 auto const f = env.current()->fees().base;
2094 enum preTrustType { noPreTrust, gwPreTrust, acctPreTrust };
2100 preTrustType preTrust;
2110 TestData
const tests[]{
2112 {
"ann",
reserve(env, 0) + 0 * f, 1, noPreTrust, 1000,
tecUNFUNDED_OFFER, f, USD( 0), 0, 0},
2113 {
"bev",
reserve(env, 0) + 1 * f, 1, noPreTrust, 1000,
tecUNFUNDED_OFFER, f, USD( 0), 0, 0},
2114 {
"cam",
reserve(env, 0) + 2 * f, 0, noPreTrust, 1000,
tecINSUF_RESERVE_OFFER, f, USD( 0), 0, 0},
2115 {
"deb",
drops(10) +
reserve(env, 0) + 1 * f, 1, noPreTrust, 1000,
tesSUCCESS,
drops(10) + f, USD(0.00001), 0, 1},
2116 {
"eve",
reserve(env, 1) + 0 * f, 0, noPreTrust, 1000,
tesSUCCESS, f, USD( 0), 1, 1},
2117 {
"flo",
reserve(env, 1) + 0 * f, 1, noPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 0, 1},
2118 {
"gay",
reserve(env, 1) + 1 * f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP( 50) + f, USD( 50), 0, 1},
2119 {
"hye",
XRP(1000) + 1 * f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP( 800) + f, USD( 800), 0, 1},
2120 {
"ivy",
XRP( 1) +
reserve(env, 1) + 1 * f, 1, noPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 0, 1},
2121 {
"joy",
XRP( 1) +
reserve(env, 2) + 1 * f, 1, noPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 1, 2},
2122 {
"kim",
XRP( 900) +
reserve(env, 2) + 1 * f, 999, noPreTrust, 1000,
tesSUCCESS,
XRP( 999) + f, USD( 999), 0, 1},
2123 {
"liz",
XRP( 998) +
reserve(env, 0) + 1 * f, 999, noPreTrust, 1000,
tesSUCCESS,
XRP( 998) + f, USD( 998), 0, 1},
2124 {
"meg",
XRP( 998) +
reserve(env, 1) + 1 * f, 999, noPreTrust, 1000,
tesSUCCESS,
XRP( 999) + f, USD( 999), 0, 1},
2125 {
"nia",
XRP( 998) +
reserve(env, 2) + 1 * f, 999, noPreTrust, 1000,
tesSUCCESS,
XRP( 999) + f, USD( 999), 1, 2},
2126 {
"ova",
XRP( 999) +
reserve(env, 0) + 1 * f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP( 999) + f, USD( 999), 0, 1},
2127 {
"pam",
XRP( 999) +
reserve(env, 1) + 1 * f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP(1000) + f, USD( 1000), 0, 1},
2128 {
"rae",
XRP( 999) +
reserve(env, 2) + 1 * f, 1000, noPreTrust, 1000,
tesSUCCESS,
XRP(1000) + f, USD( 1000), 0, 1},
2129 {
"sue",
XRP(1000) +
reserve(env, 2) + 1 * f, 0, noPreTrust, 1000,
tesSUCCESS, f, USD( 0), 1, 1},
2131 {
"abe",
reserve(env, 0) + 0 * f, 1, gwPreTrust, 1000,
tecUNFUNDED_OFFER, f, USD( 0), 0, 0},
2132 {
"bud",
reserve(env, 0) + 1 * f, 1, gwPreTrust, 1000,
tecUNFUNDED_OFFER, f, USD( 0), 0, 0},
2133 {
"che",
reserve(env, 0) + 2 * f, 0, gwPreTrust, 1000,
tecINSUF_RESERVE_OFFER, f, USD( 0), 0, 0},
2134 {
"dan",
drops(10) +
reserve(env, 0) + 1 * f, 1, gwPreTrust, 1000,
tesSUCCESS,
drops(10) + f, USD(0.00001), 0, 0},
2135 {
"eli",
XRP( 20) +
reserve(env, 0) + 1 * f, 1000, gwPreTrust, 1000,
tesSUCCESS,
XRP(20) + 1 * f, USD( 20), 0, 0},
2136 {
"fyn",
reserve(env, 1) + 0 * f, 0, gwPreTrust, 1000,
tesSUCCESS, f, USD( 0), 1, 1},
2137 {
"gar",
reserve(env, 1) + 0 * f, 1, gwPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 1, 1},
2138 {
"hal",
reserve(env, 1) + 1 * f, 1, gwPreTrust, 1000,
tesSUCCESS,
XRP( 1) + f, USD( 1), 1, 1},
2140 {
"ned",
reserve(env, 1) + 0 * f, 1, acctPreTrust, 1000,
tecUNFUNDED_OFFER, 2 * f, USD( 0), 0, 1},
2141 {
"ole",
reserve(env, 1) + 1 * f, 1, acctPreTrust, 1000,
tecUNFUNDED_OFFER, 2 * f, USD( 0), 0, 1},
2142 {
"pat",
reserve(env, 1) + 2 * f, 0, acctPreTrust, 1000,
tecUNFUNDED_OFFER, 2 * f, USD( 0), 0, 1},
2143 {
"quy",
reserve(env, 1) + 2 * f, 1, acctPreTrust, 1000,
tecUNFUNDED_OFFER, 2 * f, USD( 0), 0, 1},
2144 {
"ron",
reserve(env, 1) + 3 * f, 0, acctPreTrust, 1000,
tecINSUF_RESERVE_OFFER, 2 * f, USD( 0), 0, 1},
2145 {
"syd",
drops(10) +
reserve(env, 1) + 2 * f, 1, acctPreTrust, 1000,
tesSUCCESS,
drops(10) + 2 * f, USD(0.00001), 0, 1},
2146 {
"ted",
XRP( 20) +
reserve(env, 1) + 2 * f, 1000, acctPreTrust, 1000,
tesSUCCESS,
XRP(20) + 2 * f, USD( 20), 0, 1},
2147 {
"uli",
reserve(env, 2) + 0 * f, 0, acctPreTrust, 1000,
tecINSUF_RESERVE_OFFER, 2 * f, USD( 0), 0, 1},
2148 {
"vic",
reserve(env, 2) + 0 * f, 1, acctPreTrust, 1000,
tesSUCCESS,
XRP( 1) + 2 * f, USD( 1), 0, 1},
2149 {
"wes",
reserve(env, 2) + 1 * f, 0, acctPreTrust, 1000,
tesSUCCESS, 2 * f, USD( 0), 1, 2},
2150 {
"xan",
reserve(env, 2) + 1 * f, 1, acctPreTrust, 1000,
tesSUCCESS,
XRP( 1) + 2 * f, USD( 1), 1, 2},
2154 for (
auto const& t : tests)
2156 auto const acct =
Account(t.account);
2157 env.fund(t.fundXrp, acct);
2161 env.require(
offers(gw, 0));
2164 auto const book = t.bookAmount;
2166 env(
offer(gw,
XRP(book), USD(book)));
2171 if (t.preTrust == gwPreTrust)
2172 env(
trust(gw, acct[
"USD"](1)));
2178 if (t.preTrust == acctPreTrust)
2179 env(
trust(acct, USD(1)));
2184 auto const acctOffer = t.offerAmount;
2185 env(
offer(acct, USD(acctOffer),
XRP(acctOffer)),
ter(t.tec));
2190 BEAST_EXPECT(env.balance(acct, USD.issue()) == t.balanceUsd);
2191 BEAST_EXPECT(env.balance(acct,
xrpIssue()) == t.fundXrp - t.spentXrp);
2192 env.require(
offers(acct, t.offers));
2193 env.require(
owners(acct, t.owners));
2196 BEAST_EXPECT(acctOffers.size() == t.offers);
2197 if (acctOffers.size() && t.offers)
2199 auto const& acctOffer = *(acctOffers.front());
2201 auto const leftover = t.offerAmount - t.bookAmount;
2202 BEAST_EXPECT(acctOffer[sfTakerGets] ==
XRP(leftover));
2203 BEAST_EXPECT(acctOffer[sfTakerPays] == USD(leftover));
2206 if (t.preTrust == noPreTrust)
2208 if (t.balanceUsd.value().signum())
2216 auto const sleTrust = env.le(
keylet::line(acct, USD.issue()));
2217 BEAST_EXPECT(!sleTrust);
2526 using namespace jtx;
2528 auto const gw =
Account(
"gateway");
2529 auto const USD = gw[
"USD"];
2531 Env env{*
this, features};
2533 env.fund(
XRP(10000000), gw);
2537 auto const f = env.current()->fees().base;
2540 enum preTrustType { noPreTrust, gwPreTrust, acctPreTrust };
2574 : account(std::move(account_))
2579 , acctGets(acctGets_)
2580 , acctPays(acctPays_)
2582 , spentXrp(spentXrp_)
2583 , finalUsd(finalUsd_)
2586 , takerGets(takerGets_)
2587 , takerPays(takerPays_)
2606 std::move(account_),
2625 TestData
const tests[]{
2628 {
"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},
2629 {
"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)},
2630 {
"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},
2631 {
"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},
2632 {
"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},
2633 {
"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},
2634 {
"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},
2635 {
"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)},
2637 {
"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},
2638 {
"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)},
2639 {
"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},
2640 {
"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},
2641 {
"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},
2642 {
"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)},
2643 {
"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)},
2647 auto const zeroUsd = USD(0);
2648 for (
auto const& t : tests)
2651 env.require(
offers(gw, 0));
2653 auto const acct =
Account(t.account);
2655 env.fund(t.fundXrp, acct);
2661 if (t.fundUSD != zeroUsd)
2663 env(
trust(acct, t.fundUSD));
2665 env(
pay(gw, acct, t.fundUSD));
2669 env(
offer(gw, t.gwGets, t.gwPays));
2679 BEAST_EXPECT(env.balance(acct, USD.issue()) == t.finalUsd);
2680 BEAST_EXPECT(env.balance(acct,
xrpIssue()) == t.fundXrp - t.spentXrp);
2681 env.require(
offers(acct, t.offers));
2682 env.require(
owners(acct, t.owners));
2687 if (acctOffers.size() > 0)
2689 BEAST_EXPECT(acctOffers.size() == 1);
2690 auto const& acctOffer = *(acctOffers.front());
2692 BEAST_EXPECT(acctOffer[sfLedgerEntryType] == ltOFFER);
2693 BEAST_EXPECT(acctOffer[sfTakerGets] == t.takerGets);
2694 BEAST_EXPECT(acctOffer[sfTakerPays] == t.takerPays);
3170 using namespace jtx;
3172 auto const gw1 =
Account(
"gateway1");
3173 auto const gw2 =
Account(
"gateway2");
3174 auto const alice =
Account(
"alice");
3175 auto const USD = gw1[
"USD"];
3176 auto const EUR = gw2[
"EUR"];
3178 Env env{*
this, features};
3180 env.fund(
XRP(1000000), gw1, gw2);
3184 auto const f = env.current()->fees().base;
3198 TestData
const tests[]{
3209 for (
auto const& t : tests)
3211 auto const acct =
Account{t.acct};
3212 env.fund(t.fundXRP, acct);
3215 env(
trust(acct, USD(1000)));
3216 env(
trust(acct, EUR(1000)));
3219 if (t.fundUSD > USD(0))
3220 env(
pay(gw1, acct, t.fundUSD));
3221 if (t.fundEUR > EUR(0))
3222 env(
pay(gw2, acct, t.fundEUR));
3225 env(
offer(acct, USD(500), EUR(600)),
ter(t.firstOfferTec));
3229 int offerCount = t.firstOfferTec ==
tesSUCCESS ? 1 : 0;
3230 env.require(
owners(acct, 2 + offerCount));
3231 env.require(
balance(acct, t.fundUSD));
3232 env.require(
balance(acct, t.fundEUR));
3235 BEAST_EXPECT(acctOffers.size() == offerCount);
3236 for (
auto const& offerPtr : acctOffers)
3238 auto const&
offer = *offerPtr;
3239 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
3240 BEAST_EXPECT(
offer[sfTakerGets] == EUR(600));
3241 BEAST_EXPECT(
offer[sfTakerPays] == USD(500));
3244 env(
offer(acct, EUR(600), USD(500)),
ter(t.secondOfferTec));
3248 offerCount = t.secondOfferTec ==
tesSUCCESS ? 1 : offerCount;
3249 env.require(
owners(acct, 2 + offerCount));
3250 env.require(
balance(acct, t.fundUSD));
3251 env.require(
balance(acct, t.fundEUR));
3254 BEAST_EXPECT(acctOffers.size() == offerCount);
3255 for (
auto const& offerPtr : acctOffers)
3257 auto const&
offer = *offerPtr;
3258 BEAST_EXPECT(
offer[sfLedgerEntryType] == ltOFFER);
3259 if (
offer[sfSequence] == firstOfferSeq)
3261 BEAST_EXPECT(
offer[sfTakerGets] == EUR(600));
3262 BEAST_EXPECT(
offer[sfTakerPays] == USD(500));
3266 BEAST_EXPECT(
offer[sfTakerGets] == USD(500));
3267 BEAST_EXPECT(
offer[sfTakerPays] == EUR(600));
3745 using namespace jtx;
3747 Env env{*
this, features};
3748 auto const baseFee = env.current()->fees().base.drops();
3750 auto const gw =
Account(
"gw");
3751 auto const BTC = gw[
"BTC"];
3752 auto const USD = gw[
"USD"];
3753 auto const startXrpBalance =
XRP(4000000);
3755 env.fund(startXrpBalance, gw);
3758 env(
rate(gw, 1.25));
3784 TestData
const tests[]{
3786 {0, 0, 1, BTC(20), {{
"ann", 0,
drops(3900000'000000 - 4 * baseFee), BTC(20.0), USD(3000)}, {
"abe", 0,
drops(4100000'000000 - 3 * baseFee), BTC( 0), USD(750)}}},
3787 {0, 1, 0, BTC(20), {{
"bev", 0,
drops(4100000'000000 - 4 * baseFee), BTC( 7.5), USD(2000)}, {
"bob", 0,
drops(3900000'000000 - 3 * baseFee), BTC(10), USD( 0)}}},
3788 {0, 0, 0, BTC(20), {{
"cam", 0,
drops(4000000'000000 - 5 * baseFee), BTC(20.0), USD(2000)} }},
3789 {0, 1, 0, BTC( 5), {{
"deb", 1,
drops(4040000'000000 - 4 * baseFee), BTC( 0.0), USD(2000)}, {
"dan", 1,
drops(3960000'000000 - 3 * baseFee), BTC( 4), USD( 0)}}},
3793 for (
auto const& t : tests)
3795 Account const& self = t.actors[t.self].acct;
3796 Account const& leg0 = t.actors[t.leg0].acct;
3797 Account const& leg1 = t.actors[t.leg1].acct;
3799 for (
auto const& actor : t.actors)
3801 env.fund(
XRP(4000000), actor.acct);
3804 env(
trust(actor.acct, BTC(40)));
3805 env(
trust(actor.acct, USD(8000)));
3809 env(
pay(gw, self, t.btcStart));
3810 env(
pay(gw, self, USD(2000)));
3811 if (self.
id() != leg1.
id())
3812 env(
pay(gw, leg1, USD(2000)));
3826 env(
offer(self, USD(1000), BTC(10)));
3831 for (
auto const& actor : t.actors)
3837 actorOffers.begin(),
3839 return (*offer)[sfTakerGets].signum() == 0;
3841 BEAST_EXPECT(offerCount == actor.offers);
3843 env.require(
balance(actor.acct, actor.xrp));
3844 env.require(
balance(actor.acct, actor.btc));
3845 env.require(
balance(actor.acct, actor.usd));
4794 using namespace jtx;
4795 Env env(*
this, features);
4796 Account const issuer(
"issuer");
4799 auto const USD = issuer[
"USD"];
4800 auto const EUR = issuer[
"EUR"];
4803 env.
fund(
XRP(1'000), maker, taker);
4806 env.
trust(USD(1'000), maker, taker);
4807 env.
trust(EUR(1'000), maker, taker);
4810 env(
pay(issuer, maker, USD(1'000)));
4811 env(
pay(issuer, taker, USD(1'000)));
4812 env(
pay(issuer, maker, EUR(1'000)));
4815 auto makerUSDBalance = env.
balance(maker, USD).
value();
4816 auto takerUSDBalance = env.
balance(taker, USD).
value();
4817 auto makerEURBalance = env.
balance(maker, EUR).
value();
4818 auto takerEURBalance = env.
balance(taker, EUR).
value();
4826 env(
offer(maker,
XRP(100), USD(100)));
4832 makerXRPBalance -=
txfee(env, 1);
4833 takerXRPBalance -=
txfee(env, 1);
4836 makerUSDBalance -= USD(100);
4837 takerUSDBalance += USD(100);
4838 makerXRPBalance +=
XRP(100).value();
4839 takerXRPBalance -=
XRP(100).value();
4843 env(
offer(maker, USD(100),
XRP(100)));
4849 makerXRPBalance -=
txfee(env, 1);
4850 takerXRPBalance -=
txfee(env, 1);
4853 makerUSDBalance += USD(100);
4854 takerUSDBalance -= USD(100);
4855 makerXRPBalance -=
XRP(100).value();
4856 takerXRPBalance +=
XRP(100).value();
4860 env(
offer(maker, USD(100), EUR(100)));
4866 makerXRPBalance -=
txfee(env, 1);
4867 takerXRPBalance -=
txfee(env, 1);
4870 makerUSDBalance += USD(100);
4871 takerUSDBalance -= USD(100);
4872 makerEURBalance -= EUR(100);
4873 takerEURBalance += EUR(100);
4880 env(
offer(maker,
XRP(101), USD(101)));
4886 makerUSDBalance -= USD(101);
4887 takerUSDBalance += USD(101);
4888 makerXRPBalance +=
XRP(101).value() -
txfee(env, 1);
4889 takerXRPBalance -=
XRP(101).value() +
txfee(env, 1);
4892 env(
offer(maker, USD(101),
XRP(101)));
4898 makerUSDBalance += USD(101);
4899 takerUSDBalance -= USD(101);
4900 makerXRPBalance -=
XRP(101).value() +
txfee(env, 1);
4901 takerXRPBalance +=
XRP(101).value() -
txfee(env, 1);
4904 env(
offer(maker, USD(101), EUR(101)));
4910 makerUSDBalance += USD(101);
4911 takerUSDBalance -= USD(101);
4912 makerEURBalance -= EUR(101);
4913 takerEURBalance += EUR(101);
4914 makerXRPBalance -=
txfee(env, 1);
4915 takerXRPBalance -=
txfee(env, 1);
4922 env(
offer(maker,
XRP(100), USD(100)));
4928 makerXRPBalance -=
txfee(env, 1);
4929 takerXRPBalance -=
txfee(env, 1);
4932 env(
offer(maker, USD(100),
XRP(100)));
4938 makerXRPBalance -=
txfee(env, 1);
4939 takerXRPBalance -=
txfee(env, 1);
4942 env(
offer(maker, USD(100), EUR(100)));
4948 makerXRPBalance -=
txfee(env, 1);
4949 takerXRPBalance -=
txfee(env, 1);
4954 env.
balance(maker, USD) == makerUSDBalance && env.
balance(taker, USD) == takerUSDBalance &&
4955 env.
balance(maker, EUR) == makerEURBalance && env.
balance(taker, EUR) == takerEURBalance &&