-
Notifications
You must be signed in to change notification settings - Fork 624
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
[CL Incentives]: Sync global uptime accumulators upon tick crossing #4399
Conversation
…/osmosis into adam/add-freeze-api
…/osmosis into adam/add-freeze-api
* single fee accum * lint
Co-authored-by: Sishir Giri <[email protected]>
Co-authored-by: Roman <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left few comments
x/concentrated-liquidity/tick.go
Outdated
} | ||
|
||
// Update global accums to now before uptime outside changes | ||
if err := k.updateUptimeAccumulatorsToNow(ctx, poolId); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to update uptime accumulators as we cross ticks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we be able to update them once per block?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thinking was that the update logic for the target tick's uptime accumulators will involve the global accum values, so we need to ensure they are up to date. Are you suggesting this isn't necessary?
I do see a different issue though – we should be updating the accums prior to getting them instead of after, will fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So over a single swap, we might be crossing multiple ticks. From my understanding, we do not need to update the uptime accumulators every tick because that is idempotent within a swap. As a result, calling this update function as we cross every tick might be redundant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Outside of the scope of this PR but - why do we also need to call updateUptimeAccumulatorsToNow
in getTickInfo
?
It feels that this update needs to happen at another level of abstraction or in another location
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So over a single swap, we might be crossing multiple ticks. From my understanding, we do not need to update the uptime accumulators every tick because that is idempotent within a swap. As a result, calling this update function as we cross every tick might be redundant.
Good point – we can add a check so it only updates if LastUpdateTime < current time
. Made an issue here (#4422) to not block this PR (and because it could break some downstream PRs)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Outside of the scope of this PR but - why do we also need to call
updateUptimeAccumulatorsToNow
ingetTickInfo
?It feels that this update needs to happen at another level of abstraction or in another location
We update there simply because getInitialUptimeGrowthOutsidesForTick
uses global accum values (so they need to be up to date). The level of abstraction does seem a little off, but the function does include accumulator init logic more broadly so it might be worth discussing a small refactor or rename
additiveFee sdk.DecCoin | ||
expectedLiquidityDelta sdk.Dec | ||
expectedTickFeeGrowthOutside sdk.DecCoins | ||
expectedErr bool | ||
}{ | ||
{ | ||
name: "Get tick info on existing pool and existing tick", | ||
name: "Get tick info on existing pool and existing tick below current tick (nonzero uptime trackers)", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: let's remove "on existing pool" part from every test case name, please. It adds cognitive overhead while being unimportant context relative to other test case details because the pool existence check happens once at the top level
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, done
expectedTickFeeGrowthOutside: DefaultFeeAccumCoins.Add(defaultAdditiveFee), | ||
}, | ||
{ | ||
name: "Get tick info on existing pool and existing tick below current tick (nonzero uptime trackers)", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't it ("zero initial uptime") trackers. Should the test case name reflect that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm not sure I follow – the uptime trackers are nonzero in this test case no?
expectedTickFeeGrowthOutside: DefaultFeeAccumCoins.Add(defaultAdditiveFee), | ||
}, | ||
{ | ||
name: "Get tick info on existing pool and existing tick above current tick (nil uptime trackers)", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it make sense also having a test case where non-zero initial uptime trackers and above current tick?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is already implicitly covered by case right below your comment, but I just added an explicit case for clarity anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM pending minor suggestions and the discussion on calling updateUptimeAccumulatorsToNow
in crossTick
and getTickInfo
.
If that makes it easier for making progress, please feel free to merge this and move the discussion on Slack
Closes: #4278
What is the purpose of the change
This PR implements uptime-related logic for tick crossing. Specifically, it "flips" the tick-level uptime accum values upon crossing.
Brief Changelog
Testing and Verifying
tick_test.go
(including cases for technically undefined behavior such as crossing into non-adjacent ticks)Documentation and Release Note
Unreleased
section inCHANGELOG.md
? (no)