Skip to content

Commit

Permalink
refactor(CL): convert priceLimit API in swaps to BigDec (#6368)
Browse files Browse the repository at this point in the history
* refactor(CL): convert priceLimit API in swaps to BigDec

* changelog

* comment updates

* remove unused constant

* fix test

* tests for GetSqrtPriceLimit

* Update x/concentrated-liquidity/swapstrategy/swap_strategy.go

Co-authored-by: Alpo <[email protected]>

* clarifying comment

---------

Co-authored-by: Alpo <[email protected]>
  • Loading branch information
p0mvn and AlpinYukseloglu authored Sep 14, 2023
1 parent 39341fa commit 3f15d3d
Show file tree
Hide file tree
Showing 14 changed files with 225 additions and 101 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

* [#6256](https://github.com/osmosis-labs/osmosis/pull/6256) Refactor CalcPriceToTick to operate on BigDec price to support new price range.
* [#6317](https://github.com/osmosis-labs/osmosis/pull/6317) Remove price return from CL `math.TickToSqrtPrice`
* [#6368](https://github.com/osmosis-labs/osmosis/pull/6368) Convert priceLimit API in CL swaps to BigDec
* [#6371](https://github.com/osmosis-labs/osmosis/pull/6371) Change PoolI.SpotPrice API from Dec (18 decimals) to BigDec (36 decimals), maintain state-compatibility.

### Client Breaks
Expand Down
10 changes: 5 additions & 5 deletions x/concentrated-liquidity/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func (k Keeper) SwapOutAmtGivenIn(
tokenIn sdk.Coin,
tokenOutDenom string,
spreadFactor osmomath.Dec,
priceLimit osmomath.Dec) (calcTokenIn, calcTokenOut sdk.Coin, poolUpdates PoolUpdates, err error) {
priceLimit osmomath.BigDec) (calcTokenIn, calcTokenOut sdk.Coin, poolUpdates PoolUpdates, err error) {
return k.swapOutAmtGivenIn(ctx, sender, pool, tokenIn, tokenOutDenom, spreadFactor, priceLimit)
}

Expand All @@ -70,7 +70,7 @@ func (k Keeper) ComputeOutAmtGivenIn(
tokenInMin sdk.Coin,
tokenOutDenom string,
spreadFactor osmomath.Dec,
priceLimit osmomath.Dec,
priceLimit osmomath.BigDec,

) (swapResult SwapResult, poolUpdates PoolUpdates, err error) {
return k.computeOutAmtGivenIn(ctx, poolId, tokenInMin, tokenOutDenom, spreadFactor, priceLimit)
Expand All @@ -83,7 +83,7 @@ func (k Keeper) SwapInAmtGivenOut(
desiredTokenOut sdk.Coin,
tokenInDenom string,
spreadFactor osmomath.Dec,
priceLimit osmomath.Dec) (calcTokenIn, calcTokenOut sdk.Coin, poolUpdates PoolUpdates, err error) {
priceLimit osmomath.BigDec) (calcTokenIn, calcTokenOut sdk.Coin, poolUpdates PoolUpdates, err error) {
return k.swapInAmtGivenOut(ctx, sender, pool, desiredTokenOut, tokenInDenom, spreadFactor, priceLimit)
}

Expand All @@ -92,7 +92,7 @@ func (k Keeper) ComputeInAmtGivenOut(
desiredTokenOut sdk.Coin,
tokenInDenom string,
spreadFactor osmomath.Dec,
priceLimit osmomath.Dec,
priceLimit osmomath.BigDec,
poolId uint64,

) (swapResult SwapResult, poolUpdates PoolUpdates, err error) {
Expand Down Expand Up @@ -321,7 +321,7 @@ func (k Keeper) GetLargestSupportedUptimeDuration(ctx sdk.Context) time.Duration

func (k Keeper) SetupSwapStrategy(ctx sdk.Context, p types.ConcentratedPoolExtension,
spreadFactor osmomath.Dec, tokenInDenom string,
priceLimit osmomath.Dec) (strategy swapstrategy.SwapStrategy, sqrtPriceLimit osmomath.BigDec, err error) {
priceLimit osmomath.BigDec) (strategy swapstrategy.SwapStrategy, sqrtPriceLimit osmomath.BigDec, err error) {
return k.setupSwapStrategy(p, spreadFactor, tokenInDenom, priceLimit)
}

Expand Down
4 changes: 2 additions & 2 deletions x/concentrated-liquidity/fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ func (s *KeeperTestSuite) swap(pool types.ConcentratedPoolExtension, swapInFunde
// // Execute swap
fmt.Printf("swap in: %s\n", swapInFunded)
cacheCtx, writeOutGivenIn := s.Ctx.CacheContext()
_, tokenOut, _, err := s.clk.SwapOutAmtGivenIn(cacheCtx, s.TestAccs[0], pool, swapInFunded, swapOutDenom, pool.GetSpreadFactor(s.Ctx), osmomath.ZeroDec())
_, tokenOut, _, err := s.clk.SwapOutAmtGivenIn(cacheCtx, s.TestAccs[0], pool, swapInFunded, swapOutDenom, pool.GetSpreadFactor(s.Ctx), osmomath.ZeroBigDec())
if errors.As(err, &types.InvalidAmountCalculatedError{}) {
// If the swap we're about to execute will not generate enough output, we skip the swap.
// it would error for a real user though. This is good though, since that user would just be burning funds.
Expand All @@ -307,7 +307,7 @@ func (s *KeeperTestSuite) swap(pool types.ConcentratedPoolExtension, swapInFunde
// We expect the returned amountIn to be roughly equal to the original swapInFunded.
cacheCtx, _ = s.Ctx.CacheContext()
fmt.Printf("swap out: %s\n", tokenOut)
amountInSwapResult, _, _, err := s.clk.SwapInAmtGivenOut(cacheCtx, s.TestAccs[0], pool, tokenOut, swapInFunded.Denom, pool.GetSpreadFactor(s.Ctx), osmomath.ZeroDec())
amountInSwapResult, _, _, err := s.clk.SwapInAmtGivenOut(cacheCtx, s.TestAccs[0], pool, tokenOut, swapInFunded.Denom, pool.GetSpreadFactor(s.Ctx), osmomath.ZeroBigDec())
if errors.As(err, &types.InvalidAmountCalculatedError{}) {
// If the swap we're about to execute will not generate enough output, we skip the swap.
// it would error for a real user though. This is good though, since that user would just be burning funds.
Expand Down
4 changes: 2 additions & 2 deletions x/concentrated-liquidity/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ func (s *KeeperTestSuite) swapToMinTickAndBack(spreadFactor osmomath.Dec, incent
actualSwappedInZeroForOne, tokenOut, _, err := s.App.ConcentratedLiquidityKeeper.SwapOutAmtGivenIn(
s.Ctx, swapper, pool,
coinZeroIn, pool.GetToken1(),
spreadFactor, osmomath.ZeroDec(),
spreadFactor, osmomath.ZeroBigDec(),
)
s.Require().NoError(err)

Expand All @@ -562,7 +562,7 @@ func (s *KeeperTestSuite) swapToMinTickAndBack(spreadFactor osmomath.Dec, incent
actualSwappedInOneForZero, inverseTokenOut, _, err := s.App.ConcentratedLiquidityKeeper.SwapOutAmtGivenIn(
s.Ctx, swapper, pool,
tokenOut, pool.GetToken0(),
spreadFactor, osmomath.ZeroDec(),
spreadFactor, osmomath.ZeroBigDec(),
)
s.Require().NoError(err)

Expand Down
2 changes: 1 addition & 1 deletion x/concentrated-liquidity/position_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1796,7 +1796,7 @@ func (s *KeeperTestSuite) TestTickRoundingEdgeCase() {
swapAddr := testAccs[2]
desiredTokenOut := sdk.NewCoin(USDC, osmomath.NewInt(10000))
s.FundAcc(swapAddr, sdk.NewCoins(sdk.NewCoin(ETH, osmomath.NewInt(1000000000000000000))))
_, _, _, err := s.clk.SwapInAmtGivenOut(s.Ctx, swapAddr, pool, desiredTokenOut, ETH, osmomath.ZeroDec(), osmomath.ZeroDec())
_, _, _, err := s.clk.SwapInAmtGivenOut(s.Ctx, swapAddr, pool, desiredTokenOut, ETH, osmomath.ZeroDec(), osmomath.ZeroBigDec())
s.Require().NoError(err)

// Both positions should be able to withdraw successfully
Expand Down
4 changes: 2 additions & 2 deletions x/concentrated-liquidity/range_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ func (s *KeeperTestSuite) executeRandomizedSwap(pool types.ConcentratedPoolExten
}

// Note that we set the price limit to zero to ensure that the swap can execute in either direction (gets automatically set to correct limit)
swappedIn, swappedOut, _, err := s.clk.SwapInAmtGivenOut(s.Ctx, swapAddress, pool, swapOutCoin, swapInDenom, pool.GetSpreadFactor(s.Ctx), osmomath.ZeroDec())
swappedIn, swappedOut, _, err := s.clk.SwapInAmtGivenOut(s.Ctx, swapAddress, pool, swapOutCoin, swapInDenom, pool.GetSpreadFactor(s.Ctx), osmomath.ZeroBigDec())
s.Require().NoError(err)

return swappedIn, swappedOut
Expand Down Expand Up @@ -439,7 +439,7 @@ func (s *KeeperTestSuite) getInitialPositionAssets(pool types.ConcentratedPoolEx

// Calculate asset amounts that would be required to get the required spot price (rounding up on asset1 to ensure we stay in the intended tick)
asset0Amount := osmomath.NewInt(100000000000000)
asset1Amount := osmomath.NewDecFromInt(asset0Amount).Mul(requiredPrice.Dec()).Ceil().TruncateInt()
asset1Amount := osmomath.BigDecFromDec(osmomath.NewDecFromInt(asset0Amount)).Mul(requiredPrice).Ceil().Dec().TruncateInt()

assetCoins := sdk.NewCoins(
sdk.NewCoin(pool.GetToken0(), asset0Amount),
Expand Down
16 changes: 8 additions & 8 deletions x/concentrated-liquidity/spread_rewards_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1371,16 +1371,16 @@ func (s *KeeperTestSuite) TestFunctional_SpreadRewards_Swaps() {
}

// Swap multiple times USDC for ETH, therefore increasing the spot price
ticksActivatedAfterEachSwap, totalSpreadRewardsExpected, _, _ := s.swapAndTrackXTimesInARow(clPool.GetId(), DefaultCoin1, ETH, types.MaxSpotPrice, positions.numSwaps)
ticksActivatedAfterEachSwap, totalSpreadRewardsExpected, _, _ := s.swapAndTrackXTimesInARow(clPool.GetId(), DefaultCoin1, ETH, types.MaxSpotPriceBigDec, positions.numSwaps)
s.CollectAndAssertSpreadRewards(s.Ctx, clPool.GetId(), totalSpreadRewardsExpected, positionIds, [][]int64{ticksActivatedAfterEachSwap}, onlyUSDC, positions)

// Swap multiple times ETH for USDC, therefore decreasing the spot price
ticksActivatedAfterEachSwap, totalSpreadRewardsExpected, _, _ = s.swapAndTrackXTimesInARow(clPool.GetId(), DefaultCoin0, USDC, types.MinSpotPrice, positions.numSwaps)
ticksActivatedAfterEachSwap, totalSpreadRewardsExpected, _, _ = s.swapAndTrackXTimesInARow(clPool.GetId(), DefaultCoin0, USDC, types.MinSpotPriceBigDec, positions.numSwaps)
s.CollectAndAssertSpreadRewards(s.Ctx, clPool.GetId(), totalSpreadRewardsExpected, positionIds, [][]int64{ticksActivatedAfterEachSwap}, onlyETH, positions)

// Do the same swaps as before, however this time we collect spread rewards after both swap directions are complete.
ticksActivatedAfterEachSwapUp, totalSpreadRewardsExpectedUp, _, _ := s.swapAndTrackXTimesInARow(clPool.GetId(), DefaultCoin1, ETH, types.MaxSpotPrice, positions.numSwaps)
ticksActivatedAfterEachSwapDown, totalSpreadRewardsExpectedDown, _, _ := s.swapAndTrackXTimesInARow(clPool.GetId(), DefaultCoin0, USDC, types.MinSpotPrice, positions.numSwaps)
ticksActivatedAfterEachSwapUp, totalSpreadRewardsExpectedUp, _, _ := s.swapAndTrackXTimesInARow(clPool.GetId(), DefaultCoin1, ETH, types.MaxSpotPriceBigDec, positions.numSwaps)
ticksActivatedAfterEachSwapDown, totalSpreadRewardsExpectedDown, _, _ := s.swapAndTrackXTimesInARow(clPool.GetId(), DefaultCoin0, USDC, types.MinSpotPriceBigDec, positions.numSwaps)
totalSpreadRewardsExpected = totalSpreadRewardsExpectedUp.Add(totalSpreadRewardsExpectedDown...)

// We expect all positions to have both denoms in their spread reward accumulators except USDC for the overlapping range position since
Expand Down Expand Up @@ -1414,15 +1414,15 @@ func (s *KeeperTestSuite) TestFunctional_SpreadRewards_LP() {
s.FundAcc(owner, fundCoins)

// Errors since no position.
_, _, _, err := s.App.ConcentratedLiquidityKeeper.SwapOutAmtGivenIn(s.Ctx, owner, pool, sdk.NewCoin(ETH, osmomath.OneInt()), USDC, pool.GetSpreadFactor(s.Ctx), types.MaxSpotPrice)
_, _, _, err := s.App.ConcentratedLiquidityKeeper.SwapOutAmtGivenIn(s.Ctx, owner, pool, sdk.NewCoin(ETH, osmomath.OneInt()), USDC, pool.GetSpreadFactor(s.Ctx), types.MaxSpotPriceBigDec)
s.Require().Error(err)

// Create position in the default range 1.
positionDataOne, err := concentratedLiquidityKeeper.CreatePosition(ctx, pool.GetId(), owner, DefaultCoins, osmomath.ZeroInt(), osmomath.ZeroInt(), DefaultLowerTick, DefaultUpperTick)
s.Require().NoError(err)

// Swap once.
ticksActivatedAfterEachSwap, totalSpreadRewardsExpected, _, _ := s.swapAndTrackXTimesInARow(pool.GetId(), DefaultCoin1, ETH, types.MaxSpotPrice, 1)
ticksActivatedAfterEachSwap, totalSpreadRewardsExpected, _, _ := s.swapAndTrackXTimesInARow(pool.GetId(), DefaultCoin1, ETH, types.MaxSpotPriceBigDec, 1)

// Withdraw half.
halfLiquidity := positionDataOne.Liquidity.Mul(osmomath.NewDecWithPrec(5, 1))
Expand All @@ -1447,7 +1447,7 @@ func (s *KeeperTestSuite) TestFunctional_SpreadRewards_LP() {
fullLiquidity := positionDataTwo.Liquidity

// Swap once in the other direction.
ticksActivatedAfterEachSwap, totalSpreadRewardsExpected, _, _ = s.swapAndTrackXTimesInARow(pool.GetId(), DefaultCoin0, USDC, types.MinSpotPrice, 1)
ticksActivatedAfterEachSwap, totalSpreadRewardsExpected, _, _ = s.swapAndTrackXTimesInARow(pool.GetId(), DefaultCoin0, USDC, types.MinSpotPriceBigDec, 1)

// This should claim under the hood for position 2 since full liquidity is removed.
balanceBeforeWithdraw := s.App.BankKeeper.GetBalance(ctx, owner, ETH)
Expand Down Expand Up @@ -1583,7 +1583,7 @@ func (s *KeeperTestSuite) tickStatusInvariance(ticksActivatedAfterEachSwap [][]i

// swapAndTrackXTimesInARow performs `numSwaps` swaps and tracks the tick activated after each swap.
// It also returns the total spread rewards collected, the total token in, and the total token out.
func (s *KeeperTestSuite) swapAndTrackXTimesInARow(poolId uint64, coinIn sdk.Coin, coinOutDenom string, priceLimit osmomath.Dec, numSwaps int) (ticksActivatedAfterEachSwap []int64, totalSpreadRewards sdk.Coins, totalTokenIn sdk.Coin, totalTokenOut sdk.Coin) {
func (s *KeeperTestSuite) swapAndTrackXTimesInARow(poolId uint64, coinIn sdk.Coin, coinOutDenom string, priceLimit osmomath.BigDec, numSwaps int) (ticksActivatedAfterEachSwap []int64, totalSpreadRewards sdk.Coins, totalTokenIn sdk.Coin, totalTokenOut sdk.Coin) {
// Retrieve pool
clPool, err := s.App.ConcentratedLiquidityKeeper.GetPoolById(s.Ctx, poolId)
s.Require().NoError(err)
Expand Down
16 changes: 8 additions & 8 deletions x/concentrated-liquidity/swaps.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ func (k Keeper) swapOutAmtGivenIn(
tokenIn sdk.Coin,
tokenOutDenom string,
spreadFactor osmomath.Dec,
priceLimit osmomath.Dec,
priceLimit osmomath.BigDec,
) (calcTokenIn, calcTokenOut sdk.Coin, poolUpdates PoolUpdates, err error) {
swapResult, poolUpdates, err := k.computeOutAmtGivenIn(ctx, pool.GetId(), tokenIn, tokenOutDenom, spreadFactor, priceLimit)
if err != nil {
Expand Down Expand Up @@ -247,7 +247,7 @@ func (k *Keeper) swapInAmtGivenOut(
desiredTokenOut sdk.Coin,
tokenInDenom string,
spreadFactor osmomath.Dec,
priceLimit osmomath.Dec,
priceLimit osmomath.BigDec,
) (calcTokenIn, calcTokenOut sdk.Coin, poolUpdates PoolUpdates, err error) {
swapResult, poolUpdates, err := k.computeInAmtGivenOut(ctx, desiredTokenOut, tokenInDenom, spreadFactor, priceLimit, pool.GetId())
if err != nil {
Expand Down Expand Up @@ -278,7 +278,7 @@ func (k Keeper) CalcOutAmtGivenIn(
spreadFactor osmomath.Dec,
) (tokenOut sdk.Coin, err error) {
cacheCtx, _ := ctx.CacheContext()
swapResult, _, err := k.computeOutAmtGivenIn(cacheCtx, poolI.GetId(), tokenIn, tokenOutDenom, spreadFactor, osmomath.ZeroDec())
swapResult, _, err := k.computeOutAmtGivenIn(cacheCtx, poolI.GetId(), tokenIn, tokenOutDenom, spreadFactor, osmomath.ZeroBigDec())
if err != nil {
return sdk.Coin{}, err
}
Expand All @@ -293,7 +293,7 @@ func (k Keeper) CalcInAmtGivenOut(
spreadFactor osmomath.Dec,
) (sdk.Coin, error) {
cacheCtx, _ := ctx.CacheContext()
swapResult, _, err := k.computeInAmtGivenOut(cacheCtx, tokenOut, tokenInDenom, spreadFactor, osmomath.ZeroDec(), poolI.GetId())
swapResult, _, err := k.computeInAmtGivenOut(cacheCtx, tokenOut, tokenInDenom, spreadFactor, osmomath.ZeroBigDec(), poolI.GetId())
if err != nil {
return sdk.Coin{}, err
}
Expand Down Expand Up @@ -354,7 +354,7 @@ func (k Keeper) computeOutAmtGivenIn(
tokenInMin sdk.Coin,
tokenOutDenom string,
spreadFactor osmomath.Dec,
priceLimit osmomath.Dec,
priceLimit osmomath.BigDec,
) (swapResult SwapResult, poolUpdates PoolUpdates, err error) {
p, spreadRewardAccumulator, uptimeAccums, err := k.swapSetup(ctx, poolId, tokenInMin.Denom, tokenOutDenom)
if err != nil {
Expand Down Expand Up @@ -481,7 +481,7 @@ func (k Keeper) computeInAmtGivenOut(
desiredTokenOut sdk.Coin,
tokenInDenom string,
spreadFactor osmomath.Dec,
priceLimit osmomath.Dec,
priceLimit osmomath.BigDec,
poolId uint64,
) (swapResult SwapResult, poolUpdates PoolUpdates, err error) {
p, spreadRewardAccumulator, uptimeAccums, err := k.swapSetup(ctx, poolId, tokenInDenom, desiredTokenOut.Denom)
Expand Down Expand Up @@ -734,7 +734,7 @@ func checkDenomValidity(inDenom, outDenom, asset0, asset1 string) error {
return nil
}

func (k Keeper) setupSwapStrategy(p types.ConcentratedPoolExtension, spreadFactor osmomath.Dec, tokenInDenom string, priceLimit osmomath.Dec) (strategy swapstrategy.SwapStrategy, sqrtPriceLimit osmomath.BigDec, err error) {
func (k Keeper) setupSwapStrategy(p types.ConcentratedPoolExtension, spreadFactor osmomath.Dec, tokenInDenom string, priceLimit osmomath.BigDec) (strategy swapstrategy.SwapStrategy, sqrtPriceLimit osmomath.BigDec, err error) {
zeroForOne := getZeroForOne(tokenInDenom, p.GetToken0())

// take provided price limit and turn this into a sqrt price limit since formulas use sqrtPrice
Expand Down Expand Up @@ -838,7 +838,7 @@ func (k Keeper) ComputeMaxInAmtGivenMaxTicksCrossed(
}

// Setup the swap strategy
swapStrategy, _, err := k.setupSwapStrategy(p, p.GetSpreadFactor(cacheCtx), tokenInDenom, osmomath.ZeroDec())
swapStrategy, _, err := k.setupSwapStrategy(p, p.GetSpreadFactor(cacheCtx), tokenInDenom, osmomath.ZeroBigDec())
if err != nil {
return sdk.Coin{}, sdk.Coin{}, err
}
Expand Down
Loading

0 comments on commit 3f15d3d

Please sign in to comment.