Skip to content

Commit

Permalink
Refactor with common functions
Browse files Browse the repository at this point in the history
  • Loading branch information
gregtatcam committed Nov 7, 2024
1 parent cf9b547 commit d174aca
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 102 deletions.
2 changes: 1 addition & 1 deletion include/xrpl/protocol/Feature.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ namespace detail {
// Feature.cpp. Because it's only used to reserve storage, and determine how
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
// the actual number of amendments. A LogicError on startup will verify this.
static constexpr std::size_t numFeatures = 81;
static constexpr std::size_t numFeatures = 82;

/** Amendments that this server supports and the default voting behavior.
Whether they are enabled depends on the Rules defined in the validated
Expand Down
2 changes: 2 additions & 0 deletions src/test/app/AMM_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7251,6 +7251,7 @@ struct AMM_test : public jtx::AMMTest
testDeposit();
testInvalidWithdraw();
testWithdraw();
#if 0
testInvalidFeeVote();
testFeeVote();
testInvalidBid();
Expand Down Expand Up @@ -7295,6 +7296,7 @@ struct AMM_test : public jtx::AMMTest
testAMMDepositWithFrozenAssets(all - fixAMMv1_1 - featureAMMClawback);
testDepositAndWithdrawRoundingV2(all);
testDepositAndWithdrawRoundingV2(all - fixAMMv1_3);
#endif
}
};

Expand Down
32 changes: 32 additions & 0 deletions src/xrpld/app/misc/AMMHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,38 @@ adjustAmountsByLPTokens(
Number
solveQuadraticEq(Number const& a, Number const& b, Number const& c);

STAmount
multiply(STAmount const& amount, Number const& frac, Number::rounding_mode rm);

template <typename A>
STAmount
getAmount(
Rules const& rules,
STAmount const& balance,
A const& frac,
bool isDeposit)
{
if (!rules.enabled(fixAMMv1_3))
{
if constexpr (std::is_same_v<A, STAmount>)
return multiply(balance, frac, balance.issue());
else
return toSTAmount(balance.issue(), balance * frac);
}
// Maximize amount to deposit, minimize amount to withdraw to ensure
// AMM invariant sqrt(poolAsset1 * poolAsset2) >= LPTokensBalance
Number::rounding_mode const rm =
isDeposit ? Number::upward : Number::downward;
return multiply(balance, frac, rm);
}

STAmount
getTokens(
Rules const& rules,
STAmount const& balance,
Number const& frac,
bool isDeposit);

} // namespace ripple

#endif // RIPPLE_APP_MISC_AMMHELPERS_H_INCLUDED
41 changes: 29 additions & 12 deletions src/xrpld/app/misc/detail/AMMHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ lpTokensOut(
{
// minimize tokens out
auto const frac = (r - c) / (1 + c);
NumberRoundModeGuard g(Number::downward);
auto const t = lptAMMBalance * frac;
return toSTAmount(lptAMMBalance.issue(), t, Number::downward);
return multiply(lptAMMBalance, frac, Number::downward);
}
}

Expand Down Expand Up @@ -98,9 +96,7 @@ ammAssetIn(
{
// maximize deposit
auto const frac = solveQuadraticEq(a, b, c);
NumberRoundModeGuard g(Number::upward);
auto const t = asset1Balance * frac;
return toSTAmount(asset1Balance.issue(), t, Number::upward);
return multiply(asset1Balance, frac, Number::upward);
}
}

Expand All @@ -127,9 +123,7 @@ lpTokensIn(
{
// maximize tokens in
auto const frac = (c - root2(c * c - 4 * fr)) / 2;
NumberRoundModeGuard g(Number::upward);
auto const t = lptAMMBalance * frac;
return toSTAmount(lptAMMBalance.issue(), t, Number::upward);
return multiply(lptAMMBalance, frac, Number::upward);
}
}

Expand Down Expand Up @@ -161,9 +155,7 @@ ammAssetOut(
{
// minimize withdraw
auto const frac = (t1 * t1 - t1 * (2 - f)) / (t1 * f - 1);
NumberRoundModeGuard g(Number::downward);
auto const t = assetBalance * frac;
return toSTAmount(assetBalance.issue(), t, Number::downward);
return multiply(assetBalance, frac, Number::downward);
}
}

Expand Down Expand Up @@ -284,4 +276,29 @@ solveQuadraticEqSmallest(Number const& a, Number const& b, Number const& c)
return (2 * c) / (-b + root2(d));
}

STAmount
multiply(STAmount const& amount, Number const& frac, Number::rounding_mode rm)
{
NumberRoundModeGuard g(rm);
auto const t = amount * frac;
return toSTAmount(amount.issue(), t, rm);
}

STAmount
getTokens(
Rules const& rules,
STAmount const& balance,
Number const& frac,
bool isDeposit)
{
if (!rules.enabled(fixAMMv1_3))
return toSTAmount(balance.issue(), balance * frac);

// Minimize tokens out, maximize tokens in to ensure
// AMM invariant sqrt(poolAsset1 * poolAsset2) >= LPTokensBalance
Number::rounding_mode rm = isDeposit ? Number::downward : Number::upward;
auto const tokens = multiply(balance, frac, rm);
return adjustLPTokens(balance, tokens, isDeposit);
}

} // namespace ripple
70 changes: 22 additions & 48 deletions src/xrpld/app/tx/detail/AMMDeposit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -657,15 +657,10 @@ AMMDeposit::equalDepositTokens(
auto const tokens =
adjustLPTokensOut(view.rules(), lptAMMBalance, lpTokensDeposit);
auto const frac = divide(tokens, lptAMMBalance, lptAMMBalance.issue());
auto const getAmount = [&](STAmount const& balance) {
if (!view.rules().enabled(fixAMMv1_3))
return multiply(balance, frac, balance.issue());
// maximize deposit
NumberRoundModeGuard g(Number::upward);
return toSTAmount(balance.issue(), balance * frac, Number::upward);
};
auto const amountDeposit = getAmount(amountBalance);
auto const amount2Deposit = getAmount(amount2Balance);
auto const amountDeposit =
getAmount(view.rules(), amountBalance, frac, true);
auto const amount2Deposit =
getAmount(view.rules(), amount2Balance, frac, true);
return deposit(
view,
ammAccount,
Expand Down Expand Up @@ -729,35 +724,17 @@ AMMDeposit::equalDepositLimit(
std::optional<STAmount> const& lpTokensDepositMin,
std::uint16_t tfee)
{
auto getTokens = [&](Number const& frac) {
if (!view.rules().enabled(fixAMMv1_3))
return toSTAmount(lptAMMBalance.issue(), lptAMMBalance * frac);
else
{
// minimize tokens out
NumberRoundModeGuard g(Number::downward);
auto const t = toSTAmount(
lptAMMBalance.issue(), lptAMMBalance * frac, Number::downward);
return adjustLPTokensOut(view.rules(), lptAMMBalance, t);
}
};
auto getAmount = [&](Number const& frac, STAmount const& balance) {
if (!view.rules().enabled(fixAMMv1_3))
return toSTAmount(balance.issue(), balance * frac);
// maximize deposit
NumberRoundModeGuard g(Number::upward);
return toSTAmount(balance.issue(), balance * frac, Number::upward);
};
auto frac = Number{amount} / amountBalance;
auto tokens = getTokens(frac);
auto tokens = getTokens(view.rules(), lptAMMBalance, frac, true);
if (tokens == beast::zero)
{
if (!view.rules().enabled(fixAMMv1_3))
return {tecAMM_FAILED, STAmount{}};
else
return {tecAMM_INVALID_TOKENS, STAmount{}};
}
auto const amount2Deposit = getAmount(frac, amount2Balance);
auto const amount2Deposit =
getAmount(view.rules(), amount2Balance, frac, true);
if (amount2Deposit <= amount2)
return deposit(
view,
Expand All @@ -772,15 +749,16 @@ AMMDeposit::equalDepositLimit(
lpTokensDepositMin,
tfee);
frac = Number{amount2} / amount2Balance;
tokens = getTokens(frac);
tokens = getTokens(view.rules(), lptAMMBalance, frac, true);
if (tokens == beast::zero)
{
if (!view.rules().enabled(fixAMMv1_3))
return {tecAMM_FAILED, STAmount{}};
else
return {tecAMM_INVALID_TOKENS, STAmount{}};
}
auto const amountDeposit = getAmount(frac, amountBalance);
auto const amountDeposit =
getAmount(view.rules(), amountBalance, frac, true);
if (amountDeposit <= amount)
return deposit(
view,
Expand Down Expand Up @@ -967,29 +945,25 @@ AMMDeposit::singleDepositEPrice(
auto const c1 = 2 * c * f2 * f2 + 1 - 2 * d * f2;
auto const amountDeposit = [&] {
if (!view.rules().enabled(fixAMMv1_3))
return toSTAmount(
amountBalance.issue(),
f1 * amountBalance * solveQuadraticEq(a1, b1, c1));
else
{
// maximize deposit
auto const frac = f1 * solveQuadraticEq(a1, b1, c1);
NumberRoundModeGuard g(Number::upward);
return toSTAmount(
amountBalance.issue(), amountBalance * frac, Number::upward);
auto const a = f1 * amountBalance * solveQuadraticEq(a1, b1, c1);
return toSTAmount(amountBalance.issue(), a);
}
auto const frac = f1 * solveQuadraticEq(a1, b1, c1);
return multiply(amountBalance, frac, Number::upward);
}();
if (amountDeposit <= beast::zero)
return {tecAMM_FAILED, STAmount{}};
auto const tokens = [&] {
if (!view.rules().enabled(fixAMMv1_3))
return toSTAmount(lptAMMBalance.issue(), amountDeposit / ePrice);
// minimize tokens out
NumberRoundModeGuard g(Number::downward);
auto const t = toSTAmount(
lptAMMBalance.issue(), amountDeposit / ePrice, Number::downward);
return adjustLPTokensOut(view.rules(), lptAMMBalance, t);
Number::rounding_mode const rm = !view.rules().enabled(fixAMMv1_3)
? Number::getround()
: Number::downward;
NumberRoundModeGuard g(rm);
auto const t =
toSTAmount(lptAMMBalance.issue(), amountDeposit / ePrice, rm);
return adjustLPTokens(lptAMMBalance, t, true);
}();

return deposit(
view,
ammAccount,
Expand Down
58 changes: 17 additions & 41 deletions src/xrpld/app/tx/detail/AMMWithdraw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -761,20 +761,13 @@ AMMWithdraw::equalWithdrawTokens(
journal);
}

auto getAmount = [&](STAmount const& frac, STAmount const& balance) {
if (!view.rules().enabled(fixAMMv1_3))
return multiply(balance, frac, balance.issue());
// minimize withdraw
NumberRoundModeGuard g(Number::downward);
return toSTAmount(
balance.issue(), balance * frac, Number::downward);
};

auto const tokens =
adjustLPTokensIn(view.rules(), lptAMMBalance, lpTokensWithdraw);
auto const frac = divide(tokens, lptAMMBalance, noIssue());
auto const withdrawAmount = getAmount(frac, amountBalance);
auto const withdraw2Amount = getAmount(frac, amount2Balance);
auto const withdrawAmount =
getAmount(view.rules(), amountBalance, frac, false);
auto const withdraw2Amount =
getAmount(view.rules(), amount2Balance, frac, false);
// LP is making equal withdrawal by tokens but the requested amount
// of LP tokens is likely too small and results in one-sided pool
// withdrawal due to round off. Fail so the user withdraws
Expand Down Expand Up @@ -844,24 +837,9 @@ AMMWithdraw::equalWithdrawLimit(
STAmount const& amount2,
std::uint16_t tfee)
{
auto getTokens = [&](Number const& frac) {
if (!view.rules().enabled(fixAMMv1_3))
return toSTAmount(lptAMMBalance.issue(), lptAMMBalance * frac);
// maximize tokens in
NumberRoundModeGuard g(Number::upward);
auto const t = toSTAmount(
lptAMMBalance.issue(), lptAMMBalance * frac, Number::upward);
return adjustLPTokensIn(view.rules(), lptAMMBalance, t);
};
auto getAmount = [&](Number const& frac, STAmount const& balance) {
if (!view.rules().enabled(fixAMMv1_3))
return toSTAmount(balance.issue(), balance * frac);
// minimize withdraw
NumberRoundModeGuard g(Number::downward);
return toSTAmount(balance.issue(), balance * frac, Number::downward);
};
auto frac = Number{amount} / amountBalance;
auto const amount2Withdraw = getAmount(frac, amount2Balance);
auto const amount2Withdraw =
getAmount(view.rules(), amount2Balance, frac, false);
if (amount2Withdraw <= amount2)
{
return withdraw(
Expand All @@ -872,12 +850,13 @@ AMMWithdraw::equalWithdrawLimit(
amount,
amount2Withdraw,
lptAMMBalance,
getTokens(frac),
getTokens(view.rules(), lptAMMBalance, frac, false),
tfee);
}

frac = Number{amount2} / amount2Balance;
auto const amountWithdraw = getAmount(frac, amountBalance);
auto const amountWithdraw =
getAmount(view.rules(), amountBalance, frac, false);
assert(amountWithdraw <= amount);
return withdraw(
view,
Expand All @@ -887,7 +866,7 @@ AMMWithdraw::equalWithdrawLimit(
amountWithdraw,
amount2,
lptAMMBalance,
getTokens(frac),
getTokens(view.rules(), lptAMMBalance, frac, false),
tfee);
}

Expand Down Expand Up @@ -1020,13 +999,10 @@ AMMWithdraw::singleWithdrawEPrice(
(lptAMMBalance * f - ae);
return toSTAmount(lptAMMBalance.issue(), t);
}
// maximize tokens in
auto const frac =
(lptAMMBalance + ae * (f - 2)) / (lptAMMBalance * f - ae);
NumberRoundModeGuard g(Number::upward);
auto const t = toSTAmount(
lptAMMBalance.issue(), lptAMMBalance * frac, Number::upward);
return adjustLPTokensIn(view.rules(), lptAMMBalance, t);
auto const tokens = multiply(lptAMMBalance, frac, Number::upward);
return adjustLPTokens(lptAMMBalance, tokens, false);
}();
if (tokens <= beast::zero)
{
Expand All @@ -1036,11 +1012,11 @@ AMMWithdraw::singleWithdrawEPrice(
return {tecAMM_INVALID_TOKENS, STAmount{}};
}
auto const amountWithdraw = [&] {
if (!view.rules().enabled(fixAMMv1_3))
return toSTAmount(amount.issue(), tokens / ePrice);
// minimize withdraw
NumberRoundModeGuard g(Number::downward);
return toSTAmount(amount.issue(), tokens / ePrice, Number::downward);
Number::rounding_mode const rm = !view.rules().enabled(fixAMMv1_3)
? Number::getround()
: Number::downward;
NumberRoundModeGuard g(rm);
return toSTAmount(amount.issue(), tokens / ePrice, rm);
}();
if (amount == beast::zero || amountWithdraw >= amount)
{
Expand Down

0 comments on commit d174aca

Please sign in to comment.