-
Notifications
You must be signed in to change notification settings - Fork 592
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
TWAP logic #2168
TWAP logic #2168
Conversation
Dev, this PR is aimed at giving users the ability to buy / sell using twap? |
Nah, thats DCA'ing. This PR exposes on-chain TWAPs that people can then with cosmwasm to build that though! Exposes an on-chain TWAP oracle for every pool |
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.
I finished reviewing the core logic but haven't reviewed the tests in detail yet.
I would like to spend more time tomorrow trying to run the tests.
LGTM overall, great job on this! Also, it is fine with me if this PR is not split further
sdk "github.com/cosmos/cosmos-sdk/types" | ||
|
||
epochtypes "github.com/osmosis-labs/osmosis/v10/x/epochs/types" | ||
"github.com/osmosis-labs/osmosis/v10/x/gamm/types" | ||
) | ||
|
||
func (k Keeper) MigrateExistingPools(ctx sdk.Context, poolIds []uint64) error { |
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.
Not sure if it is desired to group this with hooks. Please consider moving this to migrations.go
(like it is in the sdk) or to keeper.go
.
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.
I wanted this file to be listeners
for things that could trigger a state change. Maybe I just change the file name to listeners.go?
I'm imagining we try to to change the entire Hook system into a publisher subscriber system
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.
Maybe I just change the file name to listeners.go?
I like listeners.go
since hook and listener feel to be synonymous. Also, I think listener
is frequently used when speaking of pub-sub systems.
I wanted this file to be listeners for things that could trigger a state change
But this specific function is a one-time migration that is done during the upgrade. Why would we ever use pub-sub for this logic?
Also, I was referring to existing examples such as:
osmosis/x/lockup/keeper/migration.go
Line 40 in 3b9e72c
func MergeLockupsForSimilarDurations( |
where upgrade migrations logic exists in the keeper's migrations.go
file
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.
hrmm yeah your right the migraiton being here is weird.
I just realized that we can do this in InitGenesis, which is likely the correct entry point. WIll move it there.
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.
ah rip we can't do it in InitGenesis without adding to the gamm keeper interface, which seems worse.
I feel like keeping it in listeners.go, as what an external module can trigger logic for, is ok personally. I'd prefer not blocking on where this function lives, as it will ultimately be deleted later.
Perhaps we can call it InitGenesisAtMigration?
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.
We agreed to leaves as is offline - I guess we can discuss this in a separate issue later
Closes: #XXX ## What is the purpose of the change Some minor pass through changes discovered while reviewing #2168 ## Documentation and Release Note - Does this pull request introduce a new feature or user-facing behavior changes? no - Is a relevant changelog entry added to the `Unreleased` section in `CHANGELOG.md`? no - How is the feature or change documented? not applicable
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.
I'm part way through tests. Still have a couple of files to review
tPlus10sp5Record := newTwapRecordWithDefaults( | ||
baseTime.Add(10*time.Second), sdk.NewDec(5), OneSec.MulInt64(10*10), OneSec) | ||
// record with t=baseTime+20, sp0=2, sp1=.5, accumulators updated from tPlus10sp5Record | ||
// tPlus20sp2Record := newTwapRecordWithDefaults( |
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.
Can deadcode be removed?
input: makeSimpleTwapInput(baseTime.Add(-time.Hour), baseTime, quoteAssetA), | ||
expErrorStr: "too old", | ||
}, | ||
// TODO: overflow tests, multi-asset pool handling, make more record interpolation cases |
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.
Agree that these would be useful. Do we have an issue for adding these?
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.
We do for multi-asset pool handling. Not yet for overflow, but handling overflow is one of the big remaining twap items
sdk "github.com/cosmos/cosmos-sdk/types" | ||
|
||
epochtypes "github.com/osmosis-labs/osmosis/v10/x/epochs/types" | ||
"github.com/osmosis-labs/osmosis/v10/x/gamm/types" | ||
) | ||
|
||
func (k Keeper) MigrateExistingPools(ctx sdk.Context, poolIds []uint64) error { |
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.
Maybe I just change the file name to listeners.go?
I like listeners.go
since hook and listener feel to be synonymous. Also, I think listener
is frequently used when speaking of pub-sub systems.
I wanted this file to be listeners for things that could trigger a state change
But this specific function is a one-time migration that is done during the upgrade. Why would we ever use pub-sub for this logic?
Also, I was referring to existing examples such as:
osmosis/x/lockup/keeper/migration.go
Line 40 in 3b9e72c
func MergeLockupsForSimilarDurations( |
where upgrade migrations logic exists in the keeper's migrations.go
file
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.
Tests LGTM. My first full pass on this PR is now complete.
Left some minor comments. I agree for the need for more tests outlined in TODOs. However, the test coverage in the core functions seems pretty good already, great work on that.
x/gamm/twap/hook_test.go
Outdated
"github.com/osmosis-labs/osmosis/v10/x/gamm/twap/types" | ||
) | ||
|
||
// TestCreatePoolFlow tests that upon a pool being created, |
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.
Most tests in this file seem to be more functional than unit in nature. While it is useful to have both, I don't think we have any unit tests for hooks.
Do we have an issue for unit testing hooks?
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.
I don't think theres any unit tests that makes sense - they should all be functionality tests, with the expected integration.
Every hook is just "capture input from elsewhere, call unit tested method"
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.
I guess we could make these more table driven! Definitely very open to figuring out how to make better tests for what we want here!
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.
I will make a separate issue for this to discuss further
x/gamm/twap/hook_test.go
Outdated
) | ||
|
||
// TestCreatePoolFlow tests that upon a pool being created, | ||
// we have made the correct store entries. |
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.
I think we should also be more specific about what exactly we are testing in this file. At first, I was looking in the hook_listener.go
due to the name of this file. However, then, I released that a lot of the functionality is actually related to endBlock
which is defined in logic.go
So I suggest renaming this to hook_functional_test.go
and adding a comment that all these tests are functional and testing the relationship between twap with other system components.
interpolateTime: time.Unix(1, 0), | ||
expRecord: newExpRecord(oneDec, twoDec), | ||
}, | ||
// TODO: Overflow tests |
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.
Bump for TODO - is this being kept track of?
|
||
"accumulator = 10*OneSec, t=100s. 0 base accum (asset 1)": testCaseFromDeltasAsset1(sdk.ZeroDec(), OneSec.MulInt64(10), 100*time.Second, sdk.NewDecWithPrec(1, 1)), | ||
|
||
// TODO: Overflow, rounding |
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.
Bump for TODO - is this being kept track of?
interpolateTime: time.Unix(55, 0), | ||
expRecord: newExpRecord(oneDec.Add(OneSec.MulInt64(44*10)), twoDec.Add(OneSec.MulInt64(44).QuoInt64(10))), | ||
}, | ||
"same time": { |
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.
What happens if newTime
is before record time by mistake so the timeDelta
is negative? How is this handled by the core logic? Is there a test covering this?
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.
Hrmm, there isn't a test handling it because its incorrect behavior. (Breaks the precondition on the function - thats the responsibility of the caller) But you should still get the same result. This is because TWAP is:
(accumEnd - accumStart) / (timeEnd - timeStart)
So if you reverse the arguments, you compute
(accumStart - accumEnd) / (timeStart - timeEnd)
= -(accumEnd - accumStart) / - (timeEnd - timeStart)
= (accumEnd - accumStart) / (timeEnd - timeStart)
Thus the function is argument order independent.
This is for the same reason that you can don't care about the order of points when trying to compute the slope of a line.
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.
That makes sense, thanks for explaining. I think it still makes to add a test even if we expect that to not happen and be incorrect. We should aim to have test cases relative to all possible inputs of a function even though some might be invalid when looking at the system holistically
Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>
Those are not the responsibility of this PR to address imo |
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. Great work!
One last thing I would like to bump is discussed here:
#2168 (comment)
sdk "github.com/cosmos/cosmos-sdk/types" | ||
|
||
epochtypes "github.com/osmosis-labs/osmosis/v10/x/epochs/types" | ||
"github.com/osmosis-labs/osmosis/v10/x/gamm/types" | ||
) | ||
|
||
func (k Keeper) MigrateExistingPools(ctx sdk.Context, poolIds []uint64) error { |
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.
We agreed to leaves as is offline - I guess we can discuss this in a separate issue later
x/gamm/twap/hook_test.go
Outdated
"github.com/osmosis-labs/osmosis/v10/x/gamm/twap/types" | ||
) | ||
|
||
// TestCreatePoolFlow tests that upon a pool being created, |
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.
I will make a separate issue for this to discuss further
Co-authored-by: Roman <roman@osmosis.team>
Added that test! Planning to merge upon test pass, to unblock other fronts |
What is the purpose of the change
Core logic for TWAP implementation. Right now wanted to ask if we wanted me to split up PR'ing the
types
package,osmoutils
, andtwap/store
changes first. I think the work inosmoutils
is generally quite helpful for our codebase, happy to break that out sooner before finishing the remainder.Remaining steps needed:
Brief Changelog
Testing and Verifying
This change added tests and can be verified as follows:
Tests are added in this PR, will be breaking up components to be more easily reviewable. First broken out component is #2175
Documentation and Release Note
Unreleased
section inCHANGELOG.md
? yes