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

feat(RewardsStreamerMP): introduce emergency mode and ability to leave #72

Merged
merged 1 commit into from
Nov 28, 2024

Conversation

0x-r4bbit
Copy link
Collaborator

@0x-r4bbit 0x-r4bbit commented Oct 28, 2024

This adds a new emergency mode that can be enabled by the owner of the system.
When in emergency mode, stakers or StakeVaults can leave the system immediately.

This also applies when there was a malicious upgrade and a call to
emergencyModeEnabled() panics.

To have this in a fully secure manner, we still have to add the counter
part of "leaving" the system. This will allow users that don't agree
with a (malicious) upgrade to get their funds out of the vaults
regardless.

Closes #66

Checklist

Ensure you completed all of the steps below before submitting your pull request:

  • Added natspec comments?
  • Ran pnpm adorno?
  • Ran pnpm verify?

@3esmit
Copy link
Contributor

3esmit commented Oct 28, 2024

The ideal logic would be:

Stake Manager contains a flag which is read by Stake Vault. When this flag is true, Stake Vault just allows withdraw and Stake Manager wont accept any iteractions anymore.

@0x-r4bbit 0x-r4bbit force-pushed the feat/emergency-exit branch 3 times, most recently from 2f4b5a0 to 9e1dcaf Compare October 30, 2024 11:58
@0x-r4bbit
Copy link
Collaborator Author

@3esmit So, the reason I've done it this way (StakeManager sets flag, and reverts accordingly in functions where necessary), is because the logic for preventing interaction with the manager should stay the same no matter what stakevault you interact with.

For example, if we upgrade StakeVault to a different version, we'd otherwise have to ensure that it reverts in functions where it should revert.

If we keep the revert logic in the StakeManager, that's one thing less to keep in mind.

--

Are there any other good reasons to have StakeVault explicitly check emergency mode first, before interacting?

Happy to make the necessary changes in that case, but right now I don't see how that would improve the state.

@0x-r4bbit
Copy link
Collaborator Author

I've updated this PR with a certora rule that ensures only view functions, ownable functions, trusted codehash functions and leave() are callable when in emergency mode

@@ -132,6 +135,27 @@ contract RewardsStreamerMP is IStakeManager, TrustedCodehashAccess, ReentrancyGu
account.accountRewardIndex = rewardIndex;
}

function leave() external onlyTrustedCodehash nonReentrant {
Copy link
Contributor

Choose a reason for hiding this comment

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

emergency mode should not have any complex logic. what happens if there is a problem, such as underflow, inside of _updateGlobalState() or _updateAccountMP()?

Emergency exit suppousedly should not process any storage or anything, just allow withdraws.

uint256 aliceInitialRewardBalance = rewardToken.balanceOf(vaults[alice]);

streamer.enableEmergencyMode();

Copy link
Contributor

Choose a reason for hiding this comment

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

To properly test emergency mode, cause the code to make a division by zero in the logic, or whatever unexpected fail.

There would be no reason in having an emergency mode for expected cases, that wouldnt be called emergency mode.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

So this is now testing the "benign" exit mode case, where the owner enables it, allowing users to exit.


uint256 accountRewards = calculateAccountRewards(msg.sender);
if (accountRewards > 0) {
distributeRewards(msg.sender, accountRewards);
Copy link
Contributor

Choose a reason for hiding this comment

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

In contrast with emergency exits on real world, they are usually used when there is a fire in the building. In that case, you don't go grab all your stuff before leave, you just run for your life directly to the exit.

Account storage account = accounts[msg.sender];

if (account.stakedBalance > 0) {
_updateGlobalState();
Copy link
Contributor

Choose a reason for hiding this comment

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

Why need to update global state if its not going being used anymore?

src/StakeVault.sol Outdated Show resolved Hide resolved
@0x-r4bbit 0x-r4bbit force-pushed the feat/emergency-exit branch 2 times, most recently from cfb50de to f5109a9 Compare November 27, 2024 09:19
@0x-r4bbit
Copy link
Collaborator Author

@3esmit @gravityblast I've updated this PR according to the discussion with had with @3esmit

In summary:

  1. Emergency exit != leaving
  2. Emergency exit allows for leaving the system without any state changes, however vaults still have to check if emergency mode is enabled
  3. If reading emergency mode panics due to malicious upgrade, users will be able to leave using leave() which I'll provide in a separate PR

Please give this another review

src/RewardsStreamerMP.sol Outdated Show resolved Hide resolved
@@ -65,6 +66,7 @@ contract RewardsStreamerMPTest is Test {
address account;
uint256 rewardBalance;
uint256 stakedBalance;
uint256 vaultBalance;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I had to introduce vaultBalance here so we can differentiate between accountInfo.stakedBalance and balanceOf(vault)

This adds a new emergency mode that can be enabled by the owner of the system.
When in emergency mode, stakers or `StakeVault`s can leave the system immediately.

This also applies when there was a malicious upgrade and a call to
`emergencyModeEnabled()` panics.

To have this in a fully secure manner, we still have to add the counter
part of "leaving" the system. This will allow users that don't agree
with a (malicious) upgrade to get their funds out of the vaults
regardless.

Closes #66
@0x-r4bbit 0x-r4bbit merged commit 1e703e3 into main Nov 28, 2024
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

Successfully merging this pull request may close these issues.

Allow accounts to exit the system
3 participants