VaultReaderState

Documentation for eth_defi.erc_4626.vault.VaultReaderState Python class.

class VaultReaderState

Bases: eth_defi.event_reader.multicall_batcher.BatchCallState

Adaptive reading frequency for vaults.

  • This class maintains the per-vault state of reading between different eth_call reads over time

  • Most vaults are uninteresting, but we do not know ahead of time which ones

  • We need 1h data for interesting vaults to make good trade decisions

  • We switch to 1h scanning if the TVL is above a threshold, otherwise we read it once per day

Note

Due to filtering, only handles stablecoin vaults correctly at the moment. Lacks exchange rate support.

Parameters
  • vault – The vault we are reading historical data for

  • tvl_threshold_1d_read – If the TVL is below this threshold, we will not read it more than once per day, otherwise hourly.

  • down_hard – Stop reading the vault if the TVL is down by this percentage from the peak.

  • min_tvl_threshold – If the vault never reaches this TVL, we stop reading it after the traction period.

  • traction_period – How long we wait for the vault to get traction before we stop reading it.

Parm peaked_tvl_threshold

The TVL value we first need to reach to trigger down hard condition.

Attributes summary

SERIALISABLE_ATTRIBUTES

All attributes we store when we serialise the read state between runs

exchange_rate

Get the exchange rate for TVL estimation

first_seen_at_block

Passed from the vault discovery reader, pass the block number as args when we know this vault popped in to the existing

last_tvl

TVL from the last read

first_read_at

Timestamp of the block of the first successful read of this vault.

max_tvl

Start with zero TVL

last_share_price

Start with zero share price

last_call_at

When this vault received its last eth_call update

last_block

When this vault received its last eth_call update

peaked_at

Disable reading if the vault has peaked (TVL too much down) and is no longer active

peaked_tvl

What was TVL when we disabled reading due to peaking

faded_at

Disable reading if the vault has never gotten any traction

traction_period

How much time after deployment we allow to get traction

min_tvl_threshold

Minimum TVL traction threshold to start reading the vault

tiny_tvl_threshold_rare_read

Vaults we do no really care about

entry_count

How many on_called() invocations have we had

invoke_count_passed

How many should_invoke() invocations have we had

invoke_count_first_read

How many should_invoke() invocations have we had

invoke_count_missing_freq

How many should_invoke() invocations have we had

invoke_count_throttled

How many should_invoke() invocations have we had

rpc_error_count

Track RPCc errors

denomination_token_address

Cache denomination token address when preparing readers

share_token_address

Cache share token address when preparing readers

one_raw_share

One share in its raw units

one

Cache denomination token address when preparing readers

chain_id

Copy for state debuggin

vault_poll_frequency

Cache for how often we are polling this vault, the mode name

token_symbol

Cache for debuggin

unsupported_token

Cache for debuggin

call_status

Map of function names to their call status for warmup system Key is the function name from extra_data["function"] Value is tuple (check_block: int, reverts: bool) Example: {"maxDeposit": (12345678, True)} means maxDeposit reverts, detected at block 12345678

Methods summary

__init__(vault[, tvl_threshold_1d_read, ...])

param vault

get_broken_calls()

Get all calls marked as broken.

get_call_status(function_name)

Get the status of a function call.

get_frequency()

How fast we are reading this vault or should the further reading be skipped.

load(data)

Load the state from a dictionary.

on_called(result[, total_assets, share_price])

param result

on_unpriced_call(result)

Update adaptive scan state for a successful supply-only read.

pformat()

Pretty print the current state.

save()

Persist state across multiple runs.

set_call_status(function_name, check_block, ...)

Record the status of a function call.

should_invoke(call, block_identifier, timestamp)

Check the condition if this multicall is good to go.

should_skip_call(function_name)

Check if a specific function call should be skipped for this vault.

SERIALISABLE_ATTRIBUTES = ('last_tvl', 'last_share_price', 'max_tvl', 'first_seen_at_block', 'first_block', 'first_read_at', 'last_call_at', 'last_block', 'peaked_at', 'peaked_tvl', 'faded_at', 'entry_count', 'chain_id', 'vault_address', 'denomination_token_address', 'share_token_address', 'one_raw_share', 'reading_restarted_count', 'vault_poll_frequency', 'token_symbol', 'unsupported_token', 'invoke_count_passed', 'invoke_count_first_read', 'invoke_count_missing_freq', 'invoke_count_throttled', 'write_filtered', 'write_done', 'rpc_error_count', 'last_rpc_error', 'call_status')

All attributes we store when we serialise the read state between runs

