From fe2adbe9fbeb8577883716c55cfa223e9aefce75 Mon Sep 17 00:00:00 2001 From: Sheng Lundquist Date: Wed, 11 Sep 2024 15:55:44 -0700 Subject: [PATCH] Don't checkpoint on paused pools. Don't check for previous checkpoints in invariance checks if pool is paused (#1682) --- scripts/checkpoint_bots.py | 22 +++++++++++++++- .../ethpy/hyperdrive/interface/_event_logs.py | 25 +++++++++++++++++++ .../hyperdrive/interface/read_interface.py | 11 ++++++++ .../hyperfuzz/system_fuzz/invariant_checks.py | 4 +++ 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/scripts/checkpoint_bots.py b/scripts/checkpoint_bots.py index 1ea222a65..539aa6499 100644 --- a/scripts/checkpoint_bots.py +++ b/scripts/checkpoint_bots.py @@ -25,6 +25,7 @@ from agent0.core.base.make_key import make_private_key from agent0.ethpy.base import get_account_balance, smart_contract_preview_transaction, smart_contract_transact from agent0.ethpy.hyperdrive import get_hyperdrive_pool_config, get_hyperdrive_registry_from_artifacts +from agent0.ethpy.hyperdrive.interface._event_logs import EARLIEST_BLOCK_LOOKUP from agent0.hyperlogs.rollbar_utilities import initialize_rollbar, log_rollbar_exception, log_rollbar_message # Checkpoint bot has a lot going on @@ -217,7 +218,26 @@ async def run_checkpoint_bot( log_level=logging.INFO, ) - if enough_time_has_elapsed and checkpoint_doesnt_exist: + # Check to see if the pool is paused. We don't run checkpoint bots on this pool if it's paused. + paused_events = hyperdrive_contract.events.PauseStatusUpdated.get_logs( + from_block=EARLIEST_BLOCK_LOOKUP.get(chain_id, "earliest") + ) + is_paused = False + if len(list(paused_events)) > 0: + # Get the latest pause event + # TODO get_logs likely returns events in an ordered + # fashion, but we iterate and find the latest one + # just in case + latest_pause_event = None + max_block_number = 0 + for event in paused_events: + if event["blockNumber"] > max_block_number: + max_block_number = event["blockNumber"] + latest_pause_event = event + assert latest_pause_event is not None + is_paused = latest_pause_event["args"]["isPaused"] + + if enough_time_has_elapsed and checkpoint_doesnt_exist and not is_paused: logging_str = f"Pool {pool_name} for {checkpoint_time=}: submitting checkpoint" logging.info(logging_str) if log_to_rollbar: diff --git a/src/agent0/ethpy/hyperdrive/interface/_event_logs.py b/src/agent0/ethpy/hyperdrive/interface/_event_logs.py index 9df4db4bf..9004da3a1 100644 --- a/src/agent0/ethpy/hyperdrive/interface/_event_logs.py +++ b/src/agent0/ethpy/hyperdrive/interface/_event_logs.py @@ -142,6 +142,31 @@ def _get_initialize_events( return out_events +def _get_pool_is_paused( + hyperdrive_interface: HyperdriveReadInterface, +) -> bool: + chain_id = hyperdrive_interface.web3.eth.chain_id + # Check to see if the pool is paused. We don't run checkpoint bots on this pool if it's paused. + paused_events = hyperdrive_interface.hyperdrive_contract.events.PauseStatusUpdated.get_logs( + from_block=EARLIEST_BLOCK_LOOKUP.get(chain_id, "earliest") + ) + is_paused = False + if len(list(paused_events)) > 0: + # Get the latest pause event + # TODO get_logs likely returns events in an ordered + # fashion, but we iterate and find the latest one + # just in case + latest_pause_event = None + max_block_number = 0 + for event in paused_events: + if event["blockNumber"] > max_block_number: + max_block_number = event["blockNumber"] + latest_pause_event = event + assert latest_pause_event is not None + is_paused = latest_pause_event["args"]["isPaused"] + return is_paused + + # TODO we can add a helper function to get all trading events here def _get_open_long_events( hyperdrive_interface: HyperdriveReadInterface, diff --git a/src/agent0/ethpy/hyperdrive/interface/read_interface.py b/src/agent0/ethpy/hyperdrive/interface/read_interface.py index c1d669c81..737717204 100644 --- a/src/agent0/ethpy/hyperdrive/interface/read_interface.py +++ b/src/agent0/ethpy/hyperdrive/interface/read_interface.py @@ -52,6 +52,7 @@ _get_initialize_events, _get_open_long_events, _get_open_short_events, + _get_pool_is_paused, _get_redeem_withdrawal_shares_events, _get_remove_liquidity_events, _get_transfer_single_events, @@ -646,6 +647,16 @@ def get_gov_fees_accrued(self, block_identifier: BlockIdentifier | None = None) """ return _get_gov_fees_accrued(self.hyperdrive_contract, block_identifier) + def get_pool_is_paused(self) -> bool: + """Get whether or not the pool is paused from events. + + Returns + ------- + bool + Whether or not the pool is paused. + """ + return _get_pool_is_paused(self) + def get_transfer_single_events( self, from_block: BlockIdentifier | None = None, diff --git a/src/agent0/hyperfuzz/system_fuzz/invariant_checks.py b/src/agent0/hyperfuzz/system_fuzz/invariant_checks.py index f5aec85f2..10f9d687d 100644 --- a/src/agent0/hyperfuzz/system_fuzz/invariant_checks.py +++ b/src/agent0/hyperfuzz/system_fuzz/invariant_checks.py @@ -301,6 +301,10 @@ def _check_previous_checkpoint_exists( ): return InvariantCheckResults(failed=False, exception_message=None, exception_data={}, log_level=None) + # We ignore this test if the pool is paused + if interface.get_pool_is_paused(): + return InvariantCheckResults(failed=False, exception_message=None, exception_data={}, log_level=None) + # Otherwise, we ensure the previous checkpoint exists previous_checkpoint = get_hyperdrive_checkpoint( interface.hyperdrive_contract, Timestamp(previous_checkpoint_time), pool_state.block_number