Skip to content

Commit

Permalink
Merge pull request #72 from gnoswap-labs/GSW-403-feat-router-rpc
Browse files Browse the repository at this point in the history
GSW-403 feat: route rpc
  • Loading branch information
r3v4s committed Oct 13, 2023
2 parents b47bb40 + c295354 commit 1ccfda4
Show file tree
Hide file tree
Showing 9 changed files with 420 additions and 129 deletions.
136 changes: 136 additions & 0 deletions pool/_TEST_math_logic_test.gnoa
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package pool

import (
"std"
"testing"

"gno.land/p/demo/testutils"

pos "gno.land/r/position"
)

var (
gsa = testutils.TestAddress("gsa")
lp01 = testutils.TestAddress("lp01")

pToken0 = "foo"
pToken1 = "bar"
pFee uint16 = 500
sqrtPrice bigint = 130621891405341611593710811006

tickLower int32 = 9000
tickUpper int32 = 11000
liquidityAmount bigint = 123456789
currentTick int32 = 10000
)

func init() {
std.TestSetOrigCaller(gsa)
InitManual()
CreatePool(pToken0, pToken1, pFee, sqrtPrice)
}

func TestGetSqrtRatioFromTick(t *testing.T) {
sqrtX96 := GetSqrtRatioFromTick(currentTick)
shouldEQ(t, sqrtX96, sqrtPrice)
}

func TestGetTickFromSqrtRatio(t *testing.T) {
tick := GetTickFromSqrtRatio(sqrtPrice)
shouldEQ(t, tick, 9999) // currentTick - 1
}

func TestDrySwap_ZeroForOneTrue_AmountSpecified_Positive_16000(t *testing.T) {
std.TestSetOrigCaller(lp01)

// no mint == no liquidity => swap will fail
shouldPanic(t, func() { DrySwap(pToken0, pToken1, pFee, "_", true, 16000, MIN_PRICE) })

// not enough mint == swap will fail
pos.Mint(pToken0, pToken1, pFee, tickLower, tickUpper, 1000, 1000, 0, 0, 9999999999)
shouldPanic(t, func() { DrySwap(pToken0, pToken1, pFee, "_", true, 16000, MIN_PRICE) })

pos.Mint(pToken0, pToken1, pFee, tickLower, tickUpper, 100000, 100000, 0, 0, 9999999999)

// zeroForOne true
// amountSpecified 16000
input, output := DrySwap(
pToken0, // pToken0
pToken1, // pToken1
pFee, // pFee
"_", // recipient
true, // zeroForOne
16000, // amountSpecified
MIN_PRICE, // sqrtPriceLimitX96
)
shouldEQ(t, input, bigint(16000))
shouldEQ(t, output, bigint(-42574))
}

func TestDrySwap_ZeroForOneTrue_AmountSpecified_Negative_16000(t *testing.T) {
// zeroForOne true
// amountSpecified -16000

input, output := DrySwap(
pToken0, // pToken0
pToken1, // pToken1
pFee, // pFee
"_", // recipient
true, // zeroForOne
-16000, // amountSpecified
MIN_SQRT_RATIO+1, // sqrtPriceLimitX96
)

shouldEQ(t, input, bigint(5934))
shouldEQ(t, output, bigint(-15999))
}

func TestDrySwap_ZeroForOneFalse_AmountSpecified_Positive_16000(t *testing.T) {
// zeroForOne false
// amountSpecified 16000

input, output := DrySwap(
pToken0, // pToken0
pToken1, // pToken1
pFee, // pFee
"_", // recipient
false, // zeroForOne
16000, // amountSpecified
MAX_SQRT_RATIO-1, // sqrtPriceLimitX96
)
shouldEQ(t, input, bigint(-42574))
shouldEQ(t, output, bigint(16000))
}

func TestDrySwap_ZeroForOneFalse_AmountSpecified_Negative_16000(t *testing.T) {
// zeroForOne false
// amountSpecified -16000

input, output := DrySwap(
pToken0, // pToken0
pToken1, // pToken1
pFee, // pFee
"_", // recipient
false, // zeroForOne
-16000, // amountSpecified
MAX_SQRT_RATIO-1, // sqrtPriceLimitX96
)
shouldEQ(t, input, bigint(-15999))
shouldEQ(t, output, bigint(5934))
}

