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

Minor fixes for aero pool #1725

Merged
merged 6 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions scripts/fork_fuzz_bots.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
# with the value as the whale address.
# Note that if a token is missing in this mapping, we will try to
# call `mint` on the trading token to fund.
# TODO we need a better method to ensure this list of whales doesn't get stale
MAINNET_WHALE_ADDRESSES = {
# stETH
"0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84": "0x7F39C581F595B53C5CB19BD0B3F8DA6C935E2CA0",
Expand Down Expand Up @@ -71,6 +72,8 @@
"0xe66E3A37C3274Ac24FE8590f7D84A2427194DC17": "0x5E564c1905fFF9724621542f58d61BE0405C4879",
# snARS
"0xC1F4C75e8925A67BE4F35D6b1c044B5ea8849a58": "0x54423d0A5c4e3a6Eb8Bd12FDD54c1e6b42D52Ebe",
# LP Token for Areo USD pool
"0x6cDcb1C4A4D1C3C6d054b27AC5B77e89eAFb971d": "0xD22B2890A6812414B544598fC77AC04382008754",
}

# We build an outer lookup based on chain id
Expand Down
10 changes: 8 additions & 2 deletions src/agent0/core/hyperdrive/interactive/hyperdrive_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import annotations

import asyncio
import logging
import threading
from functools import partial
from typing import TYPE_CHECKING, Literal, Type, overload
Expand Down Expand Up @@ -273,10 +274,15 @@ def add_funds(
else:
base_scaled_value = base.scaled_value

# If whale doesn't have enough balance, give it as much as possible
if whale_balance < base_scaled_value:
raise ValueError(
f"Whale does not have enough base to transfer. {whale_balance=}, {base_scaled_value=}."
logging.warning(
"Whale %s doesn't have enough base to transfer %s, only supplying %s base.",
whale_account_addr,
FixedPoint(scaled_value=base_scaled_value),
FixedPoint(scaled_value=whale_balance),
)
base_scaled_value = whale_balance

# RPC anvil call to impersonate account
response = self.chain._web3.provider.make_request(
Expand Down
56 changes: 31 additions & 25 deletions src/agent0/ethpy/hyperdrive/interface/_contract_calls.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from hyperdrivetypes.types.IHyperdrive import IHyperdriveContract, Options
from hyperdrivetypes.types.MockERC4626 import MockERC4626Contract
from hyperdrivetypes.types.MockLido import MockLidoContract
from packaging.version import Version
from pypechain.core import PypechainCallException
from web3 import Web3
from web3.exceptions import BadFunctionCallOutput, ContractLogicError
Expand Down Expand Up @@ -96,34 +97,39 @@ def _get_vault_shares(
) -> FixedPoint:
"""See API for documentation."""

# TODO call `hyperdrive_contract.functions.totalShares` instead of custom logic between pools
if interface.hyperdrive_kind == interface.HyperdriveKind.STETH:
# Type narrowing
assert interface.vault_shares_token_contract is not None
vault_shares = interface.vault_shares_token_contract.functions.sharesOf(hyperdrive_contract.address).call(
# `totalShares` is only available after hyperdrive version `1.0.17`
if Version(interface.hyperdrive_version) >= Version("1.0.17"):
vault_shares = interface.hyperdrive_contract.functions.totalShares().call(
block_identifier=block_identifier or "latest"
)
elif interface.hyperdrive_kind == interface.HyperdriveKind.MORPHO:
# Type narrowing
assert interface.morpho_contract is not None
assert interface.morpho_market_id is not None

# TODO pypechain requires bytes input (not HexBytes) for the position function call.
# Fix to allow for bytes input to be interchangeable.
morpho_market_id = bytes(interface.morpho_market_id)

# Get token balances
vault_shares = (
interface.morpho_contract.functions.position(morpho_market_id, hyperdrive_contract.address)
.call(block_identifier=block_identifier or "latest")
.supplyShares
)
else:
# Type narrowing
assert interface.vault_shares_token_contract is not None
vault_shares = interface.vault_shares_token_contract.functions.balanceOf(hyperdrive_contract.address).call(
block_identifier=block_identifier or "latest"
)
if interface.hyperdrive_kind == interface.HyperdriveKind.STETH:
# Type narrowing
assert interface.vault_shares_token_contract is not None
vault_shares = interface.vault_shares_token_contract.functions.sharesOf(hyperdrive_contract.address).call(
block_identifier=block_identifier or "latest"
)
elif interface.hyperdrive_kind == interface.HyperdriveKind.MORPHO:
# Type narrowing
assert interface.morpho_contract is not None
assert interface.morpho_market_id is not None

# TODO pypechain requires bytes input (not HexBytes) for the position function call.
# Fix to allow for bytes input to be interchangeable.
morpho_market_id = bytes(interface.morpho_market_id)

# Get token balances
vault_shares = (
interface.morpho_contract.functions.position(morpho_market_id, hyperdrive_contract.address)
.call(block_identifier=block_identifier or "latest")
.supplyShares
)
else:
# Type narrowing
assert interface.vault_shares_token_contract is not None
vault_shares = interface.vault_shares_token_contract.functions.balanceOf(hyperdrive_contract.address).call(
block_identifier=block_identifier or "latest"
)
return FixedPoint(scaled_value=vault_shares)


Expand Down
7 changes: 5 additions & 2 deletions src/agent0/ethpy/hyperdrive/interface/read_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,10 @@ def __init__(
# >= 1.0.17
if Version(self.hyperdrive_version) < Version("1.0.17"):
self.txn_signature = bytes(0)

elif vault_shares_token_address == ADDRESS_ZERO:
# Some contracts don't have a vault shares token contract. We set the contract to None
# in this case.
self.vault_shares_token_contract = None
else:
# TODO Although the underlying function might not be a MockERC4626Contract,
# the pypechain contract factory happily accepts any address and exposes
Expand Down Expand Up @@ -584,7 +587,7 @@ def get_variable_rate(self, block_identifier: BlockIdentifier | None = None) ->
if block_identifier is None:
block_identifier = "latest"
if self.vault_shares_token_contract is None:
raise ValueError("Vault shares token contract is not set")
return None
return _get_variable_rate(self.vault_shares_token_contract, block_identifier)

def get_standardized_variable_rate(self, time_range: int = 604800) -> FixedPoint:
Expand Down
36 changes: 15 additions & 21 deletions src/agent0/hyperfuzz/system_fuzz/run_fuzz_bots.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from agent0.ethpy.hyperdrive import HyperdriveReadWriteInterface
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
Expand Down Expand Up @@ -55,7 +55,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 = 100
TRADE_COUNT_CHECK = 100


# pylint: disable=too-many-locals
Expand Down Expand Up @@ -159,9 +159,8 @@ def _check_trades_made_on_pool(

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:
# After some iterations, we expect all pools to make at least one trade
if iteration == TRADE_COUNT_CHECK:
trade_counts = trade_counts.reset_index()
# Omission of rows means no trades of that type went through
for pool in hyperdrive_pools:
Expand Down Expand Up @@ -208,9 +207,10 @@ def _check_trades_made_on_pool(
)

if has_err:
error_message = "FuzzBots: " + error_message
logging.error(error_message)
# We log message to get rollbar to group these messages together
log_rollbar_exception(ValueError(error_message), logging.ERROR, rollbar_log_prefix="FuzzBots:")
log_rollbar_message(error_message, logging.ERROR)


def run_fuzz_bots(
Expand Down Expand Up @@ -489,21 +489,15 @@ def run_fuzz_bots(
logging.info("Refunding agents...")
if run_async:
raise NotImplementedError("Running async not implemented")
try:
_ = [
agent.add_funds(
base=base_budget_per_bot,
eth=eth_budget_per_bot,
pool=hyperdrive_pool,
whale_accounts=whale_accounts,
)
for agent in agents
]
except ValueError as e:
# Look for the case when the whale doesn't have enough base to transfer, and
# ignore when refunding.
if "Whale does not have enough base to transfer." not in e.args[0]:
raise e
_ = [
agent.add_funds(
base=base_budget_per_bot,
eth=eth_budget_per_bot,
pool=hyperdrive_pool,
whale_accounts=whale_accounts,
)
for agent in agents
]

if random_advance_time:
# We only allow random advance time if the chain connected to the pool is a
Expand Down
Loading