From f7a3400a2dec955ed72090aff34816a8300fd5ab Mon Sep 17 00:00:00 2001 From: n3wbie Date: Tue, 17 Oct 2023 18:35:48 +0900 Subject: [PATCH] GSW-441 fix: `FindBestPool` uses `DrySwap()` to pool path in first condition --- ...ic_test.gno => _TEST_math_logic_test.gnoa} | 0 ...r_test.gnoa => _TEST_pool_router_test.gno} | 72 +++++++++---------- pool/math_logic.gno | 4 +- pool/pool_router.gno | 63 +++++++++++----- 4 files changed, 83 insertions(+), 56 deletions(-) rename pool/{_TEST_math_logic_test.gno => _TEST_math_logic_test.gnoa} (100%) rename pool/{_TEST_pool_router_test.gnoa => _TEST_pool_router_test.gno} (72%) diff --git a/pool/_TEST_math_logic_test.gno b/pool/_TEST_math_logic_test.gnoa similarity index 100% rename from pool/_TEST_math_logic_test.gno rename to pool/_TEST_math_logic_test.gnoa diff --git a/pool/_TEST_pool_router_test.gnoa b/pool/_TEST_pool_router_test.gno similarity index 72% rename from pool/_TEST_pool_router_test.gnoa rename to pool/_TEST_pool_router_test.gno index 3ebfa70ab..1a0368940 100644 --- a/pool/_TEST_pool_router_test.gnoa +++ b/pool/_TEST_pool_router_test.gno @@ -1,10 +1,11 @@ package pool import ( - "encoding/gjson" "std" "testing" + "encoding/gjson" + "gno.land/p/demo/testutils" "gno.land/r/demo/users" @@ -29,23 +30,9 @@ func TestInitManual(t *testing.T) { } func TestCreatePool(t *testing.T) { - CreatePool("foo", "bar", uint16(500), 5602223755577321903022134995689) // 85_176 == x4999.904 + CreatePool("foo", "bar", uint16(500), 130621891405341611593710811006) // 2.7181459268 + CreatePool("foo", "bar", uint16(3000), 130621891405341611593710811006) // 2.7181459268 std.TestSkipHeights(1) - // fee = 500 - // tickSpacing = 10 - - // sqrtPriceX96 = 130621891405341611593710811006 - // tick = 10_000 - // ratio = 1.648% - - CreatePool("foo", "bar", uint16(3000), 255973311431586396528129062412) // 23456 == 3.23% - std.TestSkipHeights(1) - // fee = 3000 - // tickSpacing = 60 - - // sqrtPriceX96 = 255973311431586396528129062412 - // tick = 23_456 - // ratio = 3.23% } func TestPositionMint500(t *testing.T) { @@ -54,21 +41,17 @@ func TestPositionMint500(t *testing.T) { _, _, m0, m1 := pos.Mint( "foo", // token0 "bar", // token1 - uint16(500), // fee 500 ~= tickSpacing 10 - 84220, // tickLower // x4544 - 86130, // tickUpper // x5500 - 30000000, // amount0Desired - 30000000, // amount1Desired + uint16(500), // fee 3000 ~= tickSpacing 60 + 6600, // tickLower + 10200, // tickUpper + 100, // amount0Desired + 100, // amount1Desired 0, // amount0Min 0, // amount1Min 9999999999, // deadline ) - - shouldEQ(t, m0, bigint(5987)) // x5010.8565224653 - shouldEQ(t, m1, bigint(29999998)) - - shouldEQ(t, bigint(fooBalance(poolAddr)), m0) - shouldEQ(t, bigint(barBalance(poolAddr)), m1) + shouldEQ(t, m0, bigint(2)) + shouldEQ(t, m1, bigint(99)) } func TestPositionMint3000(t *testing.T) { @@ -78,15 +61,15 @@ func TestPositionMint3000(t *testing.T) { "foo", // token0 "bar", // token1 uint16(3000), // fee 3000 ~= tickSpacing 60 - 22800, // tickLower - 24000, // tickUpper + 6600, // tickLower + 10200, // tickUpper 1000, // amount0Desired 1000, // amount1Desired 0, // amount0Min 0, // amount1Min 9999999999, // deadline ) - shouldEQ(t, m0, bigint(79)) + shouldEQ(t, m0, bigint(23)) shouldEQ(t, m1, bigint(999)) } @@ -95,10 +78,23 @@ func TestFindBestPoolTruePositive(t *testing.T) { "foo", // tokenA "bar", // tokenB true, // zeroForOne - 500, // amountSpecified + 200, // amountSpecified ) jsonStr := gjson.Parse(bestPoolPathDetail) - shouldEQ(t, jsonStr.Get("response.data.pool_path").String(), "bar_foo_500") + shouldEQ(t, jsonStr.Get("response.data.pool_path").String(), "bar_foo_3000") + + // should return empty if not enough balance + { + bestPoolPathDetail := FindBestPool( + "foo", // tokenA + "bar", // tokenB + true, // zeroForOne + 438, // amountSpecified + ) + + jsonStr := gjson.Parse(bestPoolPathDetail) + shouldEQ(t, jsonStr.Get("response.data.pool_path").String(), "") + } } func TestFindBestPoolTrueNegative(t *testing.T) { @@ -106,10 +102,10 @@ func TestFindBestPoolTrueNegative(t *testing.T) { "foo", // tokenA "bar", // tokenB true, // zeroForOne - -5000, // amountSpecified + -888, // amountSpecified ) jsonStr := gjson.Parse(bestPoolPathDetail) - shouldEQ(t, jsonStr.Get("response.data.pool_path").String(), "bar_foo_500") + shouldEQ(t, jsonStr.Get("response.data.pool_path").String(), "bar_foo_3000") } func TestFindBestPoolFalsePositive(t *testing.T) { @@ -117,7 +113,7 @@ func TestFindBestPoolFalsePositive(t *testing.T) { "foo", // tokenA "bar", // tokenB false, // zeroForOne - 50, // amountSpecified + 5, // amountSpecified ) jsonStr := gjson.Parse(bestPoolPathDetail) shouldEQ(t, jsonStr.Get("response.data.pool_path").String(), "bar_foo_3000") @@ -128,10 +124,10 @@ func TestFindBestPoolFalseNegative(t *testing.T) { "foo", // tokenA "bar", // tokenB false, // zeroForOne - -1234, // amountSpecified + -11, // amountSpecified ) jsonStr := gjson.Parse(bestPoolPathDetail) - shouldEQ(t, jsonStr.Get("response.data.pool_path").String(), "bar_foo_500") + shouldEQ(t, jsonStr.Get("response.data.pool_path").String(), "bar_foo_3000") } func TestFindBestPoolWrong(t *testing.T) { diff --git a/pool/math_logic.gno b/pool/math_logic.gno index 6df1d50dd..dd8da3903 100644 --- a/pool/math_logic.gno +++ b/pool/math_logic.gno @@ -144,9 +144,9 @@ func DrySwap( } if zeroForOne { - require(pool.balances.token1 > amount1, ufmt.Sprintf("[POOL] math_logic.gno__DrySwap()_ZFO_T || pool.balances.token1(%s) > amount1(%s)", pool.balances.token1, amount1)) + require(pool.balances.token1 > (-1*amount1), ufmt.Sprintf("[POOL] math_logic.gno__DrySwap()_ZFO_T || pool.balances.token1(%s) > amount1(%s)", pool.balances.token1, (-1*amount1))) } else { - require(pool.balances.token0 > amount0, ufmt.Sprintf("[POOL] math_logic.gno__DrySwap()_ZFO_F || pool.balances.token0(%s) > amount0(%s)", pool.balances.token0, amount0)) + require(pool.balances.token0 > (-1*amount0), ufmt.Sprintf("[POOL] math_logic.gno__DrySwap()_ZFO_F || pool.balances.token0(%s) > amount0(%s)", pool.balances.token0, (-1*amount0))) } return amount0, amount1 diff --git a/pool/pool_router.gno b/pool/pool_router.gno index f0a25298a..bce844945 100644 --- a/pool/pool_router.gno +++ b/pool/pool_router.gno @@ -36,19 +36,35 @@ func FindBestPool( continue } else if zeroForOne == true && amountSpecified > 0 { for _, singlePool := range foundPool { - p := GetPoolFromPoolKey(singlePool) - poolSqrtX96 := p.slot0.sqrtPriceX96 - poolPrice := poolSqrtX96 * poolSqrtX96 / Q96 / Q96 - - pool := GetPoolFromPoolKey(singlePool) - if pool.balances.token1 > amountSpecified*poolPrice { // must be bigger (can't be equal due to fee) - firstSelectedPool = append(firstSelectedPool, singlePool) - } + func() { + defer func() { + if r := recover(); r != nil { + continue + } + }() + + _, _, fee := poolPathDivide(singlePool) + es0, es1 := DrySwap( + tokenA, + tokenB, + fee, + "", + true, + amountSpecified, + MIN_PRICE, + ) + + pool := GetPoolFromPoolKey(singlePool) + if pool.balances.token1 > (-1 * es1) { // must be bigger (can't be equal due to fee) + firstSelectedPool = append(firstSelectedPool, singlePool) + } + }() } } else if zeroForOne == true && amountSpecified < 0 { for _, singlePool := range foundPool { pool := GetPoolFromPoolKey(singlePool) + if pool.balances.token1 > (-1 * amountSpecified) { // must be bigger (can't be equal due to fee) firstSelectedPool = append(firstSelectedPool, singlePool) } @@ -56,14 +72,29 @@ func FindBestPool( } else if zeroForOne == false && amountSpecified > 0 { for _, singlePool := range foundPool { - p := GetPoolFromPoolKey(singlePool) - poolSqrtX96 := p.slot0.sqrtPriceX96 - poolPrice := poolSqrtX96 * poolSqrtX96 / Q96 / Q96 - - pool := GetPoolFromPoolKey(singlePool) - if pool.balances.token0 > amountSpecified/poolPrice { // must be bigger (can't be equal due to fee) - firstSelectedPool = append(firstSelectedPool, singlePool) - } + func() { + defer func() { + if r := recover(); r != nil { + continue + } + }() + + _, _, fee := poolPathDivide(singlePool) + es0, es1 := DrySwap( + tokenA, + tokenB, + fee, + "", + false, + amountSpecified, + MAX_PRICE, + ) + + pool := GetPoolFromPoolKey(singlePool) + if pool.balances.token1 > (-1 * es0) { // must be bigger (can't be equal due to fee) + firstSelectedPool = append(firstSelectedPool, singlePool) + } + }() } } else if zeroForOne == false && amountSpecified < 0 {