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

[CLOB-1028] allow settlement at oracle price in ProcessDeleveraging #835

Merged
merged 7 commits into from
Dec 6, 2023

Conversation

jakob-dydx
Copy link
Contributor

@jakob-dydx jakob-dydx commented Dec 4, 2023

  • updates ProcessDeleveraging to take in deltaQuoteQuantums
  • this allows us to decide on the price of the deleveraging event and to pass this in to the function
  • I have created a helper method which fetches the price - bankruptcy for regular deleveraging and oracle price for final settlement deleveraging. This is determined by the status of the clob pair linked with the perpetual

No tests for OffsetSubaccountPerpetualPosition have been included for final settlement clob pairs yet, because the final settlement status is still not allowed on main. Tests will be added for this in a separate PR for when the status is enabled. Holding off on enabling the status to properly gate these changes

Copy link

linear bot commented Dec 4, 2023

Copy link
Contributor

coderabbitai bot commented Dec 4, 2023

Walkthrough

The updates involve significant changes to the deleveraging logic in a blockchain protocol's codebase, specifically affecting how the fillPriceDeltaQuoteQuantums is calculated and how subaccount balances are updated during the deleveraging process. A new parameter fillPriceIsOraclePrice has been introduced to a function, indicating a shift towards more flexible price handling. The test suite has been expanded to cover these new scenarios, ensuring the robustness of the deleveraging process.

Changes

File Path Change Summary
protocol/x/clob/keeper/deleveraging.go
deleveraging_test.go
protocol/x/clob/keeper/process_operations.go
- Added fillPriceIsOraclePrice parameter to OffsetSubaccountPerpetualPosition
- Modified ProcessDeleveraging logic for fillPriceDeltaQuoteQuantums calculation and subaccount balance updates.
- Added new test TestProcessDeleveragingAtOraclePrice, updated existing tests with new assertions and cases to reflect changes in deleveraging logic.
- Modified function call to include new variable deltaQuoteQuantums
- Replaced deltaQuantums with deltaBaseQuantums.

Tips

Chat with CodeRabbit Bot (@coderabbitai)

  • If you reply to a review comment from CodeRabbit, the bot will automatically respond.
  • To engage with CodeRabbit bot directly around the specific lines of code in the PR, mention @coderabbitai in your review comment
  • Note: Review comments are made on code diffs or files, not on the PR overview.
  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Note: For conversation with the bot, please use the review comments on code diffs or files.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.v2.json

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 1

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 5901af4 and 64598c8.
Files selected for processing (3)
  • protocol/x/clob/keeper/deleveraging.go (5 hunks)
  • protocol/x/clob/keeper/deleveraging_test.go (3 hunks)
  • protocol/x/clob/keeper/process_operations.go (1 hunks)
Additional comments: 7
protocol/x/clob/keeper/deleveraging.go (4)
  • 3-14: The reorganization of import statements is a standard cleanup and does not impact functionality.

  • 242-245: The addition of the fillPriceIsOraclePrice boolean parameter to the OffsetSubaccountPerpetualPosition function aligns with the PR objectives to support settlement at oracle price.

  • 357-385: > Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [325-384]

The logic modification in the ProcessDeleveraging function to calculate fillPriceDeltaQuoteQuantums based on the fillPriceIsOraclePrice flag is consistent with the PR objectives to alter the settlement process.

  • 477-483: The code correctly emits a cometbft event and an on-chain update for the deleveraging, which is standard for recording state changes in blockchain applications.
protocol/x/clob/keeper/deleveraging_test.go (3)
  • 1096-1100: The ProcessDeleveraging function has been updated to include a new boolean parameter fillPriceIsOraclePrice as per the PR objective. This parameter is hardcoded to false in the test case, which aligns with the PR objective that the default behavior is not to use the oracle price unless specified otherwise.

  • 1124-1304: The new test function TestProcessDeleveragingAtOraclePrice has been added to test the functionality of the ProcessDeleveraging function when the fillPriceIsOraclePrice flag is set to true. This aligns with the PR objective to support final settlement fills at the oracle price.

  • 1458-1462: The ProcessDeleveraging function is called with the fillPriceIsOraclePrice parameter set to false in the TestProcessDeleveraging_Rounding test case. This is consistent with the default behavior described in the PR objective, where the oracle price is not used unless specified otherwise.

