Skip to content

Commit

Permalink
adds descriptions to each of the fuzz tests (#1233)
Browse files Browse the repository at this point in the history
  • Loading branch information
dpaiton authored Jan 9, 2024
1 parent 385b6e1 commit f2b2b09
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 24 deletions.
19 changes: 17 additions & 2 deletions lib/agent0/agent0/interactive_fuzz/fuzz_hyperdrive_balance.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
"""Fuzz test to verify that if all of the funds are removed from Hyperdrive, there is no base left in the contract."""
"""Fuzz test to verify that the Hyperdrive share reserves are valid after trades are opened and then closed.
# Test procedure
- spin up local chain, deploy hyperdrive
- get initial_pool_state
- generate a list of random trades
- type in [open_short, open_long]
- amount in uniform[min_trade_amount, 100k) base
- open those trades in a random order & advance time randomly between
- total time advanced in uniform[0, position_duration)
- close the trades in a random order
- invariance checks
# Invariance checks (these should be True):
- current effective share reserves calculated from hyperdrivepy == initial share reserves
- share resserves >= minimum share reserves
"""
from __future__ import annotations

import argparse
Expand Down Expand Up @@ -197,7 +213,6 @@ def invariant_check(
exception_data["invariance_check:share_reserves"] = share_reserves
exception_data["invariance_check:minimum_share_reserves"] = minimum_share_reserves
exception_data["invariance_check:share_reserves_difference_in_wei"] = difference_in_wei

failed = True

if failed:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
"""Script to verify that longs and shorts which are closed at maturity supply the correct amounts."""
"""Script to verify that longs and shorts which are closed at maturity supply the correct amounts.
# Test procedure
- spin up local chain, deploy hyperdrive
- advance time to ensure we are in the middle of a checkpoint
- generate a list of random trades
- type in [open_short, open_long]
- amount in uniform[min_trade_amount, 100k) base
- open those trades in a random order, but within the same checkpoint
- advance time past the position duration, into a new checkpoint
- close the trades one at a time, run invariance checks after each close action
# Invariance checks (these should be True):
if trade was open and close a long:
- base out == bonds in minus flat fee
if trade was open and close a short:
- base out == interest accrued
"""
from __future__ import annotations

import argparse
Expand Down Expand Up @@ -242,7 +259,6 @@ def invariant_check(
# 0.05 would be a 5% fee.
flat_fee_percent = interactive_hyperdrive.hyperdrive_interface.pool_config.fees.flat

# assert with trade values
# base out should be equal to bonds in minus the flat fee.
actual_base_amount = close_trade_event.base_amount
expected_base_amount_from_event = (
Expand All @@ -260,6 +276,7 @@ def invariant_check(
exception_data["invariance_check:base_amount_from_event_difference_in_wei"] = difference_in_wei
failed = True

# assert with trade values
expected_base_amount_from_trade = open_trade_event.bond_amount - open_trade_event.bond_amount * flat_fee_percent
if actual_base_amount != expected_base_amount_from_trade:
difference_in_wei = abs(actual_base_amount.scaled_value - expected_base_amount_from_trade.scaled_value)
Expand Down
28 changes: 27 additions & 1 deletion lib/agent0/agent0/interactive_fuzz/fuzz_path_independence.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,30 @@
"""Script to verify that the state of pool reserves is invariant to the order in which positions are closed."""
"""Script to verify that the state of pool reserves is invariant to the order in which positions are closed.
# Test procedure
- spin up local chain, deploy hyperdrive
- generate a list of random trades
- type in [open_short, open_long]
- amount in uniform[min_trade_amount, 100k base)
- open those trades in a random order & advance time randomly between
- time advance in uniform[0, position_duration)
- save a snapshot of the current chain state
- repeat N times (where N is set as a command-line arg):
- load chain state (trades are opened, none are closed)
- close the trades in a random order
- invariance checks
# Invariance checks (these should be True):
# We are checking that the pool ends up in the same sate regardless of close transaction order
- the following state values should equal in all checks:
- effective share reserves
- shorts outstanding
- withdrawal shares proceeds
- share price
- long exposure
- bond reserves
- lp total supply
- longs outstanding
"""
from __future__ import annotations

import argparse
Expand Down
20 changes: 19 additions & 1 deletion lib/agent0/agent0/interactive_fuzz/fuzz_profit_check.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
"""Script for fuzzing profit values on immediately opening & closing a long or short."""
"""Script for fuzzing profit values on immediately opening & closing a long or short.
# Test procedure
- spin up local chain, deploy hyperdrive
- open a long for a random amount
- advance time, but not enough to trigger a new checkpoint
- close the long
- open a short for a random amount
- advance time, but not enough to trigger a new checkpoint
- close the short
- invariance checks
# Invariance checks (these should be True):
# We are checking that the agent made made no profit
- Repeat these two checks for the longs & shorts
- transaction receipt: base amount returned < base amount provided
- agent wallet: agent's wallet balance < trade amount
"""
from __future__ import annotations

import argparse
Expand Down
44 changes: 28 additions & 16 deletions lib/agent0/bin/fuzz_bot_invariant_checks.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
"""Script for checking Hyperdrive invariants at each block."""
"""Script for checking Hyperdrive invariants at each block.
This script assumes that fuzz_bots is running in a concurrent process.
Given that, we will periodically run this test:
# Invariance checks (these should be True):
- hyperdrive base & eth balances are zero
- the expected total shares equals the hyperdrive balance in the vault contract
- the pool has more than the minimum share reserves
- the system is solvent, i.e. (share reserves - long exposure in shares - min share reserves) > 0
- if a hyperdrive trade happened then a checkpoint was created at the appropriate time
"""
from __future__ import annotations

import argparse
Expand Down Expand Up @@ -165,21 +177,6 @@ def run_invariant_checks(
exception_data["invariance_check:vault_shares_difference_in_wei"] = difference_in_wei
failed = True

# The system should always be solvent
solvency = (
pool_state.pool_info.share_reserves
- pool_state.pool_info.long_exposure
- pool_state.pool_config.minimum_share_reserves
)
if not solvency > FixedPoint(0):
exception_message.append(
f"{solvency=} <= 0. "
f"({pool_state.pool_info.share_reserves=} - {pool_state.pool_info.long_exposure=} - "
f"{pool_state.pool_config.minimum_share_reserves=}). Test failed at block {latest_block_number}."
)
exception_data["invariance_check:solvency"] = solvency
failed = True

# The pool has more than the minimum share reserves
current_share_reserves = pool_state.pool_info.share_reserves
minimum_share_reserves = pool_state.pool_config.minimum_share_reserves
Expand All @@ -195,6 +192,21 @@ def run_invariant_checks(
exception_data["invariance_check:minimum_share_reserves"] = minimum_share_reserves
failed = True

# The system should always be solvent
solvency = (
pool_state.pool_info.share_reserves
- pool_state.pool_info.long_exposure / pool_state.pool_info.share_price
- pool_state.pool_config.minimum_share_reserves
)
if not solvency > FixedPoint(0):
exception_message.append(
f"{solvency=} <= 0. "
f"({pool_state.pool_info.share_reserves=} - {pool_state.pool_info.long_exposure=} - "
f"{pool_state.pool_config.minimum_share_reserves=}). Test failed at block {latest_block_number}."
)
exception_data["invariance_check:solvency"] = solvency
failed = True

# Creating a checkpoint should never fail
# TODO: add get_block_transactions() to interface
# NOTE: This wold be prone to false positives.
Expand Down
4 changes: 2 additions & 2 deletions lib/ethpy/ethpy/hyperdrive/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,8 @@ def _deploy_hyperdrive_factory(
def _mint_and_approve(
web3,
funding_account,
funding_contract: Contract,
contract_to_approve: Contract,
funding_contract: ERC20MintableContract,
contract_to_approve: HyperdriveFactoryContract,
mint_amount: FixedPoint,
) -> tuple[TxReceipt, TxReceipt]:
"""Mint tokens from the funding_contract and approve spending with the contract_to_approve
Expand Down

0 comments on commit f2b2b09

Please sign in to comment.