Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only fetch uptime accumulators on Tick Crossings #7550

Merged
merged 4 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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