Developers
Search…
Recovery Mode

Credit

Credit for the below article goes to 0xSkly of the BeethovenX Team. You can find the original article on Medium.
Disclaimer: The article has been lightly edited for formatting and uniformity with the rest of the docs, but has been kept in a first-person format. Any opinions expressed below are those of the author and should not be considered opinions of Balancer Labs, BeethovenX, BalancerDAO, or any other organization.

RecoveryMode

Balancer Labs introduces a new mechanism to secure user funds in emergency situations. This is a technical insight into the RecoveryMode class which enables this functionality when inherited.
This is intended to provide a safe way to exit any pool during some
kind of emergency, to avoid locking funds in the event the pool
enters a non-functional state (i.e., some code that normally runs
during exits is causing them to revert).

What's the Effect When a Pool is in RecoveryMode ?

A special clean exit function is enabled which runs the absolute minimum code necessary to exit proportionally.
In particular:
  • Stable pools do not try to calculate the invariant
  • No protocol fees are collected
It’s important to note that the pool is not disabled, which means regular swaps, joins, and exits are still possible.

Who is Authorized to Put a Pool Into RecoveryMode ?

The external function enableRecoveryMode is protected by the Authorizer configured on the Vault. Therefore any address granted permission on the Authorizer can enable recovery mode.
This permission needs to be treated with care since the RecoveryMode functionality could be misused.

What Pools Have a Recovery Exit Available ?

The BasePool class which is a base layer for all current pools inherits from the RecoveryMode class enabling the recovery exit functionality for all new pools deployed (which are based on the BasePool class).
Note: Many pools of many poolTypes were created before this was added to BasePool, so there is a decent chance the pool you're in does not have this functionality. As more pools are created using newer factories, this scenario should change.

Inside the RecoveryMode Exit

The default implementation is within the RecoveryMode class and needs to be overwritten for special pools like a PhantomStablePool
I’ve added some comments to the function parameters for some context. So we extract the provided BPT from the userData and calculate the share of the total supply by bptAmountIn / totalSupply . Based on this ratio we can then calculate the share of each token in the pool. See _computeProportionalAmountsOut

But What About StablePhantomPools ?

StablePhantomPools use pre-minted BPT, so therefore we cannot use the totalSupply to calculate the share of a user. That’s why there is a custom implementation.
We see that before calling the default implementation with super._doRecoveryModeExit(...), we subtract the pre-minted BPT. This results in a ‘virtual supply’ which is the actual BPT in circulation.
But how do we know the actual BPT in circulation? Remember the balances parameter which includes the total balance of all tokens in the pool. This also includes the pre minted BPT. So with this, we can do totalSupply — balances[indexOfBpt] which results in all BPT in circulation. Additionally we also need to remove the BPT token from the balances array. This is what happens in _dropBptItemFromBalances(balances)

How is it All Wired Up ?

The entry point to a pool exit is the Vault class which delegates the call to the respective pool contract. The base layer of each pool contract is the BasePool which also implements the onExitPool hook:

Conclusion

With this mechanism in place, we gain an additional safety layer for users to exit with their funds in case of some unexpected pool behavior.
Last modified 1mo ago
Copy link
On this page
Credit
RecoveryMode
What's the Effect When a Pool is in RecoveryMode ?
Who is Authorized to Put a Pool Into RecoveryMode ?
What Pools Have a Recovery Exit Available ?
Inside the RecoveryMode Exit
But What About StablePhantomPools ?
How is it All Wired Up ?
Conclusion