Skip to content

Rebalancing Failures#290

Open
UlyanaAndrukhiv wants to merge 12 commits intomainfrom
UlianaAndrukhiv/280-rebalancing-failures
Open

Rebalancing Failures#290
UlyanaAndrukhiv wants to merge 12 commits intomainfrom
UlianaAndrukhiv/280-rebalancing-failures

Conversation

@UlyanaAndrukhiv
Copy link
Copy Markdown
Contributor

@UlyanaAndrukhiv UlyanaAndrukhiv commented Mar 24, 2026

Closes: #280

Context

  • Added test coverage for various rebalance failure scenarios (Insufficient_TopUpSource_Fundsis omitted, as such a test already exists - testRebalanceUndercollateralised_InsufficientTopUpSource())
  • Updated the rebalance test helper and its usages
  • Moved the asyncUpdate() helper to test_helpers.cdc and renamed it for clarity
  • Added a test transaction for setting drawDownSink

@UlyanaAndrukhiv UlyanaAndrukhiv self-assigned this Mar 24, 2026
@UlyanaAndrukhiv UlyanaAndrukhiv marked this pull request as ready for review March 24, 2026 14:36
@UlyanaAndrukhiv UlyanaAndrukhiv requested a review from a team as a code owner March 24, 2026 14:36
@UlyanaAndrukhiv UlyanaAndrukhiv requested a review from mts1715 March 27, 2026 10:14
@UlyanaAndrukhiv UlyanaAndrukhiv requested a review from a team March 31, 2026 15:28
Comment on lines +254 to +261
// minHealth = 1.1: required deposit per position to reach minHealth after 50% price crash:
// effectiveCollateral = 1 000 * 0.5 * 0.8 = 400
// effectiveDebt ≈ 615.38
//
// Ideal health = 400 / (615.38 - required) = 1.3
// Required MOET ≈ 307.69 MOET
//
// left 310 MOET which is enough for one position, not both
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't understand why using ideal health (1.3) instead of using minHealth (1.1)

To me, liquidation happens when HF < minHealth (1.1), rather than ideal health (1.3).

In other words, It requires only 251.74 (615.38 - 400 / 1.1= 251.74) MOET (rather than 310 MOET) in order to avoid liquidation when price drops 50%.

So if we provide only 251.74 MOET to the topup source, then only one of the position can pull all of it to avoid liquidation (enough to rescue), and the other position will pull nothing, and still liquidatable.

I tried changing 310.0 in L262 to 251.74, the test case still passes, and it passes even if I changed down to 216.0, but fails when changed to 215.0, do you know why?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Oh, I see. the minimum health factor to avoid liquidation is 1, not 1.1.

the minHealth 1.1 is when the low threshold to trigger rebalancing, not liquidation.

So 615.38 - 400 / 1.0 = 215.38, and 215.39 is the minimum to rescue just one.

FYI, this is my understanding:
For 1000 FLOW as collateral, and flow price is 0.5 MOET, then :

  1. to avoid rebalancing (pulling from top up source), debt must be below 363.63 (1000 * 0.5 * 0.8 / D = 1.1; D = 363.63)
  2. to avoid liquidation, debt must be below 400 (1000 * 0.5 * 0.8 / D = 1; D = 400)
  3. to avoid become bad debt (users don't care, but protocol cares), debt must be below 500 (1000 * 0.5 / D = 1; D = 500)
  4. to avoid become total dead debt (users don't care, but protocol cares): collateral still have collateral (FLOW > 0)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch, thanks for pointing this out! You’re right, so I’ve updated the test in comment 4268477

Comment on lines +254 to +261
// minHealth = 1.1: required deposit per position to reach minHealth after 50% price crash:
// effectiveCollateral = 1 000 * 0.5 * 0.8 = 400
// effectiveDebt ≈ 615.38
//
// Ideal health = 400 / (615.38 - required) = 1.3
// Required MOET ≈ 307.69 MOET
//
// left 310 MOET which is enough for one position, not both
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Oh, I see. the minimum health factor to avoid liquidation is 1, not 1.1.

the minHealth 1.1 is when the low threshold to trigger rebalancing, not liquidation.

So 615.38 - 400 / 1.0 = 215.38, and 215.39 is the minimum to rescue just one.

FYI, this is my understanding:
For 1000 FLOW as collateral, and flow price is 0.5 MOET, then :

  1. to avoid rebalancing (pulling from top up source), debt must be below 363.63 (1000 * 0.5 * 0.8 / D = 1.1; D = 363.63)
  2. to avoid liquidation, debt must be below 400 (1000 * 0.5 * 0.8 / D = 1; D = 400)
  3. to avoid become bad debt (users don't care, but protocol cares), debt must be below 500 (1000 * 0.5 / D = 1; D = 500)
  4. to avoid become total dead debt (users don't care, but protocol cares): collateral still have collateral (FLOW > 0)

UlyanaAndrukhiv and others added 2 commits April 1, 2026 11:01
Co-authored-by: Taras Maliarchuk <maliarchuk@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rebalancing Failures

3 participants