From 0718e7e8880c5d233e882ac7526d33ad5cdf97df Mon Sep 17 00:00:00 2001 From: Sheng Lundquist Date: Mon, 28 Oct 2024 15:37:19 -0700 Subject: [PATCH 01/15] Add lp doesn't compare min txn amount as shares --- src/agent0/core/hyperdrive/policies/random.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/agent0/core/hyperdrive/policies/random.py b/src/agent0/core/hyperdrive/policies/random.py index 73d7239b31..2f9c7da4af 100644 --- a/src/agent0/core/hyperdrive/policies/random.py +++ b/src/agent0/core/hyperdrive/policies/random.py @@ -114,7 +114,7 @@ def get_available_actions( """ pool_state = interface.current_pool_state # The minimum transaction amount is dependent on if we're trading with - # base or vault shares + # base or vault shares. The config's min transaction amount is in units of base. if interface.base_is_yield: minimum_transaction_amount = interface.get_minimum_transaction_amount_shares() else: @@ -386,12 +386,8 @@ def add_liquidity_with_random_amount( list[Trade[HyperdriveMarketAction]] A list with a single Trade element for adding liquidity to a Hyperdrive pool. """ - # The minimum transaction amount is dependent on if we're trading with - # base or vault shares - if interface.base_is_yield: - minimum_transaction_amount = interface.get_minimum_transaction_amount_shares() - else: - minimum_transaction_amount = interface.pool_config.minimum_transaction_amount + # The minimum transaction amount input is always compared against the pool config's minimum transaction amount + minimum_transaction_amount = interface.pool_config.minimum_transaction_amount # take a guess at the trade amount, which should be about 10% of the agent’s budget initial_trade_amount = FixedPoint( From 62bb07327ce5debc06694f93d176c796fdcead7e Mon Sep 17 00:00:00 2001 From: Sheng Lundquist Date: Mon, 28 Oct 2024 15:38:41 -0700 Subject: [PATCH 02/15] Use div up when using fallback min txn amount --- src/agent0/ethpy/hyperdrive/interface/_contract_calls.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/agent0/ethpy/hyperdrive/interface/_contract_calls.py b/src/agent0/ethpy/hyperdrive/interface/_contract_calls.py index 9bb5cc72f4..9f1a616c31 100644 --- a/src/agent0/ethpy/hyperdrive/interface/_contract_calls.py +++ b/src/agent0/ethpy/hyperdrive/interface/_contract_calls.py @@ -58,7 +58,8 @@ def _get_minimum_transaction_amount_shares( return FixedPoint(scaled_value=shares_value) except PypechainCallException: # Fallback to using vault share price - shares_value = minimum_transaction_amount_base / interface.current_pool_state.pool_info.vault_share_price + # We div_up to overestimate the min txn amount + shares_value = minimum_transaction_amount_base.div_up(interface.current_pool_state.pool_info.vault_share_price) return shares_value From b486903aa86016f3d6a1b4f36e82b800e94e6f5a Mon Sep 17 00:00:00 2001 From: Sheng Lundquist Date: Mon, 28 Oct 2024 15:40:22 -0700 Subject: [PATCH 03/15] Decrease default iterations before reforking --- scripts/fork_fuzz_bots.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/fork_fuzz_bots.py b/scripts/fork_fuzz_bots.py index 2ba087b513..63c1b9da5b 100644 --- a/scripts/fork_fuzz_bots.py +++ b/scripts/fork_fuzz_bots.py @@ -396,7 +396,7 @@ def parse_arguments(argv: Sequence[str] | None = None) -> Args: ) parser.add_argument( "--num-iterations-per-episode", - default=1000, + default=300, help="The number of iterations to run for each random pool config.", ) From f383c2b0c7091301d6f3ccd8d7c08d689e19c48b Mon Sep 17 00:00:00 2001 From: Sheng Lundquist Date: Mon, 28 Oct 2024 15:46:20 -0700 Subject: [PATCH 04/15] Log trades in info --- src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py index 30de89b75e..7cb5485d35 100644 --- a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py +++ b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py @@ -363,7 +363,7 @@ def run_fuzz_bots( raise FuzzAssertionException(*fuzz_exceptions) # Logs trades - logging.debug([[trade.__name__ for trade in agent_trade] for agent_trade in trades]) + logging.info([[trade.__name__ for trade in agent_trade] for agent_trade in trades]) # Check agent funds and refund if necessary assert len(agents) > 0 From f0327f1858675aadf885510d24b0b515956c0fd8 Mon Sep 17 00:00:00 2001 From: Sheng Lundquist Date: Mon, 28 Oct 2024 15:50:00 -0700 Subject: [PATCH 05/15] Log trades per pool --- src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py index 7cb5485d35..dbd730d9a2 100644 --- a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py +++ b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py @@ -362,8 +362,10 @@ def run_fuzz_bots( # Otherwise, we raise a new fuzz assertion exception wht the list of exceptions raise FuzzAssertionException(*fuzz_exceptions) - # Logs trades - logging.info([[trade.__name__ for trade in agent_trade] for agent_trade in trades]) + # Logs trades + logging.info( + "Trades on %s: %s", pool.name, [[trade.__name__ for trade in agent_trade] for agent_trade in trades] + ) # Check agent funds and refund if necessary assert len(agents) > 0 From f83eaf2afcbf0977c9bc3bdd95a2eca41e876cfc Mon Sep 17 00:00:00 2001 From: Sheng Lundquist Date: Mon, 28 Oct 2024 15:57:33 -0700 Subject: [PATCH 06/15] Another logging fix --- src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py index dbd730d9a2..768eb2663e 100644 --- a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py +++ b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py @@ -289,13 +289,13 @@ def run_fuzz_bots( if num_iterations is not None and iteration >= num_iterations: break iteration += 1 - # Execute the agent policies - trades = [] if run_async: # There are race conditions throughout that need to be fixed here raise NotImplementedError("Running async not implemented") for pool in hyperdrive_pools: logging.info("Trading on %s", pool.name) + # Execute the agent policies + pool_trades = [] for agent in agents: # If we're checking invariance, and we're doing the lp share test, # we need to get the pending pool state here before the trades. @@ -325,7 +325,7 @@ def run_fuzz_bots( # Otherwise, we ignore crashes, we want the bot to keep trading # These errors will get logged regardless - trades.append(agent_trade) + pool_trades.append(agent_trade) # Check invariance on every iteration if we're not doing lp_share_price_test. # Only check invariance if a trade was executed for lp_share_price_test. @@ -364,7 +364,9 @@ def run_fuzz_bots( # Logs trades logging.info( - "Trades on %s: %s", pool.name, [[trade.__name__ for trade in agent_trade] for agent_trade in trades] + "Trades on %s: %s", + pool.name, + [[trade.__name__ for trade in agent_trade] for agent_trade in pool_trades], ) # Check agent funds and refund if necessary From ad2c643931f327d79e91175e6f02a3ca947b3c42 Mon Sep 17 00:00:00 2001 From: Sheng Lundquist Date: Mon, 28 Oct 2024 16:13:03 -0700 Subject: [PATCH 07/15] Keeping track of past trades --- .../hyperfuzz/system_fuzz/run_fuzz_bots.py | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py index 768eb2663e..0b499bfffc 100644 --- a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py +++ b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py @@ -3,6 +3,7 @@ from __future__ import annotations import logging +from collections import deque from typing import Callable, Sequence from eth_typing import ChecksumAddress @@ -52,6 +53,8 @@ LP_SHARE_PRICE_GOVERNANCE_LP_FEE_RANGE: tuple[float, float] = (0, 0) LP_SHARE_PRICE_GOVERNANCE_ZOMBIE_FEE_RANGE: tuple[float, float] = (0, 0) +MAX_TRADE_HISTORY = 10 + # pylint: disable=too-many-locals def generate_fuzz_hyperdrive_config(rng: Generator, lp_share_price_test: bool, steth: bool) -> LocalHyperdrive.Config: @@ -245,7 +248,7 @@ def run_fuzz_bots( policy=PolicyZoo.random, policy_config=PolicyZoo.random.Config( slippage_tolerance=slippage_tolerance, - trade_chance=FixedPoint("0.8"), + trade_chance=FixedPoint("1.0"), randomly_ignore_slippage_tolerance=True, ), ) @@ -266,7 +269,7 @@ def run_fuzz_bots( policy=PolicyZoo.random_hold, policy_config=PolicyZoo.random_hold.Config( slippage_tolerance=slippage_tolerance, - trade_chance=FixedPoint("0.8"), + trade_chance=FixedPoint("1.0"), randomly_ignore_slippage_tolerance=True, max_open_positions_per_pool=1_000, ), @@ -292,6 +295,12 @@ def run_fuzz_bots( if run_async: # There are race conditions throughout that need to be fixed here raise NotImplementedError("Running async not implemented") + + # We use deque collection to allow for fast prepending to list + # By specifying a maxlen, items get popped off on the other side + # of the deque as new items are added + trade_history = {pool.name: deque(maxlen=MAX_TRADE_HISTORY) for pool in hyperdrive_pools} + for pool in hyperdrive_pools: logging.info("Trading on %s", pool.name) # Execute the agent policies @@ -325,7 +334,7 @@ def run_fuzz_bots( # Otherwise, we ignore crashes, we want the bot to keep trading # These errors will get logged regardless - pool_trades.append(agent_trade) + pool_trades.extend(agent_trade) # Check invariance on every iteration if we're not doing lp_share_price_test. # Only check invariance if a trade was executed for lp_share_price_test. @@ -362,12 +371,19 @@ def run_fuzz_bots( # Otherwise, we raise a new fuzz assertion exception wht the list of exceptions raise FuzzAssertionException(*fuzz_exceptions) - # Logs trades - logging.info( - "Trades on %s: %s", - pool.name, - [[trade.__name__ for trade in agent_trade] for agent_trade in pool_trades], - ) + trade_history[pool.name].appendleft(pool_trades) + + # Log trades + # Logs trades + logging.info("Trade history: %s", trade_history) + + # Look for past trades and limit the size of the list + for pool_name, trades in trade_history.items(): + if len(trades) == MAX_TRADE_HISTORY: + num_trades = [len(t) for t in trades] + if sum(num_trades) == 0: + logging.warning("No trades found on %s for the past %s iterations", pool_name, MAX_TRADE_HISTORY) + # TODO log to rollbar # Check agent funds and refund if necessary assert len(agents) > 0 From 71638a01e3fb9720041f9b4fe112a441351e5c26 Mon Sep 17 00:00:00 2001 From: Sheng Lundquist Date: Mon, 28 Oct 2024 16:18:50 -0700 Subject: [PATCH 08/15] pretty print trades --- src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py index 0b499bfffc..433dc95458 100644 --- a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py +++ b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py @@ -2,12 +2,14 @@ from __future__ import annotations +import json import logging from collections import deque from typing import Callable, Sequence from eth_typing import ChecksumAddress from fixedpointmath import FixedPoint +from hyperdrivetypes import BaseEvent from numpy.random import Generator from pypechain.core import PypechainCallException @@ -304,7 +306,7 @@ def run_fuzz_bots( for pool in hyperdrive_pools: logging.info("Trading on %s", pool.name) # Execute the agent policies - pool_trades = [] + pool_trades: list[BaseEvent] = [] for agent in agents: # If we're checking invariance, and we're doing the lp share test, # we need to get the pending pool state here before the trades. @@ -371,11 +373,11 @@ def run_fuzz_bots( # Otherwise, we raise a new fuzz assertion exception wht the list of exceptions raise FuzzAssertionException(*fuzz_exceptions) - trade_history[pool.name].appendleft(pool_trades) + trade_history[pool.name].appendleft([trade.__name__ for trade in pool_trades]) # Log trades # Logs trades - logging.info("Trade history: %s", trade_history) + logging.info("Trade history: \n %s", json.dumps(trade_history, indent=2)) # Look for past trades and limit the size of the list for pool_name, trades in trade_history.items(): From 32cb99addccbd6ff871cc96deba5717174b56699 Mon Sep 17 00:00:00 2001 From: Sheng Lundquist Date: Mon, 28 Oct 2024 16:21:28 -0700 Subject: [PATCH 09/15] Cast as list before print --- src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py index 433dc95458..2424f30920 100644 --- a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py +++ b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py @@ -376,8 +376,8 @@ def run_fuzz_bots( trade_history[pool.name].appendleft([trade.__name__ for trade in pool_trades]) # Log trades - # Logs trades - logging.info("Trade history: \n %s", json.dumps(trade_history, indent=2)) + print_trades = {k: list(v) for k, v in trade_history.items()} + logging.info("Trade history: \n %s", json.dumps(print_trades, indent=2)) # Look for past trades and limit the size of the list for pool_name, trades in trade_history.items(): From e99e545334cfb17d89c3acadbd74390c8f3412b1 Mon Sep 17 00:00:00 2001 From: Sheng Lundquist Date: Mon, 28 Oct 2024 16:29:55 -0700 Subject: [PATCH 10/15] Defining trade history outside loop --- .../hyperfuzz/system_fuzz/run_fuzz_bots.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py index 2424f30920..2b39878ba2 100644 --- a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py +++ b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py @@ -287,9 +287,15 @@ def run_fuzz_bots( agent.set_max_approval(pool=pool) agents.append(agent) + # We use deque collection to allow for fast prepending to list + # By specifying a maxlen, items get popped off on the other side + # of the deque as new items are added + trade_history = {pool.name: deque(maxlen=MAX_TRADE_HISTORY) for pool in hyperdrive_pools} + # Make trades until the user or agents stop us logging.info("Trading...") iteration = 0 + while True: if num_iterations is not None and iteration >= num_iterations: break @@ -298,15 +304,10 @@ def run_fuzz_bots( # There are race conditions throughout that need to be fixed here raise NotImplementedError("Running async not implemented") - # We use deque collection to allow for fast prepending to list - # By specifying a maxlen, items get popped off on the other side - # of the deque as new items are added - trade_history = {pool.name: deque(maxlen=MAX_TRADE_HISTORY) for pool in hyperdrive_pools} - for pool in hyperdrive_pools: logging.info("Trading on %s", pool.name) # Execute the agent policies - pool_trades: list[BaseEvent] = [] + pool_trades: list[str] = [] for agent in agents: # If we're checking invariance, and we're doing the lp share test, # we need to get the pending pool state here before the trades. @@ -336,7 +337,7 @@ def run_fuzz_bots( # Otherwise, we ignore crashes, we want the bot to keep trading # These errors will get logged regardless - pool_trades.extend(agent_trade) + pool_trades.extend([trade.__name__ for trade in agent_trade]) # Check invariance on every iteration if we're not doing lp_share_price_test. # Only check invariance if a trade was executed for lp_share_price_test. @@ -373,7 +374,7 @@ def run_fuzz_bots( # Otherwise, we raise a new fuzz assertion exception wht the list of exceptions raise FuzzAssertionException(*fuzz_exceptions) - trade_history[pool.name].appendleft([trade.__name__ for trade in pool_trades]) + trade_history[pool.name].appendleft(pool_trades) # Log trades print_trades = {k: list(v) for k, v in trade_history.items()} From 436e2ba2836c1e1089e1a691d4c865a96ef3f209 Mon Sep 17 00:00:00 2001 From: Sheng Lundquist Date: Tue, 29 Oct 2024 10:23:37 -0700 Subject: [PATCH 11/15] Using db to check if trades were made --- .../hyperfuzz/system_fuzz/invariant_checks.py | 1 - .../hyperfuzz/system_fuzz/run_fuzz_bots.py | 84 ++++++++++++++----- 2 files changed, 62 insertions(+), 23 deletions(-) diff --git a/src/agent0/hyperfuzz/system_fuzz/invariant_checks.py b/src/agent0/hyperfuzz/system_fuzz/invariant_checks.py index 858f69d3a7..22469f5d5c 100644 --- a/src/agent0/hyperfuzz/system_fuzz/invariant_checks.py +++ b/src/agent0/hyperfuzz/system_fuzz/invariant_checks.py @@ -196,7 +196,6 @@ def run_invariant_checks( rollbar_data=rollbar_data, rollbar_log_filter_func=rollbar_log_filter_func, ) - logging.info("Done") return out_exceptions diff --git a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py index 2b39878ba2..a39918c20e 100644 --- a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py +++ b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py @@ -14,6 +14,7 @@ from pypechain.core import PypechainCallException from agent0 import Chain, Hyperdrive, LocalChain, LocalHyperdrive, PolicyZoo +from agent0.chainsync.db.hyperdrive import get_trade_events from agent0.core.base.make_key import make_private_key from agent0.core.hyperdrive.interactive.hyperdrive_agent import HyperdriveAgent from agent0.ethpy.base import set_anvil_account_balance @@ -55,7 +56,7 @@ LP_SHARE_PRICE_GOVERNANCE_LP_FEE_RANGE: tuple[float, float] = (0, 0) LP_SHARE_PRICE_GOVERNANCE_ZOMBIE_FEE_RANGE: tuple[float, float] = (0, 0) -MAX_TRADE_HISTORY = 10 +TRADE_COUNT_PERIODIC_CHECK = 50 # pylint: disable=too-many-locals @@ -142,6 +143,62 @@ def generate_fuzz_hyperdrive_config(rng: Generator, lp_share_price_test: bool, s ) +def _check_trades_made_on_pool( + chain: Chain, hyperdrive_pools: Sequence[Hyperdrive], fuzz_start_block: int, iteration: int +): + # Get histogram counts of trades made on each pool + # Note we don't use interactive interface, as we want to do one query to get + # trade events for all tracked pools + assert chain.db_session is not None + trade_events = get_trade_events(chain.db_session, all_token_deltas=False) + # pylint: disable=protected-access + trade_events = chain._add_hyperdrive_name_to_dataframe(trade_events, "hyperdrive_address") + # Filter for trades since start of fuzzing + trade_events = trade_events[trade_events["block_number"] >= fuzz_start_block] + # Get counts + trade_counts = trade_events.groupby(["hyperdrive_name", "event_type"])["id"].count() + + logging.info("Trade counts: %s", trade_counts) + + # After 50 iterations, we expect all pools to make at least one trade + # Iteration at this point has already been incremented + if iteration % TRADE_COUNT_PERIODIC_CHECK == 0: + trade_counts = trade_counts.reset_index() + # Omission of rows means no trades of that type went through + for pool in hyperdrive_pools: + if pool.name not in trade_counts["hyperdrive_name"].values: + logging.error("Pool %s did not make any trades after %s iterations", pool.name, iteration) + # TODO log to rollbar + else: + pool_trade_event_counts = trade_counts[trade_counts["hyperdrive_name"] == pool.name][ + "event_type" + ].values + if "OpenLong" not in pool_trade_event_counts: + logging.error( + "Pool %s did not make any OpenLong trades after %s iterations", + ) + if "OpenShort" not in pool_trade_event_counts: + logging.error( + "Pool %s did not make any OpenShort trades after %s iterations", + ) + if "CloseLong" not in pool_trade_event_counts: + logging.error( + "Pool %s did not make any CloseLong trades after %s iterations", + ) + if "CloseShort" not in pool_trade_event_counts: + logging.error( + "Pool %s did not make any CloseShort trades after %s iterations", + ) + if "AddLiquidity" not in pool_trade_event_counts: + logging.error( + "Pool %s did not make any AddLiquidity trades after %s iterations", + ) + if "RemoveLiquidity" not in pool_trade_event_counts: + logging.error( + "Pool %s did not make any RemoveLiquidity trades after %s iterations", + ) + + def run_fuzz_bots( chain: Chain, hyperdrive_pools: Hyperdrive | Sequence[Hyperdrive], @@ -287,14 +344,11 @@ def run_fuzz_bots( agent.set_max_approval(pool=pool) agents.append(agent) - # We use deque collection to allow for fast prepending to list - # By specifying a maxlen, items get popped off on the other side - # of the deque as new items are added - trade_history = {pool.name: deque(maxlen=MAX_TRADE_HISTORY) for pool in hyperdrive_pools} - # Make trades until the user or agents stop us logging.info("Trading...") iteration = 0 + # Get block before start fuzzing + fuzz_start_block = chain.block_number() while True: if num_iterations is not None and iteration >= num_iterations: @@ -307,7 +361,6 @@ def run_fuzz_bots( for pool in hyperdrive_pools: logging.info("Trading on %s", pool.name) # Execute the agent policies - pool_trades: list[str] = [] for agent in agents: # If we're checking invariance, and we're doing the lp share test, # we need to get the pending pool state here before the trades. @@ -337,8 +390,6 @@ def run_fuzz_bots( # Otherwise, we ignore crashes, we want the bot to keep trading # These errors will get logged regardless - pool_trades.extend([trade.__name__ for trade in agent_trade]) - # Check invariance on every iteration if we're not doing lp_share_price_test. # Only check invariance if a trade was executed for lp_share_price_test. # This is because the lp_share_price_test requires a trade to be executed @@ -374,19 +425,8 @@ def run_fuzz_bots( # Otherwise, we raise a new fuzz assertion exception wht the list of exceptions raise FuzzAssertionException(*fuzz_exceptions) - trade_history[pool.name].appendleft(pool_trades) - - # Log trades - print_trades = {k: list(v) for k, v in trade_history.items()} - logging.info("Trade history: \n %s", json.dumps(print_trades, indent=2)) - - # Look for past trades and limit the size of the list - for pool_name, trades in trade_history.items(): - if len(trades) == MAX_TRADE_HISTORY: - num_trades = [len(t) for t in trades] - if sum(num_trades) == 0: - logging.warning("No trades found on %s for the past %s iterations", pool_name, MAX_TRADE_HISTORY) - # TODO log to rollbar + # Check trades on pools and log if no trades have been made on any of the pools + _check_trades_made_on_pool(chain, hyperdrive_pools, fuzz_start_block, iteration) # Check agent funds and refund if necessary assert len(agents) > 0 From de52dbbd89887b9b2378fdf3ea64743e7b62ee6e Mon Sep 17 00:00:00 2001 From: Sheng Lundquist Date: Tue, 29 Oct 2024 10:30:11 -0700 Subject: [PATCH 12/15] Logging error to rollbar --- .../hyperfuzz/system_fuzz/run_fuzz_bots.py | 45 ++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py index a39918c20e..43ad2ceb1f 100644 --- a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py +++ b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py @@ -20,7 +20,7 @@ from agent0.ethpy.base import set_anvil_account_balance from agent0.hyperfuzz import FuzzAssertionException from agent0.hyperfuzz.system_fuzz.invariant_checks import run_invariant_checks -from agent0.hyperlogs.rollbar_utilities import log_rollbar_exception +from agent0.hyperlogs.rollbar_utilities import log_rollbar_exception, log_rollbar_message ONE_HOUR_IN_SECONDS = 60 * 60 ONE_DAY_IN_SECONDS = ONE_HOUR_IN_SECONDS * 24 @@ -166,38 +166,43 @@ def _check_trades_made_on_pool( trade_counts = trade_counts.reset_index() # Omission of rows means no trades of that type went through for pool in hyperdrive_pools: + has_err = False + error_message = "" if pool.name not in trade_counts["hyperdrive_name"].values: - logging.error("Pool %s did not make any trades after %s iterations", pool.name, iteration) - # TODO log to rollbar + has_err = True + error_message = f"Pool {pool.name} did not make any trades after {iteration} iterations" else: pool_trade_event_counts = trade_counts[trade_counts["hyperdrive_name"] == pool.name][ "event_type" ].values if "OpenLong" not in pool_trade_event_counts: - logging.error( - "Pool %s did not make any OpenLong trades after %s iterations", - ) + has_err = True + error_message = f"Pool {pool.name} did not make any OpenLong trades after {iteration} iterations" if "OpenShort" not in pool_trade_event_counts: - logging.error( - "Pool %s did not make any OpenShort trades after %s iterations", - ) + has_err = True + error_message = f"Pool {pool.name} did not make any OpenShort trades after {iteration} iterations" if "CloseLong" not in pool_trade_event_counts: - logging.error( - "Pool %s did not make any CloseLong trades after %s iterations", - ) + has_err = True + error_message = f"Pool {pool.name} did not make any CloseLong trades after {iteration} iterations" if "CloseShort" not in pool_trade_event_counts: - logging.error( - "Pool %s did not make any CloseShort trades after %s iterations", - ) + has_err = True + error_message = f"Pool {pool.name} did not make any CloseShort trades after {iteration} iterations" if "AddLiquidity" not in pool_trade_event_counts: - logging.error( - "Pool %s did not make any AddLiquidity trades after %s iterations", + has_err = True + error_message = ( + f"Pool {pool.name} did not make any AddLiquidity trades after {iteration} iterations" ) if "RemoveLiquidity" not in pool_trade_event_counts: - logging.error( - "Pool %s did not make any RemoveLiquidity trades after %s iterations", + has_err = True + error_message = ( + f"Pool {pool.name} did not make any RemoveLiquidity trades after {iteration} iterations" ) + if has_err: + error_message = "FuzzBots: " + error_message + logging.error(error_message) + log_rollbar_message(error_message, logging.ERROR) + def run_fuzz_bots( chain: Chain, @@ -380,7 +385,7 @@ def run_fuzz_bots( # a contract call. # TODO this can result in duplicate entries of the same error log_rollbar_exception( - rollbar_log_prefix=f"Unexpected contract call error on pool {pool.name}", + rollbar_log_prefix=f"FuzzBots: Unexpected contract call error on pool {pool.name}", exception=exc, log_level=logging.ERROR, ) From 3663b2c37be617ec8894584c596811a75315d5d7 Mon Sep 17 00:00:00 2001 From: Sheng Lundquist Date: Tue, 29 Oct 2024 10:33:59 -0700 Subject: [PATCH 13/15] Adding prefix to exception logging --- scripts/fork_fuzz_bots.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/fork_fuzz_bots.py b/scripts/fork_fuzz_bots.py index 63c1b9da5b..6b73d0212c 100644 --- a/scripts/fork_fuzz_bots.py +++ b/scripts/fork_fuzz_bots.py @@ -281,7 +281,9 @@ def main(argv: Sequence[str] | None = None) -> None: num_iterations=parsed_args.num_iterations_per_episode, ) except Exception as e: # pylint: disable=broad-except - log_rollbar_exception(rollbar_log_prefix="Unexpected error", exception=e, log_level=logging.ERROR) + log_rollbar_exception( + rollbar_log_prefix="Fork FuzzBot: Unexpected error", exception=e, log_level=logging.ERROR + ) if parsed_args.pause_on_invariance_fail: logging.error( "Pausing pool (chain:%s port:%s) on crash %s", From cd71f21b13b2333cdea1510c198b664c1c7f3de7 Mon Sep 17 00:00:00 2001 From: Sheng Lundquist Date: Tue, 29 Oct 2024 10:36:24 -0700 Subject: [PATCH 14/15] Unused imports --- src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py index 43ad2ceb1f..cb740d5dc8 100644 --- a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py +++ b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py @@ -2,14 +2,11 @@ from __future__ import annotations -import json import logging -from collections import deque from typing import Callable, Sequence from eth_typing import ChecksumAddress from fixedpointmath import FixedPoint -from hyperdrivetypes import BaseEvent from numpy.random import Generator from pypechain.core import PypechainCallException From af8e33dde4c061ded8311c495cb467519104ca0b Mon Sep 17 00:00:00 2001 From: Sheng Lundquist Date: Tue, 29 Oct 2024 10:47:23 -0700 Subject: [PATCH 15/15] Increasing trade count periodic check --- src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py index cb740d5dc8..6c3c9e8f5f 100644 --- a/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py +++ b/src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py @@ -53,7 +53,7 @@ LP_SHARE_PRICE_GOVERNANCE_LP_FEE_RANGE: tuple[float, float] = (0, 0) LP_SHARE_PRICE_GOVERNANCE_ZOMBIE_FEE_RANGE: tuple[float, float] = (0, 0) -TRADE_COUNT_PERIODIC_CHECK = 50 +TRADE_COUNT_PERIODIC_CHECK = 100 # pylint: disable=too-many-locals