Pool Shutdown

Bootstrap requirements met for eth
Bootstrap requirements met for wbtc
Bootstrap requirements met for link

Pool ShutdownΒΆ

The system becomes exposed to potential issues when the trading liquidity on any asset is low. An arbitrary threshold of 1,000 BNT trading liquidity determines if the protocol will continue to allow trading on the affected asset; however, the trigger for this process is determined by liquidity addition and removal operations, not by trading. Therefore, it is possible (and healthy) for a liquidity pool to continue trading during intermittent volatility events, even if the BNT liquidity is traded beyond this threshold.

To examine this process, consider the following scenario. A trading pool has 1,000 each of BNT and TKN in available liquidity, then a trader performs a swap, removing BNT from the pool. Under this circumstance, although the pool has dropped below its minimum liquidity requirement, the protocol takes no action and trading can continue as normal.

However, the trading liquidity is now supercritical; add/remove liquidity actions can cause it to cease functioning. For example, suppose that a TKN liquidity provider executes a withdrawal at this state. After the algorithm has completed its work, the protocol will check that the minimum liquidity threshold is observed. In most cases, a withdrawal performed from this state will result in the pool becoming illiquid, and will trigger the shutdown. However, if there is an add liquidity event during this period that raises the BNT trading liquidity above the threshold, the pool is rescued. If the add liquidity fails to raise the BNT reserve above its threshold, the pool will also enter shutdown. These checks are always performed after the add/remove liquidity event.

During a shutdown, the pool effectively returns to its bootstrapping phase. The protocol withdraws and destroys all of the BNT trading liquidity, and the pool will remain in shutdown until the BancorDAO msig signers approve new BNT liquidity. However, the vault retains all TKN, which are available for withdrawal with modified logic.

When the pool has returned to the bootstrapping phase, the protocol cannot know the value of TKN relative to BNT. However, the value of the bnTKN pool tokens (denominated in TKN) are still known. Therefore, in a TKN surplus, users can withdraw as normal and are essentially unaffected by the state change. In a TKN deficit, the protocol is unable to evaluate the BNT reimbursement, and so a generic pro-rata ownership model must be used until the pool is re-established.

As defined previously, a TKN is in surplus when the total vault balance is greater than the staked amount, after accounting for the exit fee. In this case, the trading liquidity is zero, and all TKN in the vault are non-trading. Therefore, only the c component is required to evaluate the surplus condition:

where e is the TKN balance of the staking ledger, and n is the withdrawal fee (e.g. 0.0025, or 0.25%). So long as the above expression evaluates as True, the protocol is in an effective surplus (i.e. the quantity of TKN exceeds that of the combined user stakes). Therefore, even in shutdown, it is guaranteed that any user withdrawing will receive the full value of their stake in TKN.

If the above inequality is False, then there is a technical deficit, and the user is entitled to receive their pro rata share of the remaining illiquid TKN:

In the case of a deficit, the external protection wallet continues to reimburse users as normal. Therefore, provided there is an external protection contract in place, users can continue to withdraw the full value of their stake in TKN, regardless of the deficit, provided there are sufficient funds to support it.

#view enabled pools
state = v3.get_state()

[f'{tkn_name}={state.tokens[tkn_name].is_trading_enabled}' for tkn_name in state.whitelisted_tokens]
['bnt=False', 'eth=True', 'wbtc=True', 'link=True']
from bancor_research.bancor_simulator.v3.spec import get_bnt_trading_liquidity, get_tkn_trading_liquidity

get_bnt_trading_liquidity(state, 'eth')
Decimal('19055.238095238095238095')
get_tkn_trading_liquidity(state, 'eth')
Decimal('21.000000000000000000')
# remove liquidity

state.decrease_bnt_trading_liquidity('eth', 19000)
get_bnt_trading_liquidity(state, 'eth')
Decimal('55.238095238095238095')
from bancor_research.bancor_simulator.v3.spec import check_pool_shutdown, shutdown_pool

# now trigger the automated shutdown based on liquidity
requires_shutdown = check_pool_shutdown(state, 'eth')

if requires_shutdown:
    print('shutting down pool')
    shutdown_pool(state, 'eth')
shutting down pool
#confirm that pool was disabled as expected


[f'{tkn_name}={state.tokens[tkn_name].is_trading_enabled}' for tkn_name in state.whitelisted_tokens]
['bnt=False', 'eth=False', 'wbtc=True', 'link=True']