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

Fixing invariance checks for testnet #1632

Merged
merged 3 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ classifiers = [
dependencies = [
"dill",
"docker",
"eth-abi",
"eth-typing",
"eth-account",
"fixedpointmath",
Expand Down
32 changes: 32 additions & 0 deletions scripts/invariant_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,30 @@

from agent0 import Chain, Hyperdrive
from agent0.ethpy.hyperdrive import get_hyperdrive_registry_from_artifacts
from agent0.hyperfuzz import FuzzAssertionException
from agent0.hyperfuzz.system_fuzz.invariant_checks import run_invariant_checks
from agent0.hyperlogs.rollbar_utilities import initialize_rollbar, log_rollbar_exception, log_rollbar_message
from agent0.utils import async_runner

LOOKBACK_BLOCK_LIMIT = 1000


def _sepolia_ignore_errors(exc: Exception) -> bool:
# Ignored fuzz exceptions
if isinstance(exc, FuzzAssertionException):
# LP rate invariance check
if (
# Only ignore steth pools
"STETH" in exc.exception_data["pool_name"]
and len(exc.args) >= 2
and exc.args[0] == "Continuous Fuzz Bots Invariant Checks"
and "actual_vault_shares=" in exc.args[1]
and "is expected to be greater than expected_vault_shares=" in exc.args[1]
):
return True
return False


def main(argv: Sequence[str] | None = None) -> None:
"""Check Hyperdrive invariants each block.

Expand All @@ -41,6 +58,11 @@ def main(argv: Sequence[str] | None = None) -> None:

parsed_args = parse_arguments(argv)

if parsed_args.sepolia:
invariance_ignore_func = _sepolia_ignore_errors
else:
invariance_ignore_func = None

if parsed_args.infra:
# TODO Abstract this method out for infra scripts
# Get the rpc uri from env variable
Expand Down Expand Up @@ -113,6 +135,7 @@ def main(argv: Sequence[str] | None = None) -> None:
simulation_mode=False,
log_to_rollbar=log_to_rollbar,
rollbar_log_level_threshold=chain.config.rollbar_log_level_threshold,
rollbar_log_filter_func=invariance_ignore_func,
pool_name=hyperdrive_obj.name,
)
for hyperdrive_obj in deployed_pools
Expand All @@ -133,6 +156,7 @@ class Args(NamedTuple):
infra: bool
registry_addr: str
rpc_uri: str
sepolia: bool


def namespace_to_args(namespace: argparse.Namespace) -> Args:
Expand All @@ -153,6 +177,7 @@ def namespace_to_args(namespace: argparse.Namespace) -> Args:
infra=namespace.infra,
registry_addr=namespace.registry_addr,
rpc_uri=namespace.rpc_uri,
sepolia=namespace.sepolia,
)


Expand Down Expand Up @@ -199,6 +224,13 @@ def parse_arguments(argv: Sequence[str] | None = None) -> Args:
help="The RPC URI of the chain.",
)

parser.add_argument(
"--sepolia",
default=False,
action="store_true",
help="Running on Sepolia Testnet. If True, will ignore some known errors.",
)

# Use system arguments if none were passed
if argv is None:
argv = sys.argv
Expand Down
37 changes: 18 additions & 19 deletions src/agent0/ethpy/hyperdrive/interface/read_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from enum import Enum
from typing import TYPE_CHECKING, Any, cast

import eth_abi
from fixedpointmath import FixedPoint
from web3 import Web3
from web3.exceptions import BadFunctionCallOutput, ContractLogicError
Expand Down Expand Up @@ -96,12 +97,6 @@
pathlib.Path(__file__).parent.parent.parent.parent / "packages" / "external" / "IMorpho.sol" / "IMorpho.json"
).resolve()

# TODO morpho hyperdrive doesn't expose this
# MORPHO_LOAN_TOKEN_ADDR = "0x6B175474E89094C44Da98b954EedeAC495271d0F"
# TODO generate this id from the variables exposed by morpho hyperdrive contract
MORPHO_MARKET_PARAMS_ID = "0x39d11026eae1c6ec02aa4c0910778664089cdd97c3fd23f68f7cd05e2e95af48"


# We expect to have many instance attributes & public methods since this is a large API.
# pylint: disable=too-many-lines
# pylint: disable=too-many-instance-attributes
Expand Down Expand Up @@ -152,6 +147,7 @@ def __init__(
txn_signature: bytes | None, optional
The signature for transactions. Defaults to `0xa0`.
"""
# pylint: disable=too-many-locals
if txn_signature is None:
self.txn_signature = AGENT0_SIGNATURE
else:
Expand Down Expand Up @@ -231,19 +227,22 @@ def __init__(
self.morpho_contract = web3.eth.contract(
address=web3.to_checksum_address(morpho_contract_addr), abi=morpho_blue_abi["abi"]
)
# TODO ideally we would build the id, but something below is incorrect.
# We hard code for now.
# self.morpho_market_id = web3.solidity_keccak(
# abi_types=["address", "address", "address", "address", "uint256"],
# values=[
# MORPHO_LOAN_TOKEN_ADDR,
# morpho_hyperdrive_contract.functions.collateralToken().call(),
# morpho_hyperdrive_contract.functions.oracle().call(),
# morpho_hyperdrive_contract.functions.irm().call(),
# morpho_hyperdrive_contract.functions.lltv().call(),
# ],
# )
self.morpho_market_id = MORPHO_MARKET_PARAMS_ID

values = (
base_token_contract_address,
morpho_hyperdrive_contract.functions.collateralToken().call(),
morpho_hyperdrive_contract.functions.oracle().call(),
morpho_hyperdrive_contract.functions.irm().call(),
morpho_hyperdrive_contract.functions.lltv().call(),
)

# Typing is reporting `encode` is not exposed in `eth_abi`
encoded_market_id = eth_abi.encode( # type: ignore
("address", "address", "address", "address", "uint256"),
values,
)

self.morpho_market_id = web3.keccak(encoded_market_id)

else:
# We default to erc4626, but print a warning if we don't recognize the kind
Expand Down
3 changes: 3 additions & 0 deletions src/agent0/hyperfuzz/system_fuzz/invariant_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ def run_invariant_checks(
# pylint: disable=too-many-locals
# pylint: disable=too-many-arguments

logging.info("Running invariant checks on pool %s", pool_name)

if rollbar_log_level_threshold is None:
rollbar_log_level_threshold = logging.DEBUG

Expand Down Expand Up @@ -146,6 +148,7 @@ def run_invariant_checks(
exception_data = exception_data_template.copy()
exception_data.update(data)
exception_data["block_number"] = pool_state.block_number
exception_data["pool_name"] = pool_name

# Log exception to rollbar
assert log_level is not None
Expand Down
Loading