protocol/x/clob/keeper/process_operations.go Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 81bd4b7 and b2e6b2e.
Files selected for processing (3)
  • protocol/x/clob/keeper/deleveraging.go (5 hunks)
  • protocol/x/clob/keeper/deleveraging_test.go (8 hunks)
  • protocol/x/clob/keeper/process_operations.go (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • protocol/x/clob/keeper/deleveraging.go
Additional comments: 5
protocol/x/clob/keeper/deleveraging_test.go (4)
  • 642-683: > Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [625-678]

The changes from lines 625 to 678 show the creation of perpetuals and ClobPairs for testing purposes. The loop correctly handles the creation of perpetuals and the addition of events for each ClobPair creation. The use of mockIndexerEventManager.On to set up expectations for the mock event manager is correct and follows good testing practices.

  • 1103-1157: The changes from lines 1103 to 1157 show the setup and execution of the ProcessDeleveraging function within the test cases. The setup includes setting subaccounts and calculating the bankruptcy price. The test cases are well-structured and cover various scenarios, including error handling. The use of require.NoError and require.ErrorContains for assertions is appropriate.

  • 1162-1277: The changes from lines 1162 to 1277 introduce the TestProcessDeleveragingAtOraclePrice function, which tests the deleveraging process using oracle prices. The test cases are comprehensive and cover various scenarios, including well-collateralized and under-collateralized subaccounts. The setup for each test case is thorough, and the error handling checks with require.ErrorContains are correctly implemented.

  • 1470-1484: > Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [1470-1507]

The changes from lines 1470 to 1507 show the setup and execution of the TestProcessDeleveraging_Rounding function within the test cases. The setup includes setting subaccounts and calculating the bankruptcy price with rounding considerations. The test cases are well-structured and cover scenarios where rounding could affect the outcome of deleveraging. The use of require.NoError and require.ErrorContains for assertions is appropriate.

protocol/x/clob/keeper/process_operations.go (1)
  • 651-691: The changes from lines 651 to 691 introduce a new variable deltaQuoteQuantums and rename deltaQuantums to deltaBaseQuantums, which is consistent with the PR objectives and the summary provided. The logic for determining the sign of deltaBaseQuantums and the error handling within the loop for processing deleveraging fills appear to be correct. Ensure that the getDeleveragingQuoteQuantumsDelta and ProcessDeleveraging functions are implemented correctly and handle the new logic as intended.

Comment on lines +241 to +246
deltaQuoteQuantums, err := k.getDeleveragingQuoteQuantumsDelta(
ctx,
perpetualId,
liquidatedSubaccountId,
deltaQuantums,
)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errors returned from bankruptcy price calculation were previously caught within ProcessDeleveraging and recovered from in OffsetSubaccountPerpetualPosition, continuing onto the next iteration without breaking. I am opting to continue this pattern, but will log a debug msg

deltaBaseQuantums.Neg(deltaBaseQuantums)
}

