Skip to content

Commit

Permalink
Only fetch uptime accumulators on Tick Crossings (#7550)
Browse files Browse the repository at this point in the history
* Only fetch uptime accumulators on Tick Crossings

* Update Changelog
  • Loading branch information
ValarDragon authored Feb 21, 2024
1 parent 905a21c commit 7ba7edd
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 29 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [#7499](https://github.com/osmosis-labs/osmosis/pull/7499) Slight speed/gas improvements to CL CreatePosition and AddToPosition
* [#7508](https://github.com/osmosis-labs/osmosis/pull/7508) Improve protorev performance by removing iterator and storing base denoms as a single object rather than an array.
* [#7509](https://github.com/osmosis-labs/osmosis/pull/7509) Distributing ProtoRev profits to the community pool and burn address
* [#7550](https://github.com/osmosis-labs/osmosis/pull/7550) Speedup small CL swaps, by only fetching CL uptime accumulators if there is a tick crossing.
* [#7562](https://github.com/osmosis-labs/osmosis/pull/7562) Speedup Protorev estimation logic by removing unnecessary taker fee simulations.

## v23.0.0
Expand Down
4 changes: 0 additions & 4 deletions x/concentrated-liquidity/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@ func (k Keeper) GetPoolById(ctx sdk.Context, poolId uint64) (types.ConcentratedP
return k.getPoolById(ctx, poolId)
}

func (k Keeper) GetSwapAccumulators(ctx sdk.Context, poolId uint64) (*accum.AccumulatorObject, []*accum.AccumulatorObject, error) {
return k.getSwapAccumulators(ctx, poolId)
}

func (k Keeper) CrossTick(ctx sdk.Context, poolId uint64, tickIndex int64, nextTickInfo *model.TickInfo, swapStateSpreadRewardGrowth sdk.DecCoin, spreadRewardAccumValue sdk.DecCoins, uptimeAccums []*accum.AccumulatorObject) (liquidityDelta osmomath.Dec, err error) {
return k.crossTick(ctx, poolId, tickIndex, nextTickInfo, swapStateSpreadRewardGrowth, spreadRewardAccumValue, uptimeAccums)
}
Expand Down
4 changes: 3 additions & 1 deletion x/concentrated-liquidity/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,9 @@ func (s *KeeperTestSuite) crossTickAndChargeSpreadReward(poolId uint64, tickInde
nextTickInfo, err := s.Clk.GetTickInfo(s.Ctx, poolId, tickIndexToCross)
s.Require().NoError(err)

feeAccum, uptimeAccums, err := s.Clk.GetSwapAccumulators(s.Ctx, poolId)
feeAccum, err := s.Clk.GetSpreadRewardAccumulator(s.Ctx, poolId)
s.Require().NoError(err)
uptimeAccums, err := s.Clk.GetUptimeAccumulators(s.Ctx, poolId)
s.Require().NoError(err)

// Cross the tick to update it.
Expand Down
48 changes: 24 additions & 24 deletions x/concentrated-liquidity/swaps.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,16 +335,16 @@ func (k Keeper) CalcInAmtGivenOut(
func (k Keeper) swapSetup(ctx sdk.Context,
poolId uint64,
tokenInDenom string,
tokenOutDenom string) (pool types.ConcentratedPoolExtension, spreadAccum *accum.AccumulatorObject, uptimeAccums []*accum.AccumulatorObject, err error) {
tokenOutDenom string) (pool types.ConcentratedPoolExtension, spreadAccum *accum.AccumulatorObject, err error) {
pool, err = k.getPoolForSwap(ctx, poolId)
if err != nil {
return pool, spreadAccum, uptimeAccums, err
return pool, spreadAccum, err
}
if err := checkDenomValidity(tokenInDenom, tokenOutDenom, pool.GetToken0(), pool.GetToken1()); err != nil {
return pool, spreadAccum, uptimeAccums, err
return pool, spreadAccum, err
}
spreadAccum, uptimeAccums, err = k.getSwapAccumulators(ctx, poolId)
return pool, spreadAccum, uptimeAccums, err
spreadAccum, err = k.GetSpreadRewardAccumulator(ctx, poolId)
return pool, spreadAccum, err
}

// returns next initialized tick, next initialized tick sqrt price, implied sqrt price target, and error
Expand Down Expand Up @@ -388,10 +388,11 @@ func (k Keeper) computeOutAmtGivenIn(
spreadFactor osmomath.Dec,
priceLimit osmomath.BigDec,
) (swapResult SwapResult, poolUpdates PoolUpdates, err error) {
p, spreadRewardAccumulator, uptimeAccums, err := k.swapSetup(ctx, poolId, tokenInMin.Denom, tokenOutDenom)
p, spreadRewardAccumulator, err := k.swapSetup(ctx, poolId, tokenInMin.Denom, tokenOutDenom)
if err != nil {
return SwapResult{}, PoolUpdates{}, err
}
var uptimeAccums []*accum.AccumulatorObject

swapStrategy, sqrtPriceLimit, err := k.setupSwapStrategy(p, spreadFactor, tokenInMin.Denom, priceLimit)
if err != nil {
Expand Down Expand Up @@ -453,7 +454,7 @@ func (k Keeper) computeOutAmtGivenIn(
// bucket has been consumed and we must move on to the next bucket to complete the swap
if nextInitializedTickSqrtPrice.Equal(computedSqrtPrice) {
swapState, err = k.swapCrossTickLogic(ctx, swapState, swapStrategy,
nextInitializedTick, nextInitTickIter, p, spreadRewardAccumulator, uptimeAccums, tokenInMin.Denom)
nextInitializedTick, nextInitTickIter, p, spreadRewardAccumulator, &uptimeAccums, tokenInMin.Denom)
if err != nil {
return SwapResult{}, PoolUpdates{}, err
}
Expand Down Expand Up @@ -519,10 +520,11 @@ func (k Keeper) computeInAmtGivenOut(
priceLimit osmomath.BigDec,
poolId uint64,
) (swapResult SwapResult, poolUpdates PoolUpdates, err error) {
p, spreadRewardAccumulator, uptimeAccums, err := k.swapSetup(ctx, poolId, tokenInDenom, desiredTokenOut.Denom)
p, spreadRewardAccumulator, err := k.swapSetup(ctx, poolId, tokenInDenom, desiredTokenOut.Denom)
if err != nil {
return SwapResult{}, PoolUpdates{}, err
}
var uptimeAccums []*accum.AccumulatorObject

swapStrategy, sqrtPriceLimit, err := k.setupSwapStrategy(p, spreadFactor, tokenInDenom, priceLimit)
if err != nil {
Expand Down Expand Up @@ -579,7 +581,7 @@ func (k Keeper) computeInAmtGivenOut(
// bucket has been consumed and we must move on to the next bucket by crossing a tick to complete the swap
if nextInitializedTickSqrtPrice.Equal(computedSqrtPrice) {
swapState, err = k.swapCrossTickLogic(ctx, swapState, swapStrategy,
nextInitializedTick, nextInitTickIter, p, spreadRewardAccumulator, uptimeAccums, tokenInDenom)
nextInitializedTick, nextInitTickIter, p, spreadRewardAccumulator, &uptimeAccums, tokenInDenom)
if err != nil {
return SwapResult{}, PoolUpdates{}, err
}
Expand Down Expand Up @@ -642,23 +644,33 @@ func emitSwapDebugLogs(ctx sdk.Context, swapState SwapState, reachedPrice osmoma
}

// logic for crossing a tick during a swap
//
// if uptimeAccums is nil, fetches uptime accumulators.
// uptime accumulators are always mutated for the tick crossing.
func (k Keeper) swapCrossTickLogic(ctx sdk.Context,
swapState SwapState, strategy swapstrategy.SwapStrategy,
nextInitializedTick int64, nextTickIter db.Iterator,
p types.ConcentratedPoolExtension,
spreadRewardAccum *accum.AccumulatorObject, uptimeAccums []*accum.AccumulatorObject,
spreadRewardAccum *accum.AccumulatorObject, uptimeAccums *[]*accum.AccumulatorObject,
tokenInDenom string) (SwapState, error) {
nextInitializedTickInfo, err := ParseTickFromBz(nextTickIter.Value())
if err != nil {
return swapState, err
}
if *uptimeAccums == nil {
uptimeAccumsRaw, err := k.GetUptimeAccumulators(ctx, p.GetId())
if err != nil {
return swapState, err
}
uptimeAccums = &uptimeAccumsRaw
}

if err := k.updateGivenPoolUptimeAccumulatorsToNow(ctx, p, uptimeAccums); err != nil {
if err := k.updateGivenPoolUptimeAccumulatorsToNow(ctx, p, *uptimeAccums); err != nil {
return swapState, err
}

// Retrieve the liquidity held in the next closest initialized tick
liquidityNet, err := k.crossTick(ctx, p.GetId(), nextInitializedTick, &nextInitializedTickInfo, sdk.NewDecCoinFromDec(tokenInDenom, swapState.globalSpreadRewardGrowthPerUnitLiquidity), spreadRewardAccum.GetValue(), uptimeAccums)
liquidityNet, err := k.crossTick(ctx, p.GetId(), nextInitializedTick, &nextInitializedTickInfo, sdk.NewDecCoinFromDec(tokenInDenom, swapState.globalSpreadRewardGrowthPerUnitLiquidity), spreadRewardAccum.GetValue(), *uptimeAccums)
if err != nil {
return swapState, err
}
Expand Down Expand Up @@ -805,18 +817,6 @@ func (k Keeper) getPoolForSwap(ctx sdk.Context, poolId uint64) (types.Concentrat
return p, nil
}

func (k Keeper) getSwapAccumulators(ctx sdk.Context, poolId uint64) (*accum.AccumulatorObject, []*accum.AccumulatorObject, error) {
spreadAccum, err := k.GetSpreadRewardAccumulator(ctx, poolId)
if err != nil {
return &accum.AccumulatorObject{}, []*accum.AccumulatorObject{}, err
}
uptimeAccums, err := k.GetUptimeAccumulators(ctx, poolId)
if err != nil {
return &accum.AccumulatorObject{}, []*accum.AccumulatorObject{}, err
}
return spreadAccum, uptimeAccums, nil
}

// validateSwapProgressAndAmountConsumption validates that the swap progress and amount consumption are valid. These are valid if:
// - computedSqrtPrice is not equal to sqrtPriceStart (progress made)
// - computedSqrtPrice is equals to sqrtPriceStart and both amountIn and amountOut are zero (progress not made AND amounts are not consumed)
Expand Down

0 comments on commit 7ba7edd

Please sign in to comment.