fixReducedOffersV2: prevent offers from blocking order books: (#5032)

Fixes issue #4937.

The fixReducedOffersV1 amendment fixed certain forms of offer
modification that could lead to blocked order books.  Reduced
offers can block order books if the effective quality of the
reduced offer is worse than the quality of the original offer
(from the perspective of the taker). It turns out that, for
small values, the quality of the reduced offer can be
significantly affected by the rounding mode used during
scaling computations.

Issue #4937 identified an additional code path that modified
offers in a way that could lead to blocked order books.  This
commit changes the rounding in that newly located code path so
the quality of the modified offer is never worse than the
quality of the offer as it was originally placed.

It is possible that additional ways of producing blocking
offers will come to light.  Therefore there may be a future
need for a V3 amendment.
This commit is contained in:
Scott Schurr
2024-06-13 14:57:12 -07:00
committed by GitHub
parent 263e984bf4
commit ae7ea33b75
12 changed files with 532 additions and 157 deletions

View File

@@ -3618,13 +3618,16 @@ private:
STAmount(USD, UINT64_C(9'970'097277662122), -12),
STAmount(EUR, UINT64_C(10'029'99250187452), -11),
ammUSD_EUR.tokens()));
BEAST_EXPECT(expectOffers(
env,
alice,
1,
{{Amounts{
XRPAmount(30'201'749),
STAmount(USD, UINT64_C(29'90272233787818), -14)}}}));
// fixReducedOffersV2 changes the expected results slightly.
Amounts const expectedAmounts =
env.closed()->rules().enabled(fixReducedOffersV2)
? Amounts{XRPAmount(30'201'749), STAmount(USD, UINT64_C(29'90272233787816), -14)}
: Amounts{
XRPAmount(30'201'749),
STAmount(USD, UINT64_C(29'90272233787818), -14)};
BEAST_EXPECT(expectOffers(env, alice, 1, {{expectedAmounts}}));
}
else
{
@@ -3632,13 +3635,16 @@ private:
STAmount(USD, UINT64_C(9'970'097277662172), -12),
STAmount(EUR, UINT64_C(10'029'99250187452), -11),
ammUSD_EUR.tokens()));
BEAST_EXPECT(expectOffers(
env,
alice,
1,
{{Amounts{
XRPAmount(30'201'749),
STAmount(USD, UINT64_C(29'9027223378284), -13)}}}));
// fixReducedOffersV2 changes the expected results slightly.
Amounts const expectedAmounts =
env.closed()->rules().enabled(fixReducedOffersV2)
? Amounts{XRPAmount(30'201'749), STAmount(USD, UINT64_C(29'90272233782839), -14)}
: Amounts{
XRPAmount(30'201'749),
STAmount(USD, UINT64_C(29'90272233782840), -14)};
BEAST_EXPECT(expectOffers(env, alice, 1, {{expectedAmounts}}));
}
// Initial 30,000 + 100
BEAST_EXPECT(expectLine(env, carol, STAmount{USD, 30'100}));
@@ -6874,6 +6880,8 @@ private:
testInvalidAMMPayment();
testBasicPaymentEngine(all);
testBasicPaymentEngine(all - fixAMMv1_1);
testBasicPaymentEngine(all - fixReducedOffersV2);
testBasicPaymentEngine(all - fixAMMv1_1 - fixReducedOffersV2);
testAMMTokens();
testAmendment();
testFlags();