__init__(vault, tvl_threshold_1d_read=Decimal('10000'), tiny_tvl_threshold_rare_read=Decimal('1000'), peaked_tvl_threshold=Decimal('200000'), min_tvl_threshold=Decimal('1500'), down_hard=0.98, traction_period=datetime.timedelta(days=60))
Parameters
  • vault (eth_defi.erc_4626.vault.ERC4626Vault) – The vault we are reading historical data for

  • tvl_threshold_1d_read – If the TVL is below this threshold, we will not read it more than once per day, otherwise hourly.

  • down_hard – Stop reading the vault if the TVL is down by this percentage from the peak.

  • min_tvl_threshold – If the vault never reaches this TVL, we stop reading it after the traction period.

  • traction_period (datetime.timedelta) – How long we wait for the vault to get traction before we stop reading it.

Parm peaked_tvl_threshold

The TVL value we first need to reach to trigger down hard condition.

first_seen_at_block

Passed from the vault discovery reader, pass the block number as args when we know this vault popped in to the existing

last_tvl: decimal.Decimal

TVL from the last read

first_read_at: datetime.datetime

Timestamp of the block of the first successful read of this vault.

max_tvl: decimal.Decimal

Start with zero TVL

last_share_price: decimal.Decimal

Start with zero share price

last_call_at: Optional[datetime.datetime]

When this vault received its last eth_call update

last_block: Optional[int]

When this vault received its last eth_call update

peaked_at: datetime.datetime

Disable reading if the vault has peaked (TVL too much down) and is no longer active

peaked_tvl: float

What was TVL when we disabled reading due to peaking

faded_at: datetime.datetime

Disable reading if the vault has never gotten any traction

traction_period

How much time after deployment we allow to get traction

min_tvl_threshold

Minimum TVL traction threshold to start reading the vault

tiny_tvl_threshold_rare_read

Vaults we do no really care about

entry_count

How many on_called() invocations have we had

invoke_count_passed

How many should_invoke() invocations have we had

invoke_count_first_read

How many should_invoke() invocations have we had

invoke_count_missing_freq

How many should_invoke() invocations have we had

invoke_count_throttled

How many should_invoke() invocations have we had

rpc_error_count

Track RPCc errors

denomination_token_address

Cache denomination token address when preparing readers

share_token_address

Cache share token address when preparing readers

one_raw_share

One share in its raw units

one

Cache denomination token address when preparing readers

chain_id

Copy for state debuggin

vault_poll_frequency

Cache for how often we are polling this vault, the mode name

token_symbol

Cache for debuggin

unsupported_token

Cache for debuggin

call_status: dict[str, tuple[int, bool]]

Map of function names to their call status for warmup system Key is the function name from extra_data[“function”] Value is tuple (check_block: int, reverts: bool) Example: {“maxDeposit”: (12345678, True)} means maxDeposit reverts, detected at block 12345678

save()

Persist state across multiple runs.

Returns

Pickleable Python object

Return type

dict

load(data)

Load the state from a dictionary.

Parameters

data (dict) –

should_skip_call(function_name)

Check if a specific function call should be skipped for this vault.

Part of the warmup system to detect and skip broken contract calls. See README-reader-states.md for documentation.

Parameters

function_name (str) – The function name as stored in extra_data[“function”]

Returns

True if the call was marked as reverting

Return type

bool

get_call_status(function_name)

Get the status of a function call.

Parameters

function_name (str) – The function name to check

Returns

Tuple of (check_block, reverts) or None if not checked yet

Return type

Optional[tuple[int, bool]]

set_call_status(function_name, check_block, reverts)

Record the status of a function call.

Parameters
  • function_name (str) – The function name to record

  • check_block (int) – The block number when we checked

  • reverts (bool) – True if the call reverted

Return type

None

get_broken_calls()

Get all calls marked as broken.

Returns

Dict of function_name -> check_block for broken calls

Return type

dict[str, int]

property exchange_rate: decimal.Decimal

Get the exchange rate for TVL estimation

should_invoke(call, block_identifier, timestamp)

Check the condition if this multicall is good to go.

Parameters
Return type

bool

get_frequency()

How fast we are reading this vault or should the further reading be skipped.

Return type

tuple[Literal[‘peaked’, ‘faded’, ‘large_tvl’, ‘small_tvl’, ‘tiny_tvl’, ‘first_read’, ‘not_started’, ‘early’], datetime.timedelta | None]

on_called(result, total_assets=None, share_price=None)
Parameters
on_unpriced_call(result)

Update adaptive scan state for a successful supply-only read.

Some tokenised funds expose their share supply but no reviewed scalar NAV or TVL. They still need persistent reader state so the stateful scanner can cache token metadata, advance its last-read block and throttle historical calls. Zero values are internal scheduling sentinels only; the exported historical row must continue to expose None for its share price and total assets.

Parameters

result (eth_defi.event_reader.multicall_batcher.EncodedCallResult) – Successful supply call carrying a block number and timestamp.

Return type

None

pformat()

Pretty print the current state.

Return type

str