Skip to content

Commit

Permalink
Vt/syncswapv2 stable bug fix (#647)
Browse files Browse the repository at this point in the history
* stable helper test script

* clean

* fix wrong usage of param A for syncswapv2 stable pool
  • Loading branch information
tien7668 authored Dec 12, 2024
1 parent 03decbb commit ddeff0d
Show file tree
Hide file tree
Showing 5 changed files with 1,053 additions and 147 deletions.
18 changes: 9 additions & 9 deletions pkg/liquidity-source/syncswapv2/stable/math.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func _getAmountIn(
return integer.One()
}

x := getY(y, d)
x := getY(y, d, A)

// amountIn = MAX_FEE * (x - adjustedReserveIn) / (MAX_FEE - swapFee) + 1;
// amountIn /= tokenInPrecisionMultiplier;
Expand Down Expand Up @@ -87,7 +87,7 @@ func getExactQuote(
var d = computeDFromAdjustedBalances(adjustedReserveIn, adjustedReserveOut, A)

var x = new(uint256.Int).Add(adjustedReserveIn, new(uint256.Int).Mul(feeDeductedAmountIn, tokenInPrecisionMultiplier))
var y = getY(x, d)
var y = getY(x, d, A)

// (adjustedReserveOut - y - 1) / tokenOutPrecisionMultiplier
if adjustedReserveOut.Cmp(new(uint256.Int).Add(y, constant.One)) < 0 {
Expand All @@ -107,6 +107,7 @@ func calAmountAfterFee(amountIn, swapFee *uint256.Int) (*uint256.Int, *uint256.I
}

func computeDFromAdjustedBalances(xp0, xp1 *uint256.Int, A *uint256.Int) *uint256.Int {
nA := new(uint256.Int).Mul(A, constant.Two)
var computed = uint256.NewInt(0)

var s = new(uint256.Int).Add(xp0, xp1)
Expand All @@ -126,12 +127,12 @@ func computeDFromAdjustedBalances(xp0, xp1 *uint256.Int, A *uint256.Int) *uint25
//d = (((2000 * s) + 2 * dP) * d) / ((2000 - 1) * d + 3 * dP);
num := new(uint256.Int)
den := new(uint256.Int)
d = num.Mul(A, s).Add(
d = num.Mul(nA, s).Add(
num,
new(uint256.Int).Mul(constant.Two, dp),
).Mul(num, d).Div(
num,
den.Sub(A, constant.One).Mul(den, d).Add(
den.Sub(nA, constant.One).Mul(den, d).Add(
den,
new(uint256.Int).Mul(constant.Three, dp),
),
Expand All @@ -145,21 +146,20 @@ func computeDFromAdjustedBalances(xp0, xp1 *uint256.Int, A *uint256.Int) *uint25
return computed
}

func getY(x, d *uint256.Int) *uint256.Int {
var twoThousand = uint256.NewInt(2000)
var doubleTwoThousand = uint256.NewInt(4000)
func getY(x, d, A *uint256.Int) *uint256.Int {
nA := new(uint256.Int).Mul(A, constant.Two)

c := new(uint256.Int)
//uint c = (d * d) / (x * 2);
//c = (c * d) / 4000;
c.Div(
c.Set(d).Mul(c, d),
new(uint256.Int).Mul(x, constant.Two),
).Mul(c, d).Div(c, doubleTwoThousand)
).Mul(c, d).Div(c, nA).Div(c, constant.Two)

b := new(uint256.Int)
//uint b = x + (d / 2000);
b.Set(d).Div(b, twoThousand).Add(b, x)
b.Set(d).Div(b, nA).Add(b, x)
var yPrev *uint256.Int
var y = d

Expand Down
148 changes: 10 additions & 138 deletions pkg/liquidity-source/syncswapv2/stable/pool_simulator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,69 +20,36 @@ func TestGetAmountOut(t *testing.T) {
expectedAmountOut *poolPkg.TokenAmount
expectedErr error
}{
{
name: "test token0 as tokenIn",
entityPool: entity.Pool{
Address: "0x92eae0b3a75f3ef6c50369ce8ca96b285d2139b8",
Exchange: "syncswap",
Type: "syncswap-stable",
Reserves: []string{
"276926762767",
"284081796016",
},
Tokens: []*entity.PoolToken{
{
Address: "0x3355df6d4c9c3035724fd0e3914de96a5a83aaf4",
Swappable: true,
},
{
Address: "0xfc7e56298657b002b3e656400e746b7212912757",
Swappable: true,
},
},
Extra: "{\"swapFee0To1\":40,\"swapFee1To0\":40,\"token0PrecisionMultiplier\":1000000000000,\"token1PrecisionMultiplier\":1000000000000,\"A\":2000}",
},
tokenAmountIn: poolPkg.TokenAmount{
Token: "0x3355df6d4c9c3035724fd0e3914de96a5a83aaf4",
Amount: bignumber.NewBig("100000000000"),
},
tokenOut: "0xfc7e56298657b002b3e656400e746b7212912757",
expectedAmountOut: &poolPkg.TokenAmount{
Token: "0xfc7e56298657b002b3e656400e746b7212912757",
Amount: bignumber.NewBig("99922559468"),
},
expectedErr: nil,
},
{
name: "test token1 as tokenIn",
entityPool: entity.Pool{
Address: "0x92eae0b3a75f3ef6c50369ce8ca96b285d2139b8",
Exchange: "syncswap",
Type: "syncswap-stable",
Address: "0xd5a1a9680f083237c10c6357e72b37cafe1fb5de",
Exchange: "syncswapv2-stable",
Type: "syncswapv2-stable",
Reserves: []string{
"276838614939",
"284170002373",
"1771167531",
"8079308863505801735196",
},
Tokens: []*entity.PoolToken{
{
Address: "0x3355df6d4c9c3035724fd0e3914de96a5a83aaf4",
Swappable: true,
},
{
Address: "0xfc7e56298657b002b3e656400e746b7212912757",
Address: "0x5fc44e95eaa48f9eb84be17bd3ac66b6a82af709",
Swappable: true,
},
},
Extra: "{\"swapFee0To1\":40,\"swapFee1To0\":40,\"token0PrecisionMultiplier\":1000000000000,\"token1PrecisionMultiplier\":1000000000000,\"A\":2000}",
Extra: "{\"swapFee0To1\":100,\"swapFee1To0\":100,\"token0PrecisionMultiplier\":1000000000000,\"token1PrecisionMultiplier\":1,\"A\":80}",
},
tokenAmountIn: poolPkg.TokenAmount{
Token: "0xfc7e56298657b002b3e656400e746b7212912757",
Amount: bignumber.NewBig("100000000000"),
Token: "0x5fc44e95eaa48f9eb84be17bd3ac66b6a82af709",
Amount: bignumber.NewBig("100000000000000000000"),
},
tokenOut: "0x3355df6d4c9c3035724fd0e3914de96a5a83aaf4",
expectedAmountOut: &poolPkg.TokenAmount{
Token: "0x3355df6d4c9c3035724fd0e3914de96a5a83aaf4",
Amount: bignumber.NewBig("99915796719"),
Amount: bignumber.NewBig("95366156"),
},
expectedErr: nil,
},
Expand All @@ -105,98 +72,3 @@ func TestGetAmountOut(t *testing.T) {
})
}
}

func TestGetAmountIn(t *testing.T) {
testCases := []struct {
name string
entityPool entity.Pool
tokenAmountOut poolPkg.TokenAmount
tokenIn string
expectedAmountIn *poolPkg.TokenAmount
expectedErr error
}{
{
name: "test token0 as tokenIn",
entityPool: entity.Pool{
Address: "0x92eae0b3a75f3ef6c50369ce8ca96b285d2139b8",
Exchange: "syncswap",
Type: "syncswap-stable",
Reserves: []string{
"276926762767",
"284081796016",
},
Tokens: []*entity.PoolToken{
{
Address: "0x3355df6d4c9c3035724fd0e3914de96a5a83aaf4",
Swappable: true,
},
{
Address: "0xfc7e56298657b002b3e656400e746b7212912757",
Swappable: true,
},
},
Extra: "{\"swapFee0To1\":40,\"swapFee1To0\":40,\"token0PrecisionMultiplier\":1000000000000,\"token1PrecisionMultiplier\":1000000000000,\"A\":2000}",
},
tokenAmountOut: poolPkg.TokenAmount{
Token: "0xfc7e56298657b002b3e656400e746b7212912757",
Amount: bignumber.NewBig("100000000000"),
},
tokenIn: "0x3355df6d4c9c3035724fd0e3914de96a5a83aaf4",
expectedAmountIn: &poolPkg.TokenAmount{
Token: "0x3355df6d4c9c3035724fd0e3914de96a5a83aaf4",
Amount: bignumber.NewBig("100077539910"),
},
expectedErr: nil,
},
{
name: "test token1 as tokenIn",
entityPool: entity.Pool{
Address: "0x92eae0b3a75f3ef6c50369ce8ca96b285d2139b8",
Exchange: "syncswap",
Type: "syncswap-stable",
Reserves: []string{
"276838614939",
"284170002373",
},
Tokens: []*entity.PoolToken{
{
Address: "0x3355df6d4c9c3035724fd0e3914de96a5a83aaf4",
Swappable: true,
},
{
Address: "0xfc7e56298657b002b3e656400e746b7212912757",
Swappable: true,
},
},
Extra: "{\"swapFee0To1\":40,\"swapFee1To0\":40,\"token0PrecisionMultiplier\":1000000000000,\"token1PrecisionMultiplier\":1000000000000,\"A\":2000}",
},
tokenAmountOut: poolPkg.TokenAmount{
Token: "0x3355df6d4c9c3035724fd0e3914de96a5a83aaf4",
Amount: bignumber.NewBig("100000000000"),
},
tokenIn: "0xfc7e56298657b002b3e656400e746b7212912757",
expectedAmountIn: &poolPkg.TokenAmount{
Token: "0xfc7e56298657b002b3e656400e746b7212912757",
Amount: bignumber.NewBig("100084320367"),
},
expectedErr: nil,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
pool, err := NewPoolSimulator(tc.entityPool)
assert.Nil(t, err)
calcAmountInResult, err := testutil.MustConcurrentSafe[*poolPkg.CalcAmountInResult](t, func() (any, error) {
return pool.CalcAmountIn(poolPkg.CalcAmountInParams{
TokenAmountOut: tc.tokenAmountOut,
TokenIn: tc.tokenIn,
Limit: nil,
})
})

assert.Equal(t, tc.expectedErr, err)
assert.Equalf(t, tc.expectedAmountIn.Amount, calcAmountInResult.TokenAmountIn.Amount, "expected amount in %s, got %s", tc.expectedAmountIn.Amount.String(), calcAmountInResult.TokenAmountIn.Amount.String())
})
}
}
Loading

0 comments on commit ddeff0d

Please sign in to comment.