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

Fix rm pause #589

Merged
merged 77 commits into from
Aug 29, 2023
Merged

Fix rm pause #589

merged 77 commits into from
Aug 29, 2023

Conversation

GalloDaSballo
Copy link
Collaborator

@GalloDaSballo GalloDaSballo commented Aug 22, 2023

Closes #587

MUST REVIEW

Adds a Delay of X SECONDS before allowing liquidations

Use beginRMLiquidationCooldown to trigger the timer

Use stopRMLiquidationCooldown to cancel it

After a sequence of liquidations _checkLiquidateCoolDownAndReset is called, to reset the timer

This can still cause risks wrt to desynch of the value, but hopefully is an improvement and a simplification of the design

TO FINISH

  • Is the delay enforced in ALL Liquidations for CDPs liquidatable only in RM?
  • Is RM immediately exited after such liquidations have happened (and is the flag set back to UNSET_TIMESTAMP_FLAG right after?)
  • How do we improve the "desynch" issue? (see BO calls I added)

Towards CEI Conformity

See rationale on how hooks are called

https://miro.com/app/board/uXjVMrhxeT8=/?share_link_id=950890293382

NOTE

We break CEI in the main external functions as a way to ensure we are recording the latest proper state for RM

This ensures that:
-> Repay / Closing / Opening that undos RM resets the Timer

This + Synching in Liquidations should cover the majority of Desynch Cases

  • Check Redemptions for the desynch above
RM Triggers:
- Price Change - PRICE UP - If RM is still going, countdown is added, if RM is averted, I can manually reapply the glass
- Fee Split - STETH UP - if RM is still going, countdown is added, else I can manually reapply the glass or via any operation or manually

RM untriggers:
- Price Change - PRICE UP - If RM is still going, countdown is unchanged, if RM is averted, I can manually reapply the glass
- Fee Split - STETH UP - if RM is still going, countdown is unchanged, else I can manually reapply the glass or via any operation

- Open Cdp Positively - TCR UP - After such an operation, TCR is up and glass is applied automatically
- Repay / Adjust - TCR UP - After such an operation, TCR is up and glass is applied automatically
- Close - After such an operation, TCR is up and glass is applied automatically

- Liquidate - After such an operation, TCR is up and glass is applied automatically
- Redeem - After such an operation, TCR is up and glass is applied automatically

Debugging Branch

DO NOT MERGE THIS!!!
https://github.com/Badger-Finance/ebtc/tree/chore-logs-revert-batch-liquidate

Weird Stuff Left

  • _sequenceLiqToBatchLiq can return 0 -> Reverts with underflow / overflow
  • 1e18 check when stETH is slashed, still here...
  • _sequenceLiqToBatchLiq seems to not be correct (TODO after)

@GalloDaSballo
Copy link
Collaborator Author

NOTE:
Test failing
[FAIL. Reason: CdpManager: ICR is not below liquidation threshold in current mode] test_snipeViaPriceDradwown() (gas: 1479873)

Rightfully fails since we mitigated the sniping

@rayeaster
Copy link
Contributor

rayeaster commented Aug 22, 2023

it still depends on external interaction to explicitly trigger the "desync" and is susceptible to potential (maybe of lower likelihood) attack mentioned in #587 (review)

Another brainstorm idea (maybe not necessarily a "real" worthy attack vector): Say after time wait pass and system is still in RM, now liquidator is eager to start liquidation work, but attacker could frontrun every liquidation attempt to trigger another time wait and put the system in wait forever (render Recovery Mode not working as expected).

@GalloDaSballo GalloDaSballo mentioned this pull request Aug 22, 2023
2 tasks
@dapp-whisperer
Copy link
Contributor

dapp-whisperer commented Aug 22, 2023

DRY

This was already duplicated code, but it's a good chance to consolidate.
I would probably rewrite this whole check to an internal function
image
_canLiquidateInCurrentMode(_icr, _TCR, _recovery)

Global state synced before any external operation

we should follow the rule of applyPendingGlobalState() before doing the RM check in the external setters

@rayeaster
Copy link
Contributor

rayeaster commented Aug 23, 2023

DRY

This was already duplicated code, but it's a good chance to consolidate. I would probably rewrite this whole check to an internal function image _canLiquidateInCurrentMode(_icr, _TCR, _recovery)

Global state synced before any external operation

we should follow the rule of applyPendingGlobalState() before doing the RM check in the external setters

good point, how about add checkLiquidateCoolDownAndReset() in applyPendingGlobalState() directly?

@GalloDaSballo
Copy link
Collaborator Author

Pushing fixes for QA issues (error messages)

@dapp-whisperer
Copy link
Contributor

dapp-whisperer commented Aug 28, 2023

Redemptions Optimization

Guiding ideas:

  • dedup reads, we shouldn't be reading the same thing multiple time
  • however, not willing to make deeper / more significant code changes at this point

The RedemptionTotals struct now tracks the aggregate amount of collateral surplus that is sent to redeemed parties. This is required to know what the collateral of the system will be after the redemption loop is done so we can virtually calculate the TCR for Grace Period.

When get this value by tracking the collSurplus for each fully redeemed Cdp, and adding them to the total in a way that fits the existing code

moved "setting up the next iteration stuff" to the bottom of the core redemption loop

Finally, there are some debug checks added to confirm that the live system debt and collShares at the end of the operation (after interactions) match what we expected when we did the TCR calculation for the Grace Period

Next Up

We see that the Grace Period calcs for liquidations and redemptions are identical. This means it's a good candidate to dedup and move into an internal function.

@dapp-whisperer
Copy link
Contributor

Code Dedup

The liquidation and redemption grace period check logic has been distilled into _syncRecoveryModeGracePeriod function.
Much cleaner.

Debug checks left in redemptions code for now.

function applyPendingGlobalState() external;
function applyPendingGlobalState() external; // Accrues StEthFeeSplit without influencing Grace Period

function syncPendingGlobalState() external; // Accrues StEthFeeSplit and influences Grace Period
Copy link
Contributor

Choose a reason for hiding this comment

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

would be nice to add to comment: typically used by governance-privileged setters

@GalloDaSballo
Copy link
Collaborator Author

I'd say let's get rid of Debug events

Use the 1 invariant for Synching of TCR before and After and have Echidna run for a long time

@dapp-whisperer
Copy link
Contributor

Grace Period Governance

There is now an auth-gated setter for the grace period, setGracePeriod
It shouldn't be able to set a grace period below the hardcoded minimum

A couple additional clarity renames were sent in.

@dapp-whisperer dapp-whisperer merged commit b4f4682 into feat/spearbit-misc Aug 29, 2023
@GalloDaSballo GalloDaSballo deleted the fix-rm-pause branch September 18, 2023 14:43
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.

4 participants