deltaQuoteQuantums, err := k.getDeleveragingQuoteQuantumsDelta(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is where we call ProcessDeleveraging in DeliverTx, we call the helper function to get the delta quote quantums to pass in

subaccountId satypes.SubaccountId,
deltaQuantums *big.Int,
) (deltaQuoteQuantums *big.Int, err error) {
clobPair := k.mustGetClobPairForPerpetualId(ctx, perpetualId)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: is it okay if we panic here? This logic is executed in PrepareCheckState. Would we rather recover from this and continue? I think it is fine to panic but just want to double check.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah should be fine to panic - if clob pair is missing, then something is really really wrong

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just realized this function isn't doing exactly what I want for usability. The purpose of this function is to allow the deleveraging flow to be reusable such that non-negative TNC subaccounts with positions in a final settlement market can be closed at the oracle price.

Currently this function is written such that ALL subaccounts (including negative TNC) for the closed market will be settled at oracle price. This isn't what we want. I think the easiest way to updated this would be to do a collateral check and use the oracle price iff isFinalSettlement && nonNegativeTNC.

I think what I'll do here is use CanDeleverageSubaccount to determine if the account has non negative TNC and only call this if the market is in final settlement.

Comment on lines 346 to 348
deltaQuoteQuantums, err = k.perpetualsKeeper.GetNetNotional(ctx, perpetualId, deltaQuantums)
} else {
deltaQuoteQuantums, err = k.GetBankruptcyPriceInQuoteQuantums(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we can just return k.perpetualsKeeper.GetNetNotional or return k.GetBankruptcyPriceInQuoteQuantums. up to you

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true, will update

)
if err != nil {
liquidatedSubaccount := k.subaccountsKeeper.GetSubaccount(ctx, liquidatedSubaccountId)
k.Logger(ctx).Debug(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be Debug or Error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will change to Error

"Encountered error when getting quote quantums for deleveraging",
"error", err,
"blockHeight", ctx.BlockHeight(),
"checkTx", ctx.IsCheckTx(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: k.Logger() already has this, so we can remove this here

@@ -1095,6 +1136,215 @@ func TestProcessDeleveraging(t *testing.T) {
*tc.offsettingSubaccount.GetId(),
uint32(0),
tc.deltaQuantums,
bankruptcyPriceQuoteQuantums,
Copy link
Contributor

@jayy04 jayy04 Dec 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for my understanding - the bankruptcyPriceQuoteQuantums will be 0 if tc.expectedErr != nil, is that okay?

bankruptcy price should always exist, should we pull that out of the if statement above? similar to what you have below for quote quantums using oracle price

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I needed to push this into the if statement though, because the GetBankruptcyPriceInQuoteQuantums returns an error for my test cases where tc.expectedErr != nil. So the test code was erroring out before executing the ProcessDeleveraging logic.

I am intentionally skipping this calculation for error cases.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between b2e6b2e and 64503ff.
Files selected for processing (2)
  • protocol/x/clob/keeper/deleveraging.go (5 hunks)
  • protocol/x/clob/keeper/deleveraging_test.go (7 hunks)
Additional comments: 8
protocol/x/clob/keeper/deleveraging.go (4)
  • 236-258: The error handling within OffsetSubaccountPerpetualPosition when fetching deltaQuoteQuantums from getDeleveragingQuoteQuantumsDelta logs an error but does not halt the process or propagate the error. This behavior is consistent with the previous pattern mentioned by jakob-dydx in the existing comments, where errors in price calculation were caught and logged without breaking the loop. Ensure that this is the intended behavior and that the system can safely continue without this data.

  • 328-354: The getDeleveragingQuoteQuantumsDelta function correctly determines the type of deleveraging event and returns the appropriate quote quantums delta. This is a key part of the new feature to use oracle prices for settlement. The function uses the clobPair status to decide whether to use the bankruptcy price or the oracle price, which aligns with the PR objectives.

  • 387-401: The validation logic in ProcessDeleveraging ensures that deltaBaseQuantums is on the opposite side of the liquidated position and the same side as the offsetting position, and that its magnitude is not larger than both positions. This is crucial for maintaining the integrity of the deleveraging process. Ensure that this validation covers all necessary cases and that the error message provides sufficient context for debugging.

  • 500-508: The ProcessDeleveraging function emits a cometbft event and sends an on-chain update for the deleveraging, which is necessary for the indexer to pick up and process the event. This is consistent with the system's design for handling state changes and notifying external components.

protocol/x/clob/keeper/deleveraging_test.go (4)
  • 2-15: The import modifications are minor and do not affect functionality.

  • 642-684: > Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [625-680]

The addition of loops to create perps and clobPairs is a significant change that should be reflected in the summary, as it likely affects the setup of the test environment.

  • 1164-1350: The addition of the TestProcessDeleveragingAtOraclePrice function with detailed test cases is significant and should be reflected in the summary to highlight the complexity and nature of the tests.

  • 1472-1486: > Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [1472-1509]

The addition of the TestProcessDeleveraging_Rounding function with detailed test cases is significant and should be reflected in the summary to highlight the complexity and nature of the tests.

@jakob-dydx jakob-dydx merged commit 77773c3 into main Dec 6, 2023
14 of 15 checks passed
@jakob-dydx jakob-dydx deleted the jakob-dydx/oracle-price-deleveraging branch December 6, 2023 21:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging this pull request may close these issues.

2 participants