Skip to content

Commit

Permalink
Add logic updating reserves after CalAmount in Fluid-Dex (#563)
Browse files Browse the repository at this point in the history
  • Loading branch information
sunspirit99 authored Oct 30, 2024
1 parent e2ef130 commit 8d95194
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 62 deletions.
104 changes: 91 additions & 13 deletions pkg/liquidity-source/fluid/dex-t1/pool_simulator.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,7 @@ func (s *PoolSimulator) CalcAmountIn(param poolpkg.CalcAmountInParams) (*poolpkg
TokenAmountIn: &poolpkg.TokenAmount{Token: param.TokenIn, Amount: amountInAfterFee},
Fee: &poolpkg.TokenAmount{Token: param.TokenIn, Amount: fee},
Gas: defaultGas.Swap,
SwapInfo: StaticExtra{
DexReservesResolver: s.DexReservesResolver,
},
SwapInfo: s.StaticExtra,
}, nil
}

Expand Down Expand Up @@ -318,21 +316,37 @@ func swapInAdjusted(swap0To1 bool, amountToSwap *big.Int, colReserves Collateral
if a.Cmp(bignumber.ZeroBI) <= 0 {
// Entire trade routes through debt pool
amountOutDebt = getAmountOut(amountToSwap, debtIReserveIn, debtIReserveOut)
if amountOutDebt.Cmp(debtReserveOut) > 0 {
return nil, nil, errors.New("insufficient liquidity")
}

updateDebtReserves(swap0To1, amountToSwap, amountOutDebt, debtReserves)
} else if a.Cmp(amountToSwap) >= 0 {
// Entire trade routes through collateral pool
amountOutCollateral = getAmountOut(amountToSwap, colIReserveIn, colIReserveOut)
if amountOutCollateral.Cmp(colReserveOut) > 0 {
return nil, nil, errors.New("insufficient liquidity")
}

updateCollateralReserves(swap0To1, amountToSwap, amountOutCollateral, colReserves)
} else {
// Trade routes through both pools
amountOutCollateral = getAmountOut(a, colIReserveIn, colIReserveOut)
amountOutDebt = getAmountOut(new(big.Int).Sub(amountToSwap, a), debtIReserveIn, debtIReserveOut)
}
var (
amountInCollateral = a
amountInDebt = new(big.Int).Sub(amountToSwap, a)
)

if amountOutDebt.Cmp(debtReserveOut) > 0 {
return nil, nil, errors.New("insufficient liquidity")
}
amountOutCollateral = getAmountOut(amountInCollateral, colIReserveIn, colIReserveOut)
if amountOutCollateral.Cmp(colReserveOut) > 0 {
return nil, nil, errors.New("insufficient liquidity")
}

amountOutDebt = getAmountOut(amountInDebt, debtIReserveIn, debtIReserveOut)
if amountOutDebt.Cmp(debtReserveOut) > 0 {
return nil, nil, errors.New("insufficient liquidity")
}

if amountOutCollateral.Cmp(colReserveOut) > 0 {
return nil, nil, errors.New("insufficient liquidity")
updateBothReserves(swap0To1, amountInCollateral, amountOutCollateral, amountInDebt, amountOutDebt, colReserves, debtReserves)
}

return amountToSwap, new(big.Int).Add(amountOutCollateral, amountOutDebt), nil
Expand Down Expand Up @@ -465,20 +479,31 @@ func swapOutAdjusted(swap0To1 bool, amountOut *big.Int, colReserves CollateralRe
if amountOut.Cmp(debtReserveOut) > 0 {
return nil, nil, errors.New("insufficient liquidity")
}

updateDebtReserves(swap0To1, amountInDebt, amountOut, debtReserves)
} else if a.Cmp(amountOut) >= 0 {
// Entire trade routes through collateral pool
amountInCollateral = getAmountIn(amountOut, colIReserveIn, colIReserveOut)
if amountOut.Cmp(colReserveOut) > 0 {
return nil, nil, errors.New("insufficient liquidity")
}

updateCollateralReserves(swap0To1, amountInCollateral, amountOut, colReserves)
} else {
// Trade routes through both pools
amountInCollateral = getAmountIn(a, colIReserveIn, colIReserveOut)
amountInDebt = getAmountIn(new(big.Int).Sub(amountOut, a), debtIReserveIn, debtIReserveOut)
var (
amountOutCollateral = a
amountOutDebt = new(big.Int).Sub(amountOut, a)
)

amountInCollateral = getAmountIn(amountOutCollateral, colIReserveIn, colIReserveOut)
amountInDebt = getAmountIn(amountOutDebt, debtIReserveIn, debtIReserveOut)

if new(big.Int).Sub(amountOut, a).Cmp(debtReserveOut) > 0 || a.Cmp(debtReserveOut) > 0 {
return nil, nil, errors.New("insufficient liquidity")
}

updateBothReserves(swap0To1, amountInCollateral, amountOutCollateral, amountInDebt, amountOutDebt, colReserves, debtReserves)
}

return new(big.Int).Add(amountInCollateral, amountInDebt), amountOut, nil
Expand Down Expand Up @@ -538,3 +563,56 @@ func swapOut(

return amountIn, amountOut, nil
}

func updateDebtReserves(swap0To1 bool, amountIn, amountOut *big.Int, debtReserves DebtReserves) {
if swap0To1 {
debtReserves.Token0RealReserves.Add(debtReserves.Token0RealReserves, amountIn)
debtReserves.Token0ImaginaryReserves.Add(debtReserves.Token0ImaginaryReserves, amountIn)
debtReserves.Token1RealReserves.Sub(debtReserves.Token1RealReserves, amountOut)
debtReserves.Token1ImaginaryReserves.Sub(debtReserves.Token1ImaginaryReserves, amountOut)
} else {
debtReserves.Token0RealReserves.Sub(debtReserves.Token0RealReserves, amountOut)
debtReserves.Token0ImaginaryReserves.Sub(debtReserves.Token0ImaginaryReserves, amountOut)
debtReserves.Token1RealReserves.Add(debtReserves.Token1RealReserves, amountIn)
debtReserves.Token1ImaginaryReserves.Add(debtReserves.Token1ImaginaryReserves, amountIn)
}
}

func updateCollateralReserves(swap0To1 bool, amountIn, amountOut *big.Int, colReserves CollateralReserves) {
if swap0To1 {
colReserves.Token0RealReserves.Add(colReserves.Token0RealReserves, amountIn)
colReserves.Token0ImaginaryReserves.Add(colReserves.Token0ImaginaryReserves, amountIn)
colReserves.Token1RealReserves.Sub(colReserves.Token1RealReserves, amountOut)
colReserves.Token1ImaginaryReserves.Sub(colReserves.Token1ImaginaryReserves, amountOut)
} else {
colReserves.Token0RealReserves.Sub(colReserves.Token0RealReserves, amountOut)
colReserves.Token0ImaginaryReserves.Sub(colReserves.Token0ImaginaryReserves, amountOut)
colReserves.Token1RealReserves.Add(colReserves.Token1RealReserves, amountIn)
colReserves.Token1ImaginaryReserves.Add(colReserves.Token1ImaginaryReserves, amountIn)
}
}

func updateBothReserves(swap0To1 bool, amountInCollateral, amountOutCollateral, amountInDebt, amountOutDebt *big.Int,
colReserves CollateralReserves, debtReserves DebtReserves) {
if swap0To1 {
colReserves.Token1RealReserves.Sub(colReserves.Token1RealReserves, amountOutCollateral)
colReserves.Token1ImaginaryReserves.Sub(colReserves.Token1ImaginaryReserves, amountOutCollateral)
colReserves.Token0RealReserves.Add(colReserves.Token0RealReserves, amountInCollateral)
colReserves.Token0ImaginaryReserves.Add(colReserves.Token0ImaginaryReserves, amountInCollateral)

debtReserves.Token1RealReserves.Sub(debtReserves.Token1RealReserves, amountOutDebt)
debtReserves.Token1ImaginaryReserves.Sub(debtReserves.Token1ImaginaryReserves, amountOutDebt)
debtReserves.Token0RealReserves.Add(debtReserves.Token0RealReserves, amountInDebt)
debtReserves.Token0ImaginaryReserves.Add(debtReserves.Token0ImaginaryReserves, amountInDebt)
} else {
colReserves.Token1RealReserves.Add(colReserves.Token1RealReserves, amountInCollateral)
colReserves.Token1ImaginaryReserves.Add(colReserves.Token1ImaginaryReserves, amountInCollateral)
colReserves.Token0RealReserves.Sub(colReserves.Token0RealReserves, amountOutCollateral)
colReserves.Token0ImaginaryReserves.Sub(colReserves.Token0ImaginaryReserves, amountOutCollateral)

debtReserves.Token1RealReserves.Add(debtReserves.Token1RealReserves, amountInDebt)
debtReserves.Token1ImaginaryReserves.Add(debtReserves.Token1ImaginaryReserves, amountInDebt)
debtReserves.Token0RealReserves.Sub(debtReserves.Token0RealReserves, amountOutDebt)
debtReserves.Token0ImaginaryReserves.Sub(debtReserves.Token0ImaginaryReserves, amountOutDebt)
}
}
102 changes: 53 additions & 49 deletions pkg/liquidity-source/fluid/dex-t1/pool_simulator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,32 +323,40 @@ func TestPoolSimulator_CalcAmountIn(t *testing.T) {
}
}

