Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GSW-1838 test: swap_math unitest #429

Merged
merged 4 commits into from
Dec 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
202 changes: 0 additions & 202 deletions _deploy/p/gnoswap/pool/__TEST_swap_math_test.gnoA

This file was deleted.

127 changes: 83 additions & 44 deletions _deploy/p/gnoswap/pool/swap_math.gno
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,34 @@ import (
u256 "gno.land/p/gnoswap/uint256"
)

// SwapMathComputeSwapStepStr computes the next sqrt price, amount in, amount out, and fee amount
// Computes the result of swapping some amount in, or amount out, given the parameters of the swap
// The fee, plus the amount in, will never exceed the amount remaining if the swap's `amountSpecified` is positive
//
// input:
// - sqrtRatioCurrentX96: the current sqrt price of the pool
// - sqrtRatioTargetX96: The price that cannot be exceeded, from which the direction of the swap is inferred
// - liquidity: The usable liquidity of the pool
// - amountRemaining: How much input or output amount is remaining to be swapped in/out
// - feePips: The fee taken from the input amount, expressed in hundredths of a bip
//
// output:
// - sqrtRatioNextX96: The price after swapping the amount in/out, not to exceed the price target
// - amountIn: The amount to be swapped in, of either token0 or token1, based on the direction of the swap
// - amountOut: The amount to be received, of either token0 or token1, based on the direction of the swap
// - feeAmount: The amount of input that will be taken as a fee
func SwapMathComputeSwapStepStr(
sqrtRatioCurrentX96 *u256.Uint, // uint160
sqrtRatioTargetX96 *u256.Uint, // uint160
liquidity *u256.Uint, // uint128
amountRemaining *i256.Int, // int256
sqrtRatioCurrentX96 *u256.Uint,
sqrtRatioTargetX96 *u256.Uint,
liquidity *u256.Uint,
amountRemaining *i256.Int,
feePips uint64,
) (string, string, string, string) { // (sqrtRatioNextX96, amountIn, amountOut, feeAmount *u256.Uint)
isToken1Expensive := sqrtRatioCurrentX96.Gte(sqrtRatioTargetX96)
) (string, string, string, string) {
if sqrtRatioCurrentX96 == nil || sqrtRatioTargetX96 == nil || liquidity == nil || amountRemaining == nil {
panic("SwapMathComputeSwapStepStr: invalid input")
}

zeroForOne := sqrtRatioCurrentX96.Gte(sqrtRatioTargetX96)

// POSTIVIE == EXACT_IN => Estimated AmountOut
// NEGATIVE == EXACT_OUT => Estimated AmountIn
Expand All @@ -25,75 +45,94 @@ func SwapMathComputeSwapStepStr(

if exactIn {
amountRemainingLessFee := u256.MulDiv(amountRemaining.Abs(), u256.NewUint(1000000-feePips), u256.NewUint(1000000))

if isToken1Expensive {
amountIn = sqrtPriceMathGetAmount0DeltaHelper(sqrtRatioTargetX96, sqrtRatioCurrentX96, liquidity, true)
if zeroForOne {
amountIn = sqrtPriceMathGetAmount0DeltaHelper(
sqrtRatioTargetX96.Clone(),
sqrtRatioCurrentX96.Clone(),
liquidity.Clone(),
true)
} else {
amountIn = sqrtPriceMathGetAmount1DeltaHelper(sqrtRatioCurrentX96, sqrtRatioTargetX96, liquidity, true)
amountIn = sqrtPriceMathGetAmount1DeltaHelper(
sqrtRatioCurrentX96.Clone(),
sqrtRatioTargetX96.Clone(),
liquidity.Clone(),
true)
}

if amountRemainingLessFee.Gte(amountIn) {
sqrtRatioNextX96 = sqrtRatioTargetX96
sqrtRatioNextX96 = sqrtRatioTargetX96.Clone()
} else {
sqrtRatioNextX96 = sqrtPriceMathGetNextSqrtPriceFromInput(
sqrtRatioCurrentX96,
liquidity,
amountRemainingLessFee,
isToken1Expensive,
sqrtRatioCurrentX96.Clone(),
liquidity.Clone(),
amountRemainingLessFee.Clone(),
zeroForOne,
)
}

} else {
if isToken1Expensive {
amountOut = sqrtPriceMathGetAmount1DeltaHelper(sqrtRatioTargetX96, sqrtRatioCurrentX96, liquidity, false)
if zeroForOne {
amountOut = sqrtPriceMathGetAmount1DeltaHelper(
sqrtRatioTargetX96.Clone(),
sqrtRatioCurrentX96.Clone(),
liquidity.Clone(),
false)
} else {
amountOut = sqrtPriceMathGetAmount0DeltaHelper(sqrtRatioCurrentX96, sqrtRatioTargetX96, liquidity, false)
amountOut = sqrtPriceMathGetAmount0DeltaHelper(
sqrtRatioCurrentX96.Clone(),
sqrtRatioTargetX96.Clone(),
liquidity.Clone(),
false)
}

if amountRemaining.Abs().Gte(amountOut) {
sqrtRatioNextX96 = sqrtRatioTargetX96
sqrtRatioNextX96 = sqrtRatioTargetX96.Clone()
} else {
sqrtRatioNextX96 = sqrtPriceMathGetNextSqrtPriceFromOutput(
sqrtRatioCurrentX96,
liquidity,
sqrtRatioCurrentX96.Clone(),
liquidity.Clone(),
amountRemaining.Abs(),
isToken1Expensive,
zeroForOne,
)
}
}

max := sqrtRatioTargetX96.Eq(sqrtRatioNextX96)
isMax := sqrtRatioTargetX96.Eq(sqrtRatioNextX96)

if isToken1Expensive {
if max && exactIn {
amountIn = amountIn
} else {
amountIn = sqrtPriceMathGetAmount0DeltaHelper(sqrtRatioNextX96, sqrtRatioCurrentX96, liquidity, true)
if zeroForOne {
if !(isMax && exactIn) {
amountIn = sqrtPriceMathGetAmount0DeltaHelper(
sqrtRatioNextX96.Clone(),
sqrtRatioCurrentX96.Clone(),
liquidity.Clone(),
true)
}

if max && !exactIn {
amountOut = amountOut
} else {
amountOut = sqrtPriceMathGetAmount1DeltaHelper(sqrtRatioNextX96, sqrtRatioCurrentX96, liquidity, false)
if !(isMax && !exactIn) {
amountOut = sqrtPriceMathGetAmount1DeltaHelper(
sqrtRatioNextX96.Clone(),
sqrtRatioCurrentX96.Clone(),
liquidity.Clone(),
false)
}
} else {
if max && exactIn {
amountIn = amountIn
} else {
amountIn = sqrtPriceMathGetAmount1DeltaHelper(sqrtRatioCurrentX96, sqrtRatioNextX96, liquidity, true)
if !(isMax && exactIn) {
amountIn = sqrtPriceMathGetAmount1DeltaHelper(
sqrtRatioCurrentX96.Clone(),
sqrtRatioNextX96.Clone(),
liquidity.Clone(),
true)
}

if max && !exactIn {
amountOut = amountOut
} else {
amountOut = sqrtPriceMathGetAmount0DeltaHelper(sqrtRatioCurrentX96, sqrtRatioNextX96, liquidity, false)
if !(isMax && !exactIn) {
amountOut = sqrtPriceMathGetAmount0DeltaHelper(
sqrtRatioCurrentX96.Clone(),
sqrtRatioNextX96.Clone(),
liquidity.Clone(),
false)
}
}

if !exactIn && amountOut.Gt(amountRemaining.Abs()) {
amountOut = amountRemaining.Abs()
}

if exactIn && !(sqrtRatioNextX96.Eq(sqrtRatioTargetX96)) {
feeAmount = new(u256.Uint).Sub(amountRemaining.Abs(), amountIn)
} else {
Expand Down
Loading
Loading