3014        using namespace jtx;
 
 3021            [&](
AMM& ammAlice, 
Env& env) {
 
 3022                ammAlice.
deposit(carol, 1'000'000);
 
 3023                env(ammAlice.
bid({.account = carol, .bidMin = 110}));
 
 3036            [&](
AMM& ammAlice, 
Env& env) {
 
 3037                ammAlice.
deposit(carol, 1'000'000);
 
 3040                    {.account = carol, .bidMin = 110, .bidMax = 110}));
 
 3046                    {.account = alice, .bidMin = 180, .bidMax = 200}));
 
 3049                    XRP(11'000), USD(11'000), 
IOUAmount{10'999'814'5, -1}));
 
 3058            [&](
AMM& ammAlice, 
Env& env) {
 
 3059                ammAlice.
deposit(carol, 1'000'000);
 
 3061                env(ammAlice.
bid({.account = carol, .bidMin = 110}));
 
 3064                fund(env, gw, {bob}, {USD(10'000)}, Fund::Acct);
 
 3065                ammAlice.
deposit(bob, 1'000'000);
 
 3067                env(ammAlice.
bid({.account = bob}));
 
 3078                env(ammAlice.
bid({.account = carol, .bidMax = 600}));
 
 3092                    {.account = carol, .bidMin = 100, .bidMax = 600}));
 
 3103            [&](
AMM& ammAlice, 
Env& env) {
 
 3104                ammAlice.
deposit(carol, 1'000'000);
 
 3106                fund(env, gw, {bob}, {USD(10'000)}, Fund::Acct);
 
 3107                ammAlice.
deposit(bob, 1'000'000);
 
 3108                if (!features[fixAMMv1_3])
 
 3118                env(ammAlice.
bid({.account = carol, .bidMin = 110})).
close();
 
 3122                env(ammAlice.
bid({.account = bob}));
 
 3128                env(ammAlice.
bid({.account = carol}));
 
 3134                env(ammAlice.
bid({.account = bob}));
 
 3143                env(ammAlice.
bid({.account = carol, .bidMin = 110})).
close();
 
 3147                if (!features[fixAMMv1_3])
 
 3168            [&](
AMM& ammAlice, 
Env& env) {
 
 3171                fund(env, gw, {bob, dan, ed}, {USD(20'000)}, Fund::Acct);
 
 3172                ammAlice.
deposit(bob, 1'000'000);
 
 3173                ammAlice.
deposit(ed, 1'000'000);
 
 3174                ammAlice.
deposit(carol, 500'000);
 
 3175                ammAlice.
deposit(dan, 500'000);
 
 3180                    .authAccounts = {bob, ed},
 
 3182                auto const slotPrice = 
IOUAmount{5'200};
 
 3183                ammTokens -= slotPrice;
 
 3185                if (!features[fixAMMv1_3])
 
 3187                        XRP(13'000), USD(13'000), ammTokens));
 
 3190                        XRPAmount{13'000'000'003}, USD(13'000), ammTokens));
 
 3192                for (
int i = 0; i < 10; ++i)
 
 3194                    auto tokens = ammAlice.
deposit(carol, USD(100));
 
 3195                    ammAlice.
withdraw(carol, tokens, USD(0));
 
 3196                    tokens = ammAlice.
deposit(bob, USD(100));
 
 3197                    ammAlice.
withdraw(bob, tokens, USD(0));
 
 3198                    tokens = ammAlice.
deposit(ed, USD(100));
 
 3199                    ammAlice.
withdraw(ed, tokens, USD(0));
 
 3202                if (!features[fixAMMv1_1])
 
 3206                        STAmount(USD, UINT64_C(29'499'00572620545), -11));
 
 3209                        STAmount(USD, UINT64_C(18'999'00572616195), -11));
 
 3212                        STAmount(USD, UINT64_C(18'999'00572611841), -11));
 
 3216                        STAmount(USD, UINT64_C(13'002'98282151419), -11),
 
 3223                        STAmount(USD, UINT64_C(29'499'00572620544), -11));
 
 3226                        STAmount(USD, UINT64_C(18'999'00572616194), -11));
 
 3229                        STAmount(USD, UINT64_C(18'999'0057261184), -10));
 
 3231                    if (!features[fixAMMv1_3])
 
 3234                            STAmount(USD, UINT64_C(13'002'98282151422), -11),
 
 3239                            STAmount(USD, UINT64_C(13'002'98282151422), -11),
 
 3244                for (
int i = 0; i < 10; ++i)
 
 3246                    auto const tokens = ammAlice.
deposit(dan, USD(100));
 
 3247                    ammAlice.
withdraw(dan, tokens, USD(0));
 
 3252                if (!features[fixAMMv1_1])
 
 3256                        STAmount(USD, UINT64_C(19'490'056722744), -9));
 
 3260                        STAmount{USD, UINT64_C(13'012'92609877019), -11},
 
 3263                    ammAlice.
deposit(carol, USD(100));
 
 3267                        STAmount{USD, UINT64_C(13'112'92609877019), -11},
 
 3269                    env(pay(carol, bob, USD(100)),
 
 3277                        STAmount{USD, UINT64_C(13'012'92609877019), -11},
 
 3282                    if (!features[fixAMMv1_3])
 
 3285                            STAmount(USD, UINT64_C(19'490'05672274399), -11));
 
 3289                            STAmount(USD, UINT64_C(19'490'05672274398), -11));
 
 3291                    if (!features[fixAMMv1_3])
 
 3294                            STAmount{USD, UINT64_C(13'012'92609877023), -11},
 
 3299                            STAmount{USD, UINT64_C(13'012'92609877024), -11},
 
 3302                    ammAlice.
deposit(carol, USD(100));
 
 3304                    if (!features[fixAMMv1_3])
 
 3307                            STAmount{USD, UINT64_C(13'112'92609877023), -11},
 
 3312                            STAmount{USD, UINT64_C(13'112'92609877024), -11},
 
 3314                    env(pay(carol, bob, USD(100)),
 
 3320                    if (!features[fixAMMv1_3])
 
 3323                            STAmount{USD, UINT64_C(13'012'92609877023), -11},
 
 3328                            STAmount{USD, UINT64_C(13'012'92609877024), -11},
 
 3337                if (!features[fixAMMv1_1] && !features[fixAMMv1_3])
 
 3341                        STAmount{USD, UINT64_C(13'114'03663047264), -11},
 
 3344                else if (features[fixAMMv1_1] && !features[fixAMMv1_3])
 
 3348                        STAmount{USD, UINT64_C(13'114'03663047269), -11},
 
 3355                        STAmount{USD, UINT64_C(13'114'03663044937), -11},
 
 3362                if (!features[fixAMMv1_1])
 
 3365                        STAmount(USD, UINT64_C(29'399'00572620545), -11));
 
 3366                else if (!features[fixAMMv1_3])
 
 3369                        STAmount(USD, UINT64_C(29'399'00572620544), -11));
 
 3371                for (
int i = 0; i < 10; ++i)
 
 3373                    auto const tokens = ammAlice.
deposit(carol, USD(100));
 
 3374                    ammAlice.
withdraw(carol, tokens, USD(0));
 
 3378                if (!features[fixAMMv1_1] && !features[fixAMMv1_3])
 
 3382                        STAmount(USD, UINT64_C(29'389'06197177128), -11));
 
 3385                        STAmount{USD, UINT64_C(13'123'98038490681), -11},
 
 3388                else if (features[fixAMMv1_1] && !features[fixAMMv1_3])
 
 3392                        STAmount(USD, UINT64_C(29'389'06197177124), -11));
 
 3395                        STAmount{USD, UINT64_C(13'123'98038490689), -11},
 
 3402                        STAmount(USD, UINT64_C(29'389'06197177129), -11));
 
 3405                        STAmount{USD, UINT64_C(13'123'98038488352), -11},
 
 3413                if (!features[fixAMMv1_1] && !features[fixAMMv1_3])
 
 3417                        STAmount{USD, UINT64_C(13'023'98038490681), -11},
 
 3420                else if (features[fixAMMv1_1] && !features[fixAMMv1_3])
 
 3424                        STAmount{USD, UINT64_C(13'023'98038490689), -11},
 
 3431                        STAmount{USD, UINT64_C(13'023'98038488352), -11},
 
 3442            [&](AMM& ammAlice, Env& env) {
 
 3445                    Number{STAmount::cMinValue, STAmount::cMinOffset};
 
 3447                    {.account = alice, .bidMin = IOUAmount{tiny}}));
 
 3450                BEAST_EXPECT(ammAlice.expectAuctionSlot(0, 0, IOUAmount{tiny}));
 
 3452                BEAST_EXPECT(ammAlice.expectBalances(
 
 3453                    XRP(10'000), USD(10'000), ammAlice.tokens()));
 
 3458                        IOUAmount{STAmount::cMinValue, STAmount::cMinOffset},
 
 3461                BEAST_EXPECT(ammAlice.expectAuctionSlot(
 
 3462                    0, 0, IOUAmount{tiny * Number{105, -2}}));
 
 3465                BEAST_EXPECT(ammAlice.expectBalances(
 
 3466                    XRP(10'000), USD(10'000), ammAlice.tokens()));
 
 3475            [&](AMM& ammAlice, Env& env) {
 
 3478                    .bidMin = IOUAmount{100},
 
 3479                    .authAccounts = {carol},
 
 3481                BEAST_EXPECT(ammAlice.expectAuctionSlot({carol}));
 
 3482                env(ammAlice.bid({.account = alice, .bidMin = IOUAmount{100}}));
 
 3483                BEAST_EXPECT(ammAlice.expectAuctionSlot({}));
 
 3486                fund(env, {bob, dan}, 
XRP(1'000));
 
 3489                    .bidMin = IOUAmount{100},
 
 3490                    .authAccounts = {bob, dan},
 
 3492                BEAST_EXPECT(ammAlice.expectAuctionSlot({bob, dan}));
 
 3501            Env env(*
this, features);
 
 3502            fund(env, gw, {alice, bob}, 
XRP(2'000), {USD(2'000)});
 
 3503            AMM amm(env, gw, 
XRP(1'000), USD(1'010), 
false, 1'000);
 
 3504            auto const lpIssue = 
amm.lptIssue();
 
 3505            env.trust(STAmount{lpIssue, 500}, alice);
 
 3506            env.trust(STAmount{lpIssue, 50}, bob);
 
 3507            env(
pay(gw, alice, STAmount{lpIssue, 500}));
 
 3508            env(
pay(gw, bob, STAmount{lpIssue, 50}));
 
 3510            env(
amm.bid({.account = alice, .bidMin = 500}));
 
 3511            BEAST_EXPECT(
amm.expectAuctionSlot(100, 0, IOUAmount{500}));
 
 3512            BEAST_EXPECT(
expectHolding(env, alice, STAmount{lpIssue, 0}));
 
 3515            env(
pay(alice, bob, USD(10)), path(~USD), sendmax(
XRP(11)));
 
 3516            BEAST_EXPECT(
amm.expectBalances(
 
 3517                XRPAmount{1'010'010'011},
 
 3519                IOUAmount{1'004'487'562112089, -9}));
 
 3521            env(
pay(bob, alice, 
XRP(10)), path(~XRP), sendmax(USD(11)));
 
 3522            if (!features[fixAMMv1_1])
 
 3524                BEAST_EXPECT(
amm.expectBalances(
 
 3525                    XRPAmount{1'000'010'011},
 
 3526                    STAmount{USD, UINT64_C(1'010'10090898081), -11},
 
 3527                    IOUAmount{1'004'487'562112089, -9}));
 
 3531                BEAST_EXPECT(
amm.expectBalances(
 
 3532                    XRPAmount{1'000'010'011},
 
 3533                    STAmount{USD, UINT64_C(1'010'100908980811), -12},
 
 3534                    IOUAmount{1'004'487'562112089, -9}));
 
 3540            Env env(*
this, features);
 
 3541            auto const baseFee = env.current()->fees().base;
 
 3543            fund(env, gw, {alice, bob}, 
XRP(2'000), {USD(2'000)});
 
 3544            AMM amm(env, gw, 
XRP(1'000), USD(1'010), 
false, 1'000);
 
 3548                auto jtx = env.jt(tx, seq(1), fee(baseFee));
 
 3549                env.app().config().features.erase(featureAMM);
 
 3550                PreflightContext pfctx(
 
 3553                    env.current()->rules(),
 
 3556                auto pf = Transactor::invokePreflight<AMMBid>(pfctx);
 
 3557                BEAST_EXPECT(pf == temDISABLED);
 
 3558                env.app().config().features.insert(featureAMM);
 
 3562                auto jtx = env.jt(tx, seq(1), fee(baseFee));
 
 3563                jtx.jv[
"TxnSignature"] = 
"deadbeef";
 
 3564                jtx.stx = env.ust(jtx);
 
 3565                PreflightContext pfctx(
 
 3568                    env.current()->rules(),
 
 3571                auto pf = Transactor::invokePreflight<AMMBid>(pfctx);
 
 3572                BEAST_EXPECT(pf != tesSUCCESS);
 
 3576                auto jtx = env.jt(tx, seq(1), fee(baseFee));
 
 3577                jtx.jv[
"Asset2"][
"currency"] = 
"XRP";
 
 3578                jtx.jv[
"Asset2"].removeMember(
"issuer");
 
 3579                jtx.stx = env.ust(jtx);
 
 3580                PreflightContext pfctx(
 
 3583                    env.current()->rules(),
 
 3586                auto pf = Transactor::invokePreflight<AMMBid>(pfctx);
 
 3587                BEAST_EXPECT(pf == temBAD_AMM_TOKENS);
 
 
 3758        testcase(
"Basic Payment");
 
 3759        using namespace jtx;
 
 3764            [&](
AMM& ammAlice, 
Env& env) {
 
 3765                env.
fund(jtx::XRP(30'000), bob);
 
 3767                env(pay(bob, carol, USD(100)),
 
 3773                    XRP(10'100), USD(10'000), ammAlice.
tokens()));
 
 3778                    env, bob, 
XRP(30'000) - 
XRP(100) - 
txfee(env, 1)));
 
 3780            {{
XRP(10'000), USD(10'100)}},
 
 3787            [&](
AMM& ammAlice, 
Env& env) {
 
 3788                env.
fund(jtx::XRP(30'000), bob);
 
 3790                env(pay(bob, carol, USD(100)), 
sendmax(
XRP(100)));
 
 3793                    XRP(10'100), USD(10'000), ammAlice.
tokens()));
 
 3798                    env, bob, 
XRP(30'000) - 
XRP(100) - 
txfee(env, 1)));
 
 3800            {{
XRP(10'000), USD(10'100)}},
 
 3808            [&](
AMM& ammAlice, 
Env& env) {
 
 3809                env.
fund(jtx::XRP(30'000), bob);
 
 3814                    XRP(10'100), USD(10'000), ammAlice.
tokens()));
 
 3819                    env, bob, 
XRP(30'000) - 
XRP(100) - 
txfee(env, 1)));
 
 3821            {{
XRP(10'000), USD(10'100)}},
 
 3828            [&](
AMM& ammAlice, 
Env& env) {
 
 3829                env.
fund(jtx::XRP(30'000), bob);
 
 3833                env(pay(bob, carol, USD(100)),
 
 3840                    XRP(10'010), USD(10'000), ammAlice.
tokens()));
 
 3846                    env, bob, 
XRP(30'000) - 
XRP(10) - 
txfee(env, 1)));
 
 3850                env(pay(bob, carol, USD(100)),
 
 3858            {{
XRP(10'000), USD(10'010)}},
 
 3865            [&](
AMM& ammAlice, 
Env& env) {
 
 3868                env.
fund(jtx::XRP(30'000), bob);
 
 3873                env(pay(bob, carol, USD(100)),
 
 3880                    XRP(10'010), USD(10'000), ammAlice.
tokens()));
 
 3885                    STAmount{USD, UINT64_C(30'009'09090909091), -11}));
 
 3887                    env, bob, 
XRP(30'000) - 
XRP(10) - 
txfee(env, 1)));
 
 3889            {{
XRP(10'000), USD(10'010)}},
 
 3896            [&](
AMM& ammAlice, 
Env& env) {
 
 3897                env.
fund(jtx::XRP(30'000), bob);
 
 3899                env(pay(bob, carol, USD(100)),
 
 3905            {{
XRP(10'000), USD(10'000)}},
 
 3915            Env env(*
this, features);
 
 3917                env, gw, {alice, carol}, {USD(30'000), EUR(30'000)}, Fund::All);
 
 3921            auto ammEUR_XRP = 
AMM(env, alice, 
XRP(10'000), EUR(10'000));
 
 3922            auto ammUSD_EUR = 
AMM(env, alice, EUR(10'000), USD(10'000));
 
 3925            env(pay(bob, carol, USD(100)),
 
 3930            BEAST_EXPECT(ammEUR_XRP.expectBalances(
 
 3932                STAmount(EUR, UINT64_C(9'970'007498125468), -12),
 
 3933                ammEUR_XRP.tokens()));
 
 3934            if (!features[fixAMMv1_1])
 
 3936                BEAST_EXPECT(ammUSD_EUR.expectBalances(
 
 3937                    STAmount(USD, UINT64_C(9'970'097277662122), -12),
 
 3938                    STAmount(EUR, UINT64_C(10'029'99250187452), -11),
 
 3939                    ammUSD_EUR.tokens()));
 
 3942                Amounts 
const expectedAmounts =
 
 3943                    env.
closed()->rules().enabled(fixReducedOffersV2)
 
 3944                    ? Amounts{
XRPAmount(30'201'749), 
STAmount(USD, UINT64_C(29'90272233787816), -14)}
 
 3947                          STAmount(USD, UINT64_C(29'90272233787818), -14)};
 
 3949                BEAST_EXPECT(
expectOffers(env, alice, 1, {{expectedAmounts}}));
 
 3953                BEAST_EXPECT(ammUSD_EUR.expectBalances(
 
 3954                    STAmount(USD, UINT64_C(9'970'097277662172), -12),
 
 3955                    STAmount(EUR, UINT64_C(10'029'99250187452), -11),
 
 3956                    ammUSD_EUR.tokens()));
 
 3959                Amounts 
const expectedAmounts =
 
 3960                    env.
closed()->rules().enabled(fixReducedOffersV2)
 
 3961                    ? Amounts{
XRPAmount(30'201'749), 
STAmount(USD, UINT64_C(29'90272233782839), -14)}
 
 3964                          STAmount(USD, UINT64_C(29'90272233782840), -14)};
 
 3966                BEAST_EXPECT(
expectOffers(env, alice, 1, {{expectedAmounts}}));
 
 3982            [&](
AMM& ammAlice, 
Env& env) {
 
 3985                env.
trust(EUR(2'000), alice);
 
 3987                env(pay(gw, alice, EUR(1'000)));
 
 3992                env(pay(bob, carol, USD(100)),
 
 3999                    STAmount(USD, UINT64_C(9'950'01249687578), -11),
 
 4007                          STAmount(EUR, UINT64_C(49'98750312422), -11)},
 
 4009                          STAmount(EUR, UINT64_C(49'98750312422), -11),
 
 4010                          STAmount(USD, UINT64_C(49'98750312422), -11)}}}));
 
 4015                    STAmount{USD, UINT64_C(30'099'99999999999), -11}));
 
 4032            [&](
AMM& ammAlice, 
Env& env) {
 
 4033                fund(env, gw, {bob}, {USD(100)}, Fund::Acct);
 
 4037                env(pay(alice, carol, USD(200)),
 
 4041                if (!features[fixAMMv1_1])
 
 4044                        XRP(10'100), USD(10'000), ammAlice.
tokens()));
 
 4052                        STAmount(USD, UINT64_C(10'000'00000000001), -11),
 
 4057                        STAmount(USD, UINT64_C(30'199'99999999999), -11)));
 
 4065                        ammCrtFee(env) - 
txfee(env, 1)));
 
 4068            {{
XRP(10'000), USD(10'100)}},
 
 4077            Env env(*
this, features);
 
 4078            fund(env, gw, {alice, bob, carol}, 
XRP(20'000), {USD(2'000)});
 
 4082            AMM ammAlice(env, alice, 
XRP(1'000), USD(1'050));
 
 4083            env(pay(alice, carol, USD(200)),
 
 4088                XRP(1'050), USD(1'000), ammAlice.
tokens()));
 
 4095            [&](
AMM& ammAlice, 
Env& env) {
 
 4096                fund(env, gw, {bob}, {USD(1'000)}, Fund::Acct);
 
 4098                env(offer(bob, USD(100), 
XRP(100)));
 
 4101                    XRP(10'100), USD(10'000), ammAlice.
tokens()));
 
 4106                    env, bob, 
XRP(30'000) - 
XRP(100) - 
txfee(env, 1)));
 
 4109            {{
XRP(10'000), USD(10'100)}},
 
 4117            [&](
AMM& ammAlice, 
Env& env) {
 
 4118                env(rate(gw, 1.25));
 
 4124                env(offer(carol, EUR(100), GBP(100)));
 
 4128                    GBP(1'100), EUR(1'000), ammAlice.
tokens()));
 
 4135            {{GBP(1'000), EUR(1'100)}},
 
 4141            [&](
AMM& amm, 
Env& env) {
 
 4142                env(rate(gw, 1.001));
 
 4144                env(offer(carol, 
XRP(100), USD(55)));
 
 4146                if (!features[fixAMMv1_1])
 
 4156                        amm.expectBalances(
XRP(1'000), USD(500), amm.tokens()));
 
 4158                        env, carol, 1, {{Amounts{
XRP(100), USD(55)}}}));
 
 4169                    BEAST_EXPECT(amm.expectBalances(
 
 4171                        STAmount{USD, UINT64_C(550'000000055), -9},
 
 4180                            STAmount{USD, 4'99999995, -8}}}}));
 
 4184                        STAmount(USD, UINT64_C(29'949'94999999494), -11));
 
 4187            {{
XRP(1'000), USD(500)}},
 
 4192            [&](
AMM& amm, 
Env& env) {
 
 4193                env(rate(gw, 1.001));
 
 4195                env(offer(carol, 
XRP(10), USD(5.5)));
 
 4197                if (!features[fixAMMv1_1])
 
 4199                    BEAST_EXPECT(amm.expectBalances(
 
 4201                        STAmount{USD, UINT64_C(505'050505050505), -12},
 
 4207                    BEAST_EXPECT(amm.expectBalances(
 
 4209                        STAmount{USD, UINT64_C(505'0505050505051), -13},
 
 4214            {{
XRP(1'000), USD(500)}},
 
 4220            [&](
AMM& ammAlice, 
Env& env) {
 
 4227                    {GBP(2'000), EUR(2'000)},
 
 4229                env(rate(gw, 1.25));
 
 4240                env(offer(carol, EUR(100), GBP(100)));
 
 4242                if (!features[fixAMMv1_1])
 
 4251                        STAmount{GBP, UINT64_C(1'037'06583722133), -11},
 
 4252                        STAmount{EUR, UINT64_C(1'060'684828792831), -12},
 
 4260                            STAmount{EUR, UINT64_C(50'684828792831), -12},
 
 4261                            STAmount{GBP, UINT64_C(50'684828792831), -12}}}));
 
 4273                        STAmount{GBP, UINT64_C(29'941'16770347333), -11}));
 
 4278                        STAmount{EUR, UINT64_C(30'049'31517120716), -11}));
 
 4290                        STAmount{GBP, UINT64_C(1'060'684828792832), -12},
 
 4291                        STAmount{EUR, UINT64_C(1'037'06583722134), -11},
 
 4299                            STAmount{EUR, UINT64_C(27'06583722134028), -14},
 
 4300                            STAmount{GBP, UINT64_C(27'06583722134028), -14}}}));
 
 4312                        STAmount{GBP, UINT64_C(29'911'64396400896), -11}));
 
 4317                        STAmount{EUR, UINT64_C(30'072'93416277865), -11}));
 
 4324            {{GBP(1'000), EUR(1'100)}},
 
 4337            [&](
AMM& ammAlice, 
Env& env) {
 
 4338                fund(env, gw, {bob}, {GBP(200), EUR(200)}, Fund::Acct);
 
 4339                env(rate(gw, 1.25));
 
 4341                env(pay(bob, carol, EUR(100)),
 
 4347                    GBP(1'100), EUR(1'000), ammAlice.
tokens()));
 
 4351            {{GBP(1'000), EUR(1'100)}},
 
 4368            [&](
AMM& ammAlice, 
Env& env) {
 
 4371                auto const CAN = gw[
"CAN"];
 
 4372                fund(env, gw, {dan}, {CAN(200), GBP(200)}, Fund::Acct);
 
 4373                fund(env, gw, {ed}, {EUR(200), USD(200)}, Fund::Acct);
 
 4374                fund(env, gw, {bob}, {CAN(195.3125)}, Fund::Acct);
 
 4375                env(trust(carol, USD(100)));
 
 4376                env(rate(gw, 1.25));
 
 4378                env(offer(dan, CAN(200), GBP(200)));
 
 4379                env(offer(ed, EUR(200), USD(200)));
 
 4381                env(pay(bob, carol, USD(100)),
 
 4382                    path(~GBP, ~EUR, ~USD),
 
 4387                BEAST_EXPECT(
expectHolding(env, dan, CAN(356.25), GBP(43.75)));
 
 4389                    GBP(10'125), EUR(10'000), ammAlice.
tokens()));
 
 4393            {{GBP(10'000), EUR(10'125)}},
 
 4400            [&](
AMM& ammAlice, 
Env& env) {
 
 4401                env(pay(alice, carol, USD(99.99)),
 
 4406                env(pay(alice, carol, USD(100)),
 
 4411                env(pay(alice, carol, 
XRP(100)),
 
 4422            {{
XRP(100), USD(100)}},
 
 4429            Env env(*
this, features);
 
 4430            auto const ETH = gw[
"ETH"];
 
 4436                {EUR(50'000), BTC(50'000), ETH(50'000), USD(50'000)});
 
 4437            fund(env, gw, {carol, bob}, 
XRP(1'000), {USD(200)}, Fund::Acct);
 
 4438            AMM xrp_eur(env, alice, 
XRP(10'100), EUR(10'000));
 
 4439            AMM eur_btc(env, alice, EUR(10'000), BTC(10'200));
 
 4440            AMM btc_usd(env, alice, BTC(10'100), USD(10'000));
 
 4441            AMM xrp_usd(env, alice, 
XRP(10'150), USD(10'200));
 
 4442            AMM xrp_eth(env, alice, 
XRP(10'000), ETH(10'100));
 
 4443            AMM eth_eur(env, alice, ETH(10'900), EUR(11'000));
 
 4444            AMM eur_usd(env, alice, EUR(10'100), USD(10'000));
 
 4445            env(pay(bob, carol, USD(100)),
 
 4446                path(~EUR, ~BTC, ~USD),
 
 4448                path(~ETH, ~EUR, ~USD),
 
 4450            if (!features[fixAMMv1_1])
 
 4456                    STAmount{ETH, UINT64_C(10'073'65779244494), -11},
 
 4459                    STAmount{ETH, UINT64_C(10'926'34220755506), -11},
 
 4460                    STAmount{EUR, UINT64_C(10'973'54232078752), -11},
 
 4463                    STAmount{EUR, UINT64_C(10'126'45767921248), -11},
 
 4464                    STAmount{USD, UINT64_C(9'973'93151712086), -11},
 
 4470                    STAmount{USD, UINT64_C(10'126'06848287914), -11},
 
 4477                    STAmount{ETH, UINT64_C(10'073'65779244461), -11},
 
 4480                    STAmount{ETH, UINT64_C(10'926'34220755539), -11},
 
 4481                    STAmount{EUR, UINT64_C(10'973'5423207872), -10},
 
 4484                    STAmount{EUR, UINT64_C(10'126'4576792128), -10},
 
 4485                    STAmount{USD, UINT64_C(9'973'93151712057), -11},
 
 4491                    STAmount{USD, UINT64_C(10'126'06848287943), -11},
 
 4501            BEAST_EXPECT(xrp_eur.expectBalances(
 
 4502                XRP(10'100), EUR(10'000), xrp_eur.tokens()));
 
 4504                EUR(10'000), BTC(10'200), eur_btc.
tokens()));
 
 4506                BTC(10'100), USD(10'000), btc_usd.
tokens()));
 
 4513            Env env(*
this, features);
 
 4514            auto const ETH = gw[
"ETH"];
 
 4520                {EUR(50'000), BTC(50'000), ETH(50'000), USD(50'000)});
 
 4521            fund(env, gw, {carol, bob}, 
XRP(1000), {USD(200)}, Fund::Acct);
 
 4522            AMM xrp_eur(env, alice, 
XRP(10'100), EUR(10'000));
 
 4523            AMM eur_btc(env, alice, EUR(10'000), BTC(10'200));
 
 4524            AMM btc_usd(env, alice, BTC(10'100), USD(10'000));
 
 4525            AMM xrp_eth(env, alice, 
XRP(10'000), ETH(10'100));
 
 4526            AMM eth_eur(env, alice, ETH(10'900), EUR(11'000));
 
 4527            env(pay(bob, carol, USD(100)),
 
 4528                path(~EUR, ~BTC, ~USD),
 
 4529                path(~ETH, ~EUR, ~BTC, ~USD),
 
 4531            if (!features[fixAMMv1_1])
 
 4535                BEAST_EXPECT(xrp_eur.expectBalances(
 
 4537                    STAmount{EUR, UINT64_C(9'981'544436337968), -12},
 
 4540                    STAmount{EUR, UINT64_C(10'101'16096785173), -11},
 
 4541                    STAmount{BTC, UINT64_C(10'097'91426968066), -11},
 
 4544                    STAmount{BTC, UINT64_C(10'202'08573031934), -11},
 
 4549                    STAmount{ETH, UINT64_C(10'017'41072778012), -11},
 
 4552                    STAmount{ETH, UINT64_C(10'982'58927221988), -11},
 
 4553                    STAmount{EUR, UINT64_C(10'917'2945958103), -10},
 
 4558                BEAST_EXPECT(xrp_eur.expectBalances(
 
 4560                    STAmount{EUR, UINT64_C(9'981'544436337923), -12},
 
 4563                    STAmount{EUR, UINT64_C(10'101'16096785188), -11},
 
 4564                    STAmount{BTC, UINT64_C(10'097'91426968059), -11},
 
 4567                    STAmount{BTC, UINT64_C(10'202'08573031941), -11},
 
 4572                    STAmount{ETH, UINT64_C(10'017'41072777996), -11},
 
 4575                    STAmount{ETH, UINT64_C(10'982'58927222004), -11},
 
 4576                    STAmount{EUR, UINT64_C(10'917'2945958102), -10},
 
 4585            [&](
AMM& ammAlice, 
Env& env) {
 
 4587                fund(env, gw, {bob}, {EUR(400)}, Fund::IOUOnly);
 
 4588                env(trust(alice, EUR(200)));
 
 4589                for (
int i = 0; i < 30; ++i)
 
 4590                    env(offer(alice, EUR(1.0 + 0.01 * i), 
XRP(1)));
 
 4593                env(offer(alice, EUR(140), 
XRP(100)));
 
 4594                env(pay(bob, carol, USD(100)),
 
 4598                if (!features[fixAMMv1_1])
 
 4603                        STAmount{USD, UINT64_C(9'970'089730807577), -12},
 
 4608                        STAmount{USD, UINT64_C(30'029'91026919241), -11}));
 
 4614                        STAmount{USD, UINT64_C(9'970'089730807827), -12},
 
 4619                        STAmount{USD, UINT64_C(30'029'91026919217), -11}));
 
 4630            [&](
AMM& ammAlice, 
Env& env) {
 
 4632                fund(env, gw, {bob}, {EUR(400)}, Fund::IOUOnly);
 
 4633                env(trust(alice, EUR(200)));
 
 4634                for (
int i = 0; i < 29; ++i)
 
 4635                    env(offer(alice, EUR(1.0 + 0.01 * i), 
XRP(1)));
 
 4638                env(offer(alice, EUR(140), 
XRP(100)));
 
 4639                env(pay(bob, carol, USD(100)),
 
 4645                if (!features[fixAMMv1_1])
 
 4651                        STAmount{USD, UINT64_C(30'099'99999999999), -11}));
 
 4661                    {{{
STAmount{EUR, UINT64_C(39'1858572), -7},
 
 4672            Env env(*
this, features);
 
 4673            fund(env, gw, {alice, carol, bob}, 
XRP(30'000), {USD(30'000)});
 
 4674            env(offer(bob, 
XRP(100), USD(100.001)));
 
 4675            AMM ammAlice(env, alice, 
XRP(10'000), USD(10'100));
 
 4676            env(offer(carol, USD(100), 
XRP(100)));
 
 4677            if (!features[fixAMMv1_1])
 
 4681                    STAmount{USD, UINT64_C(10'049'92586949302), -11},
 
 4688                       STAmount{USD, UINT64_C(50'07513050698), -11}}}}));
 
 4694                    STAmount{USD, UINT64_C(10'049'92587049303), -11},
 
 4701                       STAmount{USD, UINT64_C(50'07512950697), -11}}}}));
 
 4708            [&](
AMM& ammAlice, 
Env& env) {
 
 4712                env(pay(alice, carol, USD(1)),
 
 
 5008        testcase(
"Trading Fee");
 
 5009        using namespace jtx;
 
 5013            [&](
AMM& ammAlice, 
Env& env) {
 
 5015                ammAlice.
deposit(carol, USD(3'000));
 
 5021                ammAlice.
vote(alice, 1'000);
 
 5025                ammAlice.
deposit(carol, USD(3'000));
 
 5027                    carol, 
IOUAmount{994'981155689671, -12}));
 
 5030                ammAlice.
vote(alice, 0);
 
 5036                    STAmount{USD, UINT64_C(29'994'96220068281), -11}));
 
 5038            {{USD(1'000), EUR(1'000)}},
 
 5046            [&](
AMM& ammAlice, 
Env& env) {
 
 5048                auto tokensFee = ammAlice.
deposit(
 
 5052                ammAlice.
vote(alice, 0);
 
 5054                auto const tokensNoFee = ammAlice.
deposit(carol, deposit);
 
 5057                BEAST_EXPECT(tokensFee == 
IOUAmount(485'636'0611129, -7));
 
 5058                BEAST_EXPECT(tokensNoFee == 
IOUAmount(487'644'85901109, -8));
 
 5068            [&](
AMM& ammAlice, 
Env& env) {
 
 5070                auto const tokensFee = ammAlice.
deposit(
 
 5074                ammAlice.
vote(alice, 0);
 
 5076                auto const tokensNoFee = ammAlice.
deposit(carol, deposit);
 
 5079                BEAST_EXPECT(tokensFee == 
IOUAmount(98'000'00000002, -8));
 
 5080                BEAST_EXPECT(tokensNoFee == 
IOUAmount(98'475'81871545, -8));
 
 5089            [&](
AMM& ammAlice, 
Env& env) {
 
 5091                ammAlice.
deposit(carol, USD(3'000));
 
 5096                ammAlice.
vote(alice, 1'000);
 
 5103                    STAmount{USD, UINT64_C(29'994'97487437186), -11}));
 
 5105            {{USD(1'000), EUR(1'000)}},
 
 5112            [&](
AMM& ammAlice, 
Env& env) {
 
 5113                ammAlice.
deposit(carol, 1'000'000);
 
 5114                auto const tokensFee = ammAlice.
withdraw(
 
 5117                auto const balanceAfterWithdraw = [&]() {
 
 5118                    if (!features[fixAMMv1_1] && !features[fixAMMv1_3])
 
 5119                        return STAmount(USD, UINT64_C(30'443'43891402715), -11);
 
 5120                    else if (features[fixAMMv1_1] && !features[fixAMMv1_3])
 
 5121                        return STAmount(USD, UINT64_C(30'443'43891402714), -11);
 
 5123                        return STAmount(USD, UINT64_C(30'443'43891402713), -11);
 
 5125                BEAST_EXPECT(env.
balance(carol, USD) == balanceAfterWithdraw);
 
 5127                auto const deposit = balanceAfterWithdraw - USD(29'000);
 
 5128                ammAlice.
deposit(carol, deposit);
 
 5130                ammAlice.
vote(alice, 0);
 
 5132                auto const tokensNoFee = ammAlice.
withdraw(carol, deposit);
 
 5133                if (!features[fixAMMv1_1] && !features[fixAMMv1_3])
 
 5136                        STAmount(USD, UINT64_C(30'443'43891402717), -11));
 
 5137                else if (features[fixAMMv1_1] && !features[fixAMMv1_3])
 
 5140                        STAmount(USD, UINT64_C(30'443'43891402716), -11));
 
 5144                        STAmount(USD, UINT64_C(30'443'43891402713), -11));
 
 5147                if (!features[fixAMMv1_1] && !features[fixAMMv1_3])
 
 5149                        tokensNoFee == 
IOUAmount(746'579'80779913, -8));
 
 5150                else if (features[fixAMMv1_1] && !features[fixAMMv1_3])
 
 5152                        tokensNoFee == 
IOUAmount(746'579'80779912, -8));
 
 5155                        tokensNoFee == 
IOUAmount(746'579'80779911, -8));
 
 5156                BEAST_EXPECT(tokensFee == 
IOUAmount(750'588'23529411, -8));
 
 5165            [&](
AMM& ammAlice, 
Env& env) {
 
 5171                    {USD(1'000), EUR(1'000)},
 
 5178                env(pay(carol, alice, EUR(10)),
 
 5189                ammAlice.
vote(alice, 1'000);
 
 5192                env(pay(bob, carol, USD(10)),
 
 5199                    env, bob, 
STAmount{EUR, UINT64_C(989'8989898989899), -13}));
 
 5204                    STAmount{EUR, UINT64_C(1'010'10101010101), -11},
 
 5207            {{USD(1'000), EUR(1'010)}},
 
 5214            [&](
AMM& ammAlice, 
Env& env) {
 
 5216                env(offer(carol, EUR(10), USD(10)));
 
 5221                env(offer(carol, USD(10), EUR(10)));
 
 5224                ammAlice.
vote(alice, 500);
 
 5226                env(offer(carol, EUR(10), USD(10)));
 
 5233                    STAmount{USD, UINT64_C(29'995'02512562814), -11}));
 
 5237                    STAmount{EUR, UINT64_C(30'004'97487437186), -11}));
 
 5243                        STAmount{EUR, UINT64_C(5'025125628140703), -15},
 
 5244                        STAmount{USD, UINT64_C(5'025125628140703), -15}}}}));
 
 5245                if (!features[fixAMMv1_1])
 
 5248                        STAmount{USD, UINT64_C(1'004'974874371859), -12},
 
 5249                        STAmount{EUR, UINT64_C(1'005'025125628141), -12},
 
 5255                        STAmount{USD, UINT64_C(1'004'97487437186), -11},
 
 5256                        STAmount{EUR, UINT64_C(1'005'025125628141), -12},
 
 5260            {{USD(1'000), EUR(1'010)}},
 
 5270            Env env(*
this, features);
 
 5275                {alice, bob, carol, ed},
 
 5277                {USD(2'000), EUR(2'000)});
 
 5278            env(offer(carol, EUR(5), USD(5)));
 
 5279            AMM ammAlice(env, alice, USD(1'005), EUR(1'000));
 
 5280            env(pay(bob, ed, USD(10)),
 
 5285            if (!features[fixAMMv1_1])
 
 5289                    USD(1'000), EUR(1'005), ammAlice.
tokens()));
 
 5294                    env, bob, 
STAmount(EUR, UINT64_C(1989'999999999999), -12)));
 
 5297                    STAmount(EUR, UINT64_C(1005'000000000001), -12),
 
 5306            Env env(*
this, features);
 
 5311                {alice, bob, carol, ed},
 
 5313                {USD(2'000), EUR(2'000)});
 
 5314            env(offer(carol, EUR(5), USD(5)));
 
 5316            AMM ammAlice(env, alice, USD(1'005), EUR(1'000), 
false, 250);
 
 5317            env(pay(bob, ed, USD(10)),
 
 5322            if (!features[fixAMMv1_1])
 
 5327                    STAmount{EUR, UINT64_C(1'989'987453007618), -12}));
 
 5330                    STAmount{EUR, UINT64_C(1'005'012546992382), -12},
 
 5338                    STAmount{EUR, UINT64_C(1'989'987453007628), -12}));
 
 5341                    STAmount{EUR, UINT64_C(1'005'012546992372), -12},
 
 5351            Env env(*
this, features);
 
 5356                {alice, bob, carol, ed},
 
 5358                {USD(2'000), EUR(2'000)});
 
 5359            env(offer(carol, EUR(10), USD(10)));
 
 5361            AMM ammAlice(env, alice, USD(1'005), EUR(1'000), 
false, 1'000);
 
 5362            env(pay(bob, ed, USD(10)),
 
 5369                USD(1'005), EUR(1'000), ammAlice.
tokens()));
 
 5378            Env env(*
this, features);
 
 5383                {alice, bob, carol, ed},
 
 5385                {USD(2'000), EUR(2'000)});
 
 5386            env(offer(carol, EUR(9), USD(9)));
 
 5388            AMM ammAlice(env, alice, USD(1'005), EUR(1'000), 
false, 1'000);
 
 5389            env(pay(bob, ed, USD(10)),
 
 5395                env, bob, 
STAmount{EUR, UINT64_C(1'989'993923296712), -12}));
 
 5398                STAmount{EUR, UINT64_C(1'001'006076703288), -12},
 
 
 5806        testcase(
"Offer/Strand Selection");
 
 5807        using namespace jtx;
 
 5810        auto const ETH = gw1[
"ETH"];
 
 5811        auto const CAN = gw1[
"CAN"];
 
 5817        auto prep = [&](
Env& env, 
auto gwRate, 
auto gw1Rate) {
 
 5818            fund(env, gw, {alice, carol, bob, ed}, 
XRP(2'000), {USD(2'000)});
 
 5823                {alice, carol, bob, ed},
 
 5824                {ETH(2'000), CAN(2'000)},
 
 5826            env(rate(gw, gwRate));
 
 5827            env(rate(gw1, gw1Rate));
 
 5831        for (
auto const& rates :
 
 5846                for (
auto i = 0; i < 3; ++i)
 
 5848                    Env env(*
this, features);
 
 5849                    prep(env, rates.first, rates.second);
 
 5851                    if (i == 0 || i == 2)
 
 5857                        amm.emplace(env, ed, USD(1'000), ETH(1'000));
 
 5858                    env(pay(carol, bob, USD(100)),
 
 5865                        BEAST_EXPECT(amm->expectBalances(
 
 5866                            USD(1'000), ETH(1'000), amm->tokens()));
 
 5869                    q[i] = Quality(Amounts{
 
 5870                        ETH(2'000) - env.
balance(carol, ETH),
 
 5871                        env.
balance(bob, USD) - USD(2'000)});
 
 5874                BEAST_EXPECT(q[0] > q[1]);
 
 5876                BEAST_EXPECT(q[0] == q[2]);
 
 5883            for (
auto i = 0; i < 3; ++i)
 
 5885                Env env(*
this, features);
 
 5886                prep(env, rates.first, rates.second);
 
 5888                if (i == 0 || i == 2)
 
 5894                    amm.emplace(env, ed, USD(1'000), ETH(1'000));
 
 5895                env(offer(alice, USD(400), ETH(400)));
 
 5900                    BEAST_EXPECT(amm->expectBalances(
 
 5901                        USD(1'000), ETH(1'000), amm->tokens()));
 
 5903                if (i == 0 || i == 2)
 
 5912                        env, alice, 1, {Amounts{USD(400), ETH(400)}}));
 
 5923                for (
auto i = 0; i < 3; ++i)
 
 5925                    Env env(*
this, features);
 
 5926                    prep(env, rates.first, rates.second);
 
 5928                    if (i == 0 || i == 2)
 
 5934                        amm.emplace(env, ed, USD(1'000), ETH(1'000));
 
 5935                    env(pay(carol, bob, USD(100)),
 
 5942                        BEAST_EXPECT(!amm->expectBalances(
 
 5943                            USD(1'000), ETH(1'000), amm->tokens()));
 
 5945                    if (i == 2 && !features[fixAMMv1_1])
 
 5947                        if (rates.first == 1.5)
 
 5949                            if (!features[fixAMMv1_1])
 
 5957                                            UINT64_C(378'6327949540823),
 
 5961                                            UINT64_C(283'9745962155617),
 
 5971                                            UINT64_C(378'6327949540813),
 
 5975                                            UINT64_C(283'974596215561),
 
 5980                            if (!features[fixAMMv1_1])
 
 5988                                            UINT64_C(325'299461620749),
 
 5992                                            UINT64_C(243'9745962155617),
 
 6002                                            UINT64_C(325'299461620748),
 
 6006                                            UINT64_C(243'974596215561),
 
 6012                        if (rates.first == 1.5)
 
 6020                                        ETH, UINT64_C(378'6327949540812), -13},
 
 6023                                        UINT64_C(283'9745962155609),
 
 6034                                        ETH, UINT64_C(325'2994616207479), -13},
 
 6037                                        UINT64_C(243'9745962155609),
 
 6042                    q[i] = Quality(Amounts{
 
 6043                        ETH(2'000) - env.
balance(carol, ETH),
 
 6044                        env.
balance(bob, USD) - USD(2'000)});
 
 6047                BEAST_EXPECT(q[1] > q[0]);
 
 6049                BEAST_EXPECT(q[2] > q[1]);
 
 6053            for (
auto i = 0; i < 3; ++i)
 
 6055                Env env(*
this, features);
 
 6056                prep(env, rates.first, rates.second);
 
 6058                if (i == 0 || i == 2)
 
 6064                    amm.emplace(env, ed, USD(1'000), ETH(1'000));
 
 6065                env(offer(alice, USD(250), ETH(400)));
 
 6070                    BEAST_EXPECT(!amm->expectBalances(
 
 6071                        USD(1'000), ETH(1'000), amm->tokens()));
 
 6077                    if (rates.first == 1.5)
 
 6079                        if (!features[fixAMMv1_1])
 
 6082                                env, ed, 1, {{Amounts{ETH(400), USD(250)}}}));
 
 6089                                        USD, UINT64_C(40'5694150420947), -13},
 
 6091                                        ETH, UINT64_C(64'91106406735152), -14},
 
 6105                                        ETH, UINT64_C(335'0889359326475), -13},
 
 6107                                        USD, UINT64_C(209'4305849579047), -13},
 
 6114                        if (!features[fixAMMv1_1])
 
 6123                                        ETH, UINT64_C(335'0889359326485), -13},
 
 6125                                        USD, UINT64_C(209'4305849579053), -13},
 
 6138                                        ETH, UINT64_C(335'0889359326475), -13},
 
 6140                                        USD, UINT64_C(209'4305849579047), -13},
 
 6166                for (
auto i = 0; i < 3; ++i)
 
 6168                    Env env(*
this, features);
 
 6169                    prep(env, rates.first, rates.second);
 
 6172                    if (i == 0 || i == 2)
 
 6180                        amm.emplace(env, ed, ETH(1'000), USD(1'000));
 
 6182                    env(pay(carol, bob, USD(100)),
 
 6190                    if (i == 2 && !features[fixAMMv1_1])
 
 6192                        if (rates.first == 1.5)
 
 6195                            BEAST_EXPECT(amm->expectBalances(
 
 6196                                STAmount{ETH, UINT64_C(1'176'66038955758), -11},
 
 6202                            BEAST_EXPECT(amm->expectBalances(
 
 6204                                    ETH, UINT64_C(1'179'540094339627), -12},
 
 6205                                STAmount{USD, UINT64_C(847'7880529867501), -13},
 
 6214                                          UINT64_C(343'3179205198749),
 
 6218                                          UINT64_C(343'3179205198749),
 
 6224                                          UINT64_C(362'2119470132499),
 
 6228                                          UINT64_C(362'2119470132499),
 
 6235                        if (rates.first == 1.5)
 
 6238                            BEAST_EXPECT(amm->expectBalances(
 
 6240                                    ETH, UINT64_C(1'176'660389557593), -12},
 
 6246                            BEAST_EXPECT(amm->expectBalances(
 
 6247                                STAmount{ETH, UINT64_C(1'179'54009433964), -11},
 
 6248                                STAmount{USD, UINT64_C(847'7880529867501), -13},
 
 6257                                          UINT64_C(343'3179205198749),
 
 6261                                          UINT64_C(343'3179205198749),
 
 6267                                          UINT64_C(362'2119470132499),
 
 6271                                          UINT64_C(362'2119470132499),
 
 6276                    q[i] = Quality(Amounts{
 
 6277                        ETH(2'000) - env.
balance(carol, ETH),
 
 6278                        env.
balance(bob, USD) - USD(2'000)});
 
 6280                BEAST_EXPECT(q[1] > q[0]);
 
 6281                BEAST_EXPECT(q[2] > q[0] && q[2] < q[1]);
 
 
 6389        testcase(
"Fix changeSpotPriceQuality");
 
 6390        using namespace jtx;
 
 6395            SucceedShouldSucceedResize,  
 
 6407        auto const xrpIouAmounts10_100 =
 
 6409        auto const iouXrpAmounts10_100 =
 
 6414            {
"0.001519763260828713", 
"1558701",             Quality{5414253689393440221}, 1000, FailShouldSucceed},
 
 6415            {
"0.01099814367603737",  
"1892611",             Quality{5482264816516900274}, 1000, FailShouldSucceed},
 
 6416            {
"0.78",                 
"796599",              Quality{5630392334958379008}, 1000, FailShouldSucceed},
 
 6417            {
"105439.2955578965",    
"49398693",            Quality{5910869983721805038},  400, FailShouldSucceed},
 
 6418            {
"12408293.23445213",    
"4340810521",          Quality{5911611095910090752},  997, FailShouldSucceed},
 
 6419            {
"1892611",              
"0.01099814367603737", Quality{6703103457950430139}, 1000, FailShouldSucceed},
 
 6420            {
"423028.8508101858",    
"3392804520",          Quality{5837920340654162816},  600, FailShouldSucceed},
 
 6421            {
"44565388.41001027",    
"73890647",            Quality{6058976634606450001}, 1000, FailShouldSucceed},
 
 6422            {
"66831.68494832662",    
"16",                  Quality{6346111134641742975},    0, FailShouldSucceed},
 
 6423            {
"675.9287302203422",    
"1242632304",          Quality{5625960929244093294},  300, FailShouldSucceed},
 
 6424            {
"7047.112186735699",    
"1649845866",          Quality{5696855348026306945},  504, FailShouldSucceed},
 
 6425            {
"840236.4402981238",    
"47419053",            Quality{5982561601648018688},  499, FailShouldSucceed},
 
 6426            {
"992715.618909774",     
"189445631733",        Quality{5697835648288106944},  815, SucceedShouldSucceedResize},
 
 6427            {
"504636667521",         
"185545883.9506651",   Quality{6343802275337659280},  503, SucceedShouldSucceedResize},
 
 6428            {
"992706.7218636649",    
"189447316000",        Quality{5697835648288106944},  797, SucceedShouldSucceedResize},
 
 6429            {
"1.068737911388205",    
"127860278877",        Quality{5268604356368739396},  293, SucceedShouldSucceedResize},
 
 6430            {
"17932506.56880419",    
"189308.6043676173",   Quality{6206460598195440068},  311, SucceedShouldSucceedResize},
 
 6431            {
"1.066379294658174",    
"128042251493",        Quality{5268559341368739328},  270, SucceedShouldSucceedResize},
 
 6432            {
"350131413924",         
"1576879.110907892",   Quality{6487411636539049449},  650, 
Fail},
 
 6433            {
"422093460",            
"2.731797662057464",   Quality{6702911108534394924}, 1000, 
Fail},
 
 6434            {
"76128132223",          
"367172.7148422662",   Quality{6487263463413514240},  548, 
Fail},
 
 6435            {
"132701839250",         
"280703770.7695443",   Quality{6273750681188885075},  562, 
Fail},
 
 6436            {
"994165.7604612011",    
"189551302411",        Quality{5697835592690668727},  815, 
Fail},
 
 6437            {
"45053.33303227917",    
"86612695359",         Quality{5625695218943638190},  500, 
Fail},
 
 6438            {
"199649.077043865",     
"14017933007",         Quality{5766034667318524880},  324, 
Fail},
 
 6439            {
"27751824831.70903",    
"78896950",            Quality{6272538159621630432},  500, 
Fail},
 
 6440            {
"225.3731275781907",    
"156431793648",        Quality{5477818047604078924},  989, 
Fail},
 
 6441            {
"199649.077043865",     
"14017933007",         Quality{5766036094462806309},  324, 
Fail},
 
 6442            {
"3.590272027140361",    
"20677643641",         Quality{5406056147042156356},  808, 
Fail},
 
 6443            {
"1.070884664490231",    
"127604712776",        Quality{5268620608623825741},  293, 
Fail},
 
 6444            {
"3272.448829820197",    
"6275124076",          Quality{5625710328924117902},   81, 
Fail},
 
 6445            {
"0.009059512633902926", 
"7994028",             Quality{5477511954775533172}, 1000, 
Fail},
 
 6446            {
"1",                    
"1.0",                 Quality{0},                    100, 
Fail},
 
 6447            {
"1.0",                  
"1",                   Quality{0},                    100, 
Fail},
 
 6448            {
"10",                   
"10.0",                Quality{xrpIouAmounts10_100},  100, 
Fail},
 
 6449            {
"10.0",                 
"10",                  Quality{iouXrpAmounts10_100},  100, 
Fail},
 
 6450            {
"69864389131",          
"287631.4543025075",   Quality{6487623473313516078},  451, Succeed},
 
 6451            {
"4328342973",           
"12453825.99247381",   Quality{6272522264364865181},  997, Succeed},
 
 6452            {
"32347017",             
"7003.93031579449",    Quality{6347261126087916670}, 1000, Succeed},
 
 6453            {
"61697206161",          
"36631.4583206413",    Quality{6558965195382476659},  500, Succeed},
 
 6454            {
"1654524979",           
"7028.659825511603",   Quality{6487551345110052981},  504, Succeed},
 
 6455            {
"88621.22277293179",    
"5128418948",          Quality{5766347291552869205},  380, Succeed},
 
 6456            {
"1892611",              
"0.01099814367603737", Quality{6703102780512015436}, 1000, Succeed},
 
 6457            {
"4542.639373338766",    
"24554809",            Quality{5838994982188783710},    0, Succeed},
 
 6458            {
"5132932546",           
"88542.99750172683",   Quality{6419203342950054537},  380, Succeed},
 
 6459            {
"78929964.1549083",     
"1506494795",          Quality{5986890029845558688},  589, Succeed},
 
 6460            {
"10096561906",          
"44727.72453735605",   Quality{6487455290284644551},  250, Succeed},
 
 6461            {
"5092.219565514988",    
"8768257694",          Quality{5626349534958379008},  503, Succeed},
 
 6462            {
"1819778294",           
"8305.084302902864",   Quality{6487429398998540860},  415, Succeed},
 
 6463            {
"6970462.633911943",    
"57359281",            Quality{6054087899185946624},  850, Succeed},
 
 6464            {
"3983448845",           
"2347.543644281467",   Quality{6558965195382476659},  856, Succeed},
 
 6468            {
"771493171",            
"1.243473020567508",   Quality{6707566798038544272},  100, SucceedShouldFail},
 
 6472        boost::regex rx(
"^\\d+$");
 
 6473        boost::smatch match;
 
 6477        auto rules = env.
current()->rules();
 
 6479        for (
auto const& t : tests)
 
 6489            auto const poolInIsXRP =
 
 6491            auto const poolOutIsXRP =
 
 6493            assert(!(poolInIsXRP && poolOutIsXRP));
 
 6494            auto const poolIn = getPool(
std::get<0>(t), poolInIsXRP);
 
 6495            auto const poolOut = getPool(
std::get<1>(t), poolOutIsXRP);
 
 6499                    Amounts{poolIn, poolOut},
 
 6506                    if (status == SucceedShouldSucceedResize)
 
 6508                        if (!features[fixAMMv1_1])
 
 6509                            BEAST_EXPECT(Quality{*amounts} < quality);
 
 6511                            BEAST_EXPECT(Quality{*amounts} >= quality);
 
 6513                    else if (status == Succeed)
 
 6515                        if (!features[fixAMMv1_1])
 
 6517                                Quality{*amounts} >= quality ||
 
 6519                                    Quality{*amounts}, quality, 
Number{1, -7}));
 
 6521                            BEAST_EXPECT(Quality{*amounts} >= quality);
 
 6523                    else if (status == FailShouldSucceed)
 
 6526                            features[fixAMMv1_1] &&
 
 6527                            Quality{*amounts} >= quality);
 
 6529                    else if (status == SucceedShouldFail)
 
 6532                            !features[fixAMMv1_1] &&
 
 6533                            Quality{*amounts} < quality &&
 
 6535                                Quality{*amounts}, quality, 
Number{1, -7}));
 
 6544                    if (status == 
Fail && quality != Quality{0})
 
 6546                        auto tinyOffer = [&]() {
 
 6553                                        Amounts{poolIn, poolOut},
 
 6557                            else if (
isXRP(poolOut))
 
 6562                                        Amounts{poolIn, poolOut},
 
 6567                            auto const takerPays = toAmount<STAmount>(
 
 6572                                    Amounts{poolIn, poolOut}, takerPays, tfee)};
 
 6574                        BEAST_EXPECT(Quality(tinyOffer) < quality);
 
 6576                    else if (status == FailShouldSucceed)
 
 6578                        BEAST_EXPECT(!features[fixAMMv1_1]);
 
 6580                    else if (status == SucceedShouldFail)
 
 6582                        BEAST_EXPECT(features[fixAMMv1_1]);
 
 6589                    !strcmp(e.
what(), 
"changeSpotPriceQuality failed"));
 
 6591                    !features[fixAMMv1_1] && status == FailShouldSucceed);
 
 6600            BEAST_EXPECT(!res.has_value());
 
 
 6666        using namespace jtx;
 
 6672        Account const gatehub{
"gatehub"};
 
 6673        Account const bitstamp{
"bitstamp"};
 
 6674        Account const trader{
"trader"};
 
 6675        auto const usdGH = gatehub[
"USD"];
 
 6676        auto const btcGH = gatehub[
"BTC"];
 
 6677        auto const usdBIT = bitstamp[
"USD"];
 
 6681            char const* testCase;
 
 6682            double const poolUsdBIT;
 
 6683            double const poolUsdGH;
 
 6696            double const offer1BtcGH = 0.1;
 
 6697            double const offer2BtcGH = 0.1;
 
 6698            double const offer2UsdGH = 1;
 
 6699            double const rateBIT = 0.0;
 
 6700            double const rateGH = 0.0;
 
 6705        for (
auto const& input : {
 
 6707                     .testCase = 
"Test Fix Overflow Offer",                   
 
 6710                     .sendMaxUsdBIT{usdBIT(50)},                              
 
 6711                     .sendUsdGH{usdGH, 
uint64_t(272'455089820359), -12},      
 
 6714                     .failUsdBIT{usdBIT, 
uint64_t(46'47826086956522), -14},   
 
 6715                     .failUsdBITr{usdBIT, 
uint64_t(46'47826086956521), -14},  
 
 6716                     .goodUsdGH{usdGH, 
uint64_t(96'7543114220382), -13},      
 
 6717                     .goodUsdGHr{usdGH, 
uint64_t(96'7543114222965), -13},     
 
 6718                     .goodUsdBIT{usdBIT, 
uint64_t(8'464739069120721), -15},   
 
 6719                     .goodUsdBITr{usdBIT, 
uint64_t(8'464739069098152), -15},  
 
 6720                     .lpTokenBalance = {28'61817604250837, -14},              
 
 6721                     .lpTokenBalanceAlt = 
IOUAmount{28'61817604250836, -14},  
 
 6729                     .testCase = 
"Overflow test {1, 100, 0.111}",           
 
 6732                     .sendMaxUsdBIT{usdBIT(0.111)},                         
 
 6733                     .sendUsdGH{usdGH, 100},                                
 
 6736                     .failUsdBIT{usdBIT, 
uint64_t(1'111), -3},              
 
 6737                     .failUsdBITr{usdBIT, 
uint64_t(1'111), -3},             
 
 6738                     .goodUsdGH{usdGH, 
uint64_t(90'04347888284115), -14},   
 
 6739                     .goodUsdGHr{usdGH, 
uint64_t(90'04347888284201), -14},  
 
 6740                     .goodUsdBIT{usdBIT, 
uint64_t(1'111), -3},              
 
 6741                     .goodUsdBITr{usdBIT, 
uint64_t(1'111), -3},             
 
 6742                     .lpTokenBalance{10, 0},                                
 
 6743                     .offer1BtcGH = 1e-5,                                   
 
 6745                     .offer2UsdGH = 1e-5,                                   
 
 6750                     .testCase = 
"Overflow test {1, 100, 1.00}",            
 
 6753                     .sendMaxUsdBIT{usdBIT(1.00)},                          
 
 6754                     .sendUsdGH{usdGH, 100},                                
 
 6757                     .failUsdBIT{usdBIT, 
uint64_t(2), 0},                   
 
 6758                     .failUsdBITr{usdBIT, 
uint64_t(2), 0},                  
 
 6759                     .goodUsdGH{usdGH, 
uint64_t(52'94379354424079), -14},   
 
 6760                     .goodUsdGHr{usdGH, 
uint64_t(52'94379354424135), -14},  
 
 6761                     .goodUsdBIT{usdBIT, 
uint64_t(2), 0},                   
 
 6762                     .goodUsdBITr{usdBIT, 
uint64_t(2), 0},                  
 
 6763                     .lpTokenBalance{10, 0},                                
 
 6764                     .offer1BtcGH = 1e-5,                                   
 
 6766                     .offer2UsdGH = 1e-5,                                   
 
 6771                     .testCase = 
"Overflow test {1, 100, 4.6432}",            
 
 6774                     .sendMaxUsdBIT{usdBIT(4.6432)},                          
 
 6775                     .sendUsdGH{usdGH, 100},                                  
 
 6778                     .failUsdBIT{usdBIT, 
uint64_t(5'6432), -4},               
 
 6779                     .failUsdBITr{usdBIT, 
uint64_t(5'6432), -4},              
 
 6780                     .goodUsdGH{usdGH, 
uint64_t(35'44113971506987), -14},     
 
 6781                     .goodUsdGHr{usdGH, 
uint64_t(35'44113971506987), -14},    
 
 6782                     .goodUsdBIT{usdBIT, 
uint64_t(2'821579689703915), -15},   
 
 6783                     .goodUsdBITr{usdBIT, 
uint64_t(2'821579689703954), -15},  
 
 6784                     .lpTokenBalance{10, 0},                                  
 
 6785                     .offer1BtcGH = 1e-5,                                     
 
 6787                     .offer2UsdGH = 1e-5,                                     
 
 6792                     .testCase = 
"Overflow test {1, 100, 10}",                
 
 6795                     .sendMaxUsdBIT{usdBIT(10)},                              
 
 6796                     .sendUsdGH{usdGH, 100},                                  
 
 6799                     .failUsdBIT{usdBIT, 
uint64_t(11), 0},                    
 
 6800                     .failUsdBITr{usdBIT, 
uint64_t(11), 0},                   
 
 6801                     .goodUsdGH{usdGH, 
uint64_t(35'44113971506987), -14},     
 
 6802                     .goodUsdGHr{usdGH, 
uint64_t(35'44113971506987), -14},    
 
 6803                     .goodUsdBIT{usdBIT, 
uint64_t(2'821579689703915), -15},   
 
 6804                     .goodUsdBITr{usdBIT, 
uint64_t(2'821579689703954), -15},  
 
 6805                     .lpTokenBalance{10, 0},                                  
 
 6806                     .offer1BtcGH = 1e-5,                                     
 
 6808                     .offer2UsdGH = 1e-5,                                     
 
 6813                     .testCase = 
"Overflow test {50, 100, 5.55}",          
 
 6816                     .sendMaxUsdBIT{usdBIT(5.55)},                         
 
 6817                     .sendUsdGH{usdGH, 100},                               
 
 6820                     .failUsdBIT{usdBIT, 
uint64_t(55'55), -2},             
 
 6821                     .failUsdBITr{usdBIT, 
uint64_t(55'55), -2},            
 
 6822                     .goodUsdGH{usdGH, 
uint64_t(90'04347888284113), -14},  
 
 6823                     .goodUsdGHr{usdGH, 
uint64_t(90'0434788828413), -13},  
 
 6824                     .goodUsdBIT{usdBIT, 
uint64_t(55'55), -2},             
 
 6825                     .goodUsdBITr{usdBIT, 
uint64_t(55'55), -2},            
 
 6826                     .lpTokenBalance{
uint64_t(70'71067811865475), -14},    
 
 6827                     .offer1BtcGH = 1e-5,                                  
 
 6829                     .offer2UsdGH = 1e-5,                                  
 
 6834                     .testCase = 
"Overflow test {50, 100, 50.00}",          
 
 6837                     .sendMaxUsdBIT{usdBIT(50.00)},                         
 
 6838                     .sendUsdGH{usdGH, 100},                                
 
 6839                     .failUsdGH{usdGH, 
uint64_t(52'94379354424081), -14},   
 
 6840                     .failUsdGHr{usdGH, 
uint64_t(52'94379354424092), -14},  
 
 6841                     .failUsdBIT{usdBIT, 
uint64_t(100), 0},                 
 
 6842                     .failUsdBITr{usdBIT, 
uint64_t(100), 0},                
 
 6843                     .goodUsdGH{usdGH, 
uint64_t(52'94379354424081), -14},   
 
 6844                     .goodUsdGHr{usdGH, 
uint64_t(52'94379354424092), -14},  
 
 6845                     .goodUsdBIT{usdBIT, 
uint64_t(100), 0},                 
 
 6846                     .goodUsdBITr{usdBIT, 
uint64_t(100), 0},                
 
 6847                     .lpTokenBalance{
uint64_t(70'71067811865475), -14},     
 
 6848                     .offer1BtcGH = 1e-5,                                   
 
 6850                     .offer2UsdGH = 1e-5,                                   
 
 6855                     .testCase = 
"Overflow test {50, 100, 232.16}",           
 
 6858                     .sendMaxUsdBIT{usdBIT(232.16)},                          
 
 6859                     .sendUsdGH{usdGH, 100},                                  
 
 6862                     .failUsdBIT{usdBIT, 
uint64_t(282'16), -2},               
 
 6863                     .failUsdBITr{usdBIT, 
uint64_t(282'16), -2},              
 
 6864                     .goodUsdGH{usdGH, 
uint64_t(35'44113971506987), -14},     
 
 6865                     .goodUsdGHr{usdGH, 
uint64_t(35'44113971506987), -14},    
 
 6866                     .goodUsdBIT{usdBIT, 
uint64_t(141'0789844851958), -13},   
 
 6867                     .goodUsdBITr{usdBIT, 
uint64_t(141'0789844851962), -13},  
 
 6868                     .lpTokenBalance{70'71067811865475, -14},                 
 
 6869                     .offer1BtcGH = 1e-5,                                     
 
 6871                     .offer2UsdGH = 1e-5,                                     
 
 6876                     .testCase = 
"Overflow test {50, 100, 500}",              
 
 6879                     .sendMaxUsdBIT{usdBIT(500)},                             
 
 6880                     .sendUsdGH{usdGH, 100},                                  
 
 6883                     .failUsdBIT{usdBIT, 
uint64_t(550), 0},                   
 
 6884                     .failUsdBITr{usdBIT, 
uint64_t(550), 0},                  
 
 6885                     .goodUsdGH{usdGH, 
uint64_t(35'44113971506987), -14},     
 
 6886                     .goodUsdGHr{usdGH, 
uint64_t(35'44113971506987), -14},    
 
 6887                     .goodUsdBIT{usdBIT, 
uint64_t(141'0789844851958), -13},   
 
 6888                     .goodUsdBITr{usdBIT, 
uint64_t(141'0789844851962), -13},  
 
 6889                     .lpTokenBalance{70'71067811865475, -14},                 
 
 6890                     .offer1BtcGH = 1e-5,                                     
 
 6892                     .offer2UsdGH = 1e-5,                                     
 
 6898            testcase(input.testCase);
 
 6899            for (
auto const& features :
 
 6900                 {all - fixAMMOverflowOffer - fixAMMv1_1 - fixAMMv1_3, all})
 
 6904                env.
fund(
XRP(5'000), gatehub, bitstamp, trader);
 
 6907                if (input.rateGH != 0.0)
 
 6908                    env(rate(gatehub, input.rateGH));
 
 6909                if (input.rateBIT != 0.0)
 
 6910                    env(rate(bitstamp, input.rateBIT));
 
 6912                env(trust(trader, usdGH(10'000'000)));
 
 6913                env(trust(trader, usdBIT(10'000'000)));
 
 6914                env(trust(trader, btcGH(10'000'000)));
 
 6917                env(pay(gatehub, trader, usdGH(100'000)));
 
 6918                env(pay(gatehub, trader, btcGH(100'000)));
 
 6919                env(pay(bitstamp, trader, usdBIT(100'000)));
 
 6925                    usdGH(input.poolUsdGH),
 
 6926                    usdBIT(input.poolUsdBIT)};
 
 6930                    amm.getLPTokensBalance();
 
 6932                env(offer(trader, usdBIT(1), btcGH(input.offer1BtcGH)));
 
 6935                    btcGH(input.offer2BtcGH),
 
 6936                    usdGH(input.offer2UsdGH)));
 
 6939                env(pay(trader, trader, input.sendUsdGH),
 
 6941                    path(~btcGH, ~usdGH),
 
 6946                auto const failUsdGH =
 
 6947                    features[fixAMMv1_1] ? input.failUsdGHr : input.failUsdGH;
 
 6948                auto const failUsdBIT =
 
 6949                    features[fixAMMv1_1] ? input.failUsdBITr : input.failUsdBIT;
 
 6950                auto const goodUsdGH =
 
 6951                    features[fixAMMv1_1] ? input.goodUsdGHr : input.goodUsdGH;
 
 6952                auto const goodUsdBIT =
 
 6953                    features[fixAMMv1_1] ? input.goodUsdBITr : input.goodUsdBIT;
 
 6954                auto const lpTokenBalance =
 
 6955                    env.
enabled(fixAMMv1_3) && input.lpTokenBalanceAlt
 
 6956                    ? *input.lpTokenBalanceAlt
 
 6957                    : input.lpTokenBalance;
 
 6958                if (!features[fixAMMOverflowOffer])
 
 6960                    BEAST_EXPECT(amm.expectBalances(
 
 6961                        failUsdGH, failUsdBIT, lpTokenBalance));
 
 6965                    BEAST_EXPECT(amm.expectBalances(
 
 6966                        goodUsdGH, goodUsdBIT, lpTokenBalance));
 
 6971                        amm.getLPTokensBalance() == preSwapLPTokenBalance);
 
 6975                    Number const sqrtPoolProduct =
 
 6976                        root2(goodUsdGH * goodUsdBIT);
 
 6987                        (sqrtPoolProduct + 
Number{1, -14} >=
 
 6988                         input.lpTokenBalance));