var colReservesOne = CollateralReserves{
Token0RealReserves: big.NewInt(20000000006000000),
Token1RealReserves: big.NewInt(20000000000500000),
Token0ImaginaryReserves: big.NewInt(389736659726997981),
Token1ImaginaryReserves: big.NewInt(389736659619871949),
func NewColReservesOne() CollateralReserves {
return CollateralReserves{
Token0RealReserves: big.NewInt(20000000006000000),
Token1RealReserves: big.NewInt(20000000000500000),
Token0ImaginaryReserves: big.NewInt(389736659726997981),
Token1ImaginaryReserves: big.NewInt(389736659619871949),
}
}

var colReservesEmpty = CollateralReserves{
Token0RealReserves: big.NewInt(0),
Token1RealReserves: big.NewInt(0),
Token0ImaginaryReserves: big.NewInt(0),
Token1ImaginaryReserves: big.NewInt(0),
func NewColReservesEmpty() CollateralReserves {
return CollateralReserves{
Token0RealReserves: big.NewInt(0),
Token1RealReserves: big.NewInt(0),
Token0ImaginaryReserves: big.NewInt(0),
Token1ImaginaryReserves: big.NewInt(0),
}
}

var debtReservesEmpty = DebtReserves{
Token0RealReserves: big.NewInt(0),
Token1RealReserves: big.NewInt(0),
Token0ImaginaryReserves: big.NewInt(0),
Token1ImaginaryReserves: big.NewInt(0),
func NewDebtReservesEmpty() DebtReserves {
return DebtReserves{
Token0RealReserves: big.NewInt(0),
Token1RealReserves: big.NewInt(0),
Token0ImaginaryReserves: big.NewInt(0),
Token1ImaginaryReserves: big.NewInt(0),
}
}

var debtReservesOne = DebtReserves{
Token0RealReserves: big.NewInt(9486832995556050),
Token1RealReserves: big.NewInt(9486832993079885),
Token0ImaginaryReserves: big.NewInt(184868330099560759),
Token1ImaginaryReserves: big.NewInt(184868330048879109),
func NewDebtReservesOne() DebtReserves {
return DebtReserves{
Token0RealReserves: big.NewInt(9486832995556050),
Token1RealReserves: big.NewInt(9486832993079885),
Token0ImaginaryReserves: big.NewInt(184868330099560759),
Token1ImaginaryReserves: big.NewInt(184868330048879109),
}
}

func assertSwapInResult(t *testing.T, expected bool, amountIn *big.Int, colReserves CollateralReserves, debtReserves DebtReserves, expectedAmountIn string, expectedAmountOut string) {
Expand All @@ -367,15 +375,15 @@ func assertSwapOutResult(t *testing.T, expected bool, amountOut *big.Int, colRes

func TestPoolSimulator_SwapIn(t *testing.T) {
t.Run("TestPoolSimulator_SwapIn", func(t *testing.T) {
assertSwapInResult(t, true, big.NewInt(1e15), colReservesOne, debtReservesOne, "1000000000000000", "998262697204710")
assertSwapInResult(t, true, big.NewInt(1e15), colReservesEmpty, debtReservesOne, "1000000000000000", "994619847016724")
assertSwapInResult(t, true, big.NewInt(1e15), colReservesOne, debtReservesEmpty, "1000000000000000", "997440731289905")
assertSwapInResult(t, false, big.NewInt(1e15), colReservesOne, debtReservesOne, "1000000000000000", "998262697752553")
assertSwapInResult(t, false, big.NewInt(1e15), colReservesEmpty, debtReservesOne, "1000000000000000", "994619847560607")
assertSwapInResult(t, false, big.NewInt(1e15), colReservesOne, debtReservesEmpty, "1000000000000000", "997440731837532")
assertSwapInResult(t, true, big.NewInt(1e15), NewColReservesOne(), NewDebtReservesOne(), "1000000000000000", "998262697204710")
assertSwapInResult(t, true, big.NewInt(1e15), NewColReservesEmpty(), NewDebtReservesOne(), "1000000000000000", "994619847016724")
assertSwapInResult(t, true, big.NewInt(1e15), NewColReservesOne(), NewDebtReservesEmpty(), "1000000000000000", "997440731289905")
assertSwapInResult(t, false, big.NewInt(1e15), NewColReservesOne(), NewDebtReservesOne(), "1000000000000000", "998262697752553")
assertSwapInResult(t, false, big.NewInt(1e15), NewColReservesEmpty(), NewDebtReservesOne(), "1000000000000000", "994619847560607")
assertSwapInResult(t, false, big.NewInt(1e15), NewColReservesOne(), NewDebtReservesEmpty(), "1000000000000000", "997440731837532")
})
}
func TestPoolSimulator_SwapInCompareEstimateIn(t *testing.T) {
func TestPoolSimulator_swapInAdjusted(t *testing.T) {
t.Run("TestPoolSimulator_SwapInCompareEstimateIn", func(t *testing.T) {
expectedAmountIn := "1000000000000000000"
expectedAmountOut := "1180035404724000000"
Expand All @@ -400,57 +408,53 @@ func TestPoolSimulator_SwapInCompareEstimateIn(t *testing.T) {

require.Equal(t, expectedAmountIn, big.NewInt(0).Mul(inAmt, big.NewInt(1e6)).String())
require.Equal(t, expectedAmountOut, big.NewInt(0).Mul(outAmt, big.NewInt(1e6)).String())

// swapIn should do the conversion for token decimals
_, outAmtSwapIn, _ := swapIn(true, big.NewInt(1e18), colReserves, debtReserves, 18, 18)
require.Equal(t, expectedAmountOut, outAmtSwapIn.String())
})
}

func TestPoolSimulator_SwapOut(t *testing.T) {
t.Run("TestPoolSimulator_SwapOut", func(t *testing.T) {
assertSwapOutResult(t, true, big.NewInt(1e15), colReservesOne, debtReservesOne, "1001743360284199", "1000000000000000")
assertSwapOutResult(t, true, big.NewInt(1e15), colReservesEmpty, debtReservesOne, "1005438674786548", "1000000000000000")
assertSwapOutResult(t, true, big.NewInt(1e15), colReservesOne, debtReservesEmpty, "1002572435818386", "1000000000000000")
assertSwapOutResult(t, false, big.NewInt(1e15), colReservesOne, debtReservesOne, "1001743359733488", "1000000000000000")
assertSwapOutResult(t, false, big.NewInt(1e15), colReservesEmpty, debtReservesOne, "1005438674233767", "1000000000000000")
assertSwapOutResult(t, false, big.NewInt(1e15), colReservesOne, debtReservesEmpty, "1002572435266527", "1000000000000000")
assertSwapOutResult(t, true, big.NewInt(1e15), NewColReservesOne(), NewDebtReservesOne(), "1001743360284199", "1000000000000000")
assertSwapOutResult(t, true, big.NewInt(1e15), NewColReservesEmpty(), NewDebtReservesOne(), "1005438674786548", "1000000000000000")
assertSwapOutResult(t, true, big.NewInt(1e15), NewColReservesOne(), NewDebtReservesEmpty(), "1002572435818386", "1000000000000000")
assertSwapOutResult(t, false, big.NewInt(1e15), NewColReservesOne(), NewDebtReservesOne(), "1001743359733488", "1000000000000000")
assertSwapOutResult(t, false, big.NewInt(1e15), NewColReservesEmpty(), NewDebtReservesOne(), "1005438674233767", "1000000000000000")
assertSwapOutResult(t, false, big.NewInt(1e15), NewColReservesOne(), NewDebtReservesEmpty(), "1002572435266527", "1000000000000000")
})
}

func TestPoolSimulator_SwapInOut(t *testing.T) {
t.Run("TestPoolSimulator_SwapInOut", func(t *testing.T) {
assertSwapInResult(t, true, big.NewInt(1e15), colReservesOne, debtReservesOne, "1000000000000000", "998262697204710")
assertSwapInResult(t, true, big.NewInt(1e15), NewColReservesOne(), NewDebtReservesOne(), "1000000000000000", "998262697204710")

assertSwapOutResult(t, true, big.NewInt(998262697204710), colReservesOne, debtReservesOne, "999999999999998", "998262697204710")
assertSwapOutResult(t, true, big.NewInt(998262697204710), NewColReservesOne(), NewDebtReservesOne(), "999999999999998", "998262697204710")

assertSwapInResult(t, false, big.NewInt(1e15), colReservesOne, debtReservesOne, "1000000000000000", "998262697752553")
assertSwapInResult(t, false, big.NewInt(1e15), NewColReservesOne(), NewDebtReservesOne(), "1000000000000000", "998262697752553")

assertSwapOutResult(t, false, big.NewInt(998262697752553), colReservesOne, debtReservesOne, "999999999999998", "998262697752553")
assertSwapOutResult(t, false, big.NewInt(998262697752553), NewColReservesOne(), NewDebtReservesOne(), "999999999999998", "998262697752553")
})
}

func TestPoolSimulator_SwapInOutDebtEmpty(t *testing.T) {
t.Run("TestPoolSimulator_SwapInOutDebtEmpty", func(t *testing.T) {
assertSwapInResult(t, true, big.NewInt(1e15), colReservesEmpty, debtReservesOne, "1000000000000000", "994619847016724")
assertSwapInResult(t, true, big.NewInt(1e15), NewColReservesEmpty(), NewDebtReservesOne(), "1000000000000000", "994619847016724")

assertSwapOutResult(t, true, big.NewInt(994619847016724), colReservesEmpty, debtReservesOne, "999999999999999", "994619847016724")
assertSwapOutResult(t, true, big.NewInt(994619847016724), NewColReservesEmpty(), NewDebtReservesOne(), "999999999999999", "994619847016724")

assertSwapInResult(t, false, big.NewInt(1e15), colReservesEmpty, debtReservesOne, "1000000000000000", "994619847560607")
assertSwapInResult(t, false, big.NewInt(1e15), NewColReservesEmpty(), NewDebtReservesOne(), "1000000000000000", "994619847560607")

assertSwapOutResult(t, false, big.NewInt(994619847560607), colReservesEmpty, debtReservesOne, "999999999999999", "994619847560607")
assertSwapOutResult(t, false, big.NewInt(994619847560607), NewColReservesEmpty(), NewDebtReservesOne(), "999999999999999", "994619847560607")
})

}

func TestPoolSimulator_SwapInOutColEmpty(t *testing.T) {
t.Run("TestPoolSimulator_SwapInOutColEmpty", func(t *testing.T) {
assertSwapInResult(t, true, big.NewInt(1e15), colReservesOne, debtReservesEmpty, "1000000000000000", "997440731289905")
assertSwapInResult(t, true, big.NewInt(1e15), NewColReservesOne(), NewDebtReservesEmpty(), "1000000000000000", "997440731289905")

assertSwapOutResult(t, true, big.NewInt(997440731289905), colReservesOne, debtReservesEmpty, "999999999999999", "997440731289905")
assertSwapOutResult(t, true, big.NewInt(997440731289905), NewColReservesOne(), NewDebtReservesEmpty(), "999999999999999", "997440731289905")

assertSwapInResult(t, false, big.NewInt(1e15), colReservesOne, debtReservesEmpty, "1000000000000000", "997440731837532")
assertSwapInResult(t, false, big.NewInt(1e15), NewColReservesOne(), NewDebtReservesEmpty(), "1000000000000000", "997440731837532")

assertSwapOutResult(t, false, big.NewInt(997440731837532), colReservesOne, debtReservesEmpty, "999999999999999", "997440731837532")
assertSwapOutResult(t, false, big.NewInt(997440731837532), NewColReservesOne(), NewDebtReservesEmpty(), "999999999999999", "997440731837532")
})
}

0 comments on commit 8d95194

Please sign in to comment.