/* HELPER */
func shouldEQ(t *testing.T, got, expected interface{}) {
if got != expected {
t.Errorf("got %v, expected %v", got, expected)
}
}

func shouldPanic(t *testing.T, f func()) {
defer func() {
if r := recover(); r == nil {
t.Errorf("expected panic")
}
}()
f()
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
160 changes: 160 additions & 0 deletions pool/_TEST_pool_router_test.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package pool

import (
"std"
"testing"

"gno.land/p/demo/testutils"
"gno.land/r/demo/users"

bar "gno.land/r/bar"
foo "gno.land/r/foo"

pos "gno.land/r/position"
)

var (
gsa = testutils.TestAddress("gsa") // Gnoswap Admin
lp01 = testutils.TestAddress("lp01") // Liquidity Provider 01

poolAddr = std.DerivePkgAddr("gno.land/r/pool")
)

// 1. Init
func TestInitManual(t *testing.T) {
std.TestSetOrigCaller(gsa)
InitManual()
std.TestSkipHeights(1)
}

func TestCreatePool(t *testing.T) {
CreatePool("foo", "bar", uint16(500), 5602223755577321903022134995689) // 85_176 == x4999.904
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) {
std.TestSetOrigCaller(lp01)

_, _, m0, m1 := pos.Mint(
"foo", // token0
"bar", // token1
uint16(500), // fee 500 ~= tickSpacing 10
84220, // tickLower // x4544
86130, // tickUpper // x5500
30000000, // amount0Desired
30000000, // 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)
}

func TestPositionMint3000(t *testing.T) {
std.TestSetOrigCaller(lp01)

_, _, m0, m1 := pos.Mint(
"foo", // token0
"bar", // token1
uint16(3000), // fee 3000 ~= tickSpacing 60
22800, // tickLower
24000, // tickUpper
1000, // amount0Desired
1000, // amount1Desired
0, // amount0Min
0, // amount1Min
9999999999, // deadline
)
shouldEQ(t, m0, bigint(79))
shouldEQ(t, m1, bigint(999))
}

func TestFindBestPoolTruePositive(t *testing.T) {
bestPath := FindBestPool(
"foo", // tokenA
"bar", // tokenB
true, // zeroForOne
500, // amountSpecified
)
shouldEQ(t, bestPath, "bar_foo_500")
}

func TestFindBestPoolTrueNegative(t *testing.T) {
bestPath := FindBestPool(
"foo", // tokenA
"bar", // tokenB
true, // zeroForOne
-5000, // amountSpecified
)
shouldEQ(t, bestPath, "bar_foo_500")
}

func TestFindBestPoolFalsePositive(t *testing.T) {
bestPath := FindBestPool(
"foo", // tokenA
"bar", // tokenB
false, // zeroForOne
50, // amountSpecified
)
shouldEQ(t, bestPath, "bar_foo_3000")
}

func TestFindBestPoolFalseNegative(t *testing.T) {
bestPath := FindBestPool(
"foo", // tokenA
"bar", // tokenB
false, // zeroForOne
-1234, // amountSpecified
)
shouldEQ(t, bestPath, "bar_foo_500")
}

func TestFindBestPoolWrong(t *testing.T) {
shouldPanic(t, func() { FindBestPool("foo", "bar", true, 0) })
}

/* HELPER */
func shouldEQ(t *testing.T, got, expected interface{}) {
if got != expected {
t.Errorf("got %v, expected %v", got, expected)
}
}

func shouldPanic(t *testing.T, f func()) {
defer func() {
if r := recover(); r == nil {
t.Errorf("expected panic")
}
}()
f()
}

func fooBalance(addr std.Address) uint64 {
user := users.AddressOrName(addr)
return foo.BalanceOf(user)
}

func barBalance(addr std.Address) uint64 {
user := users.AddressOrName(addr)
return bar.BalanceOf(user)
}
File renamed without changes.
Loading

0 comments on commit 1ccfda4

Please sign in to comment.