erc_4626.classification
Documentation for eth_defi.erc_4626.classification Python module.
ERC-4626 vault type classification.
Used in vault discovery to figure out what kind of vaults we have autodetected
Use multicall based apporach to probe contracts
Module Attributes
Chain restrictions for protocols deployed on 3 or fewer chains. |
|
Handle problematic protocols. |
Functions
|
Create calls that call each vault address using multicall. |
|
Create a new vault instance class based on the detected features. |
|
Create any vault instance. |
|
Detect the ERC-4626 features of a vault smart contract. |
|
Based on multicall results, create the feature flags for the vault.. |
|
Perform multicalls against each vault address to extract the features of the vault smart contract. |
Classes
Results of a multicall probing to a vault address. |
- CHAIN_RESTRICTED_PROBES: dict[str, set[int]] = {'POOL': {999}, 'SAY_TRADER_ROLE': {42161}, 'agent': {}, 'aggregateVault': {42161}, 'borrowed_token': {1, 10, 42161}, 'bridgedSupply': {42161}, 'claimableKeeper': {137, 42161}, 'depositController': {1, 56, 42161}, 'getPerformanceFeeData': {1, 8453, 42161}, 'marketManager': {143}, 'outputToLp0Route': {}, 'poolId': {1, 8453, 42161}, 'previewRateAfterDeposit': {1, 42161, 80094}, 'queue': {143}, 'registry': {42161}, 'repoTokenHoldings': {1, 9745, 43114}, 'routerRegistry': {8453}, 'strategist': {5000}, 'strategy': {143}, 'validateComponentRatios': {42161}, 'vaultManager': {5000}, 'wards': {1, 8453, 42161}}
Chain restrictions for protocols deployed on 3 or fewer chains.
Maps probe function names to the set of chain IDs where that protocol is deployed. Probes for these protocols will be skipped on chains not in their set.
Data source: https://top-defi-vaults.tradingstrategy.ai/top_vaults_by_chain.json Data checked: 2026-01-13
- class VaultFeatureProbe
Bases:
objectResults of a multicall probing to a vault address.
Method generated by attrs for class VaultFeatureProbe.
- __init__(address, features)
Method generated by attrs for class VaultFeatureProbe.
- Parameters
address (eth_typing.evm.HexAddress) –
features (set[eth_defi.erc_4626.core.ERC4626Feature]) –
- Return type
None
- create_probe_calls(addresses, share_probe_amount=1000000, chain_id=None)
Create calls that call each vault address using multicall.
Because ERC standards are such a shit show, and nobody is using good interface standard, we figure out the vault type by probing it with various calls
Skips protocol-specific probes for protocols only deployed on certain chains (see
CHAIN_RESTRICTED_PROBESfor the list)
- Parameters
addresses (collections.abc.Iterable[eth_typing.evm.HexAddress]) – Iterable of vault contract addresses to probe.
share_probe_amount – Amount used for convertToShares() probe call.
chain_id (int | None) – If provided, filters out probe calls for protocols that are not deployed on this chain. This reduces unnecessary RPC calls when scanning chains where certain protocols don’t exist. Protocols deployed on 3 or fewer chains have their probes skipped on other chains. If None, all probes are generated (no filtering).
- Return type
collections.abc.Iterable[eth_defi.event_reader.multicall_batcher.EncodedCall]
- identify_vault_features(address, calls, debug_text)
Based on multicall results, create the feature flags for the vault..
- Parameters
calls (dict[str, eth_defi.event_reader.multicall_batcher.EncodedCallResult]) – Call name -> result
address (eth_typing.evm.HexAddress) –
debug_text (str | None) –
- Return type
- probe_vaults(chain_id, web3factory, addresses, block_identifier, max_workers=8, progress_bar_desc=None)
Perform multicalls against each vault address to extract the features of the vault smart contract.
- Returns
Iterator of what vault smart contract features we detected for each potential vault address
- Parameters
chain_id (int) –
web3factory (eth_defi.event_reader.web3factory.Web3Factory) –
addresses (list[eth_typing.evm.HexAddress]) –
block_identifier (Union[Literal['latest', 'earliest', 'pending', 'safe', 'finalized'], eth_typing.evm.BlockNumber, eth_typing.evm.Hash32, eth_typing.encoding.HexStr, hexbytes.main.HexBytes, int]) –
progress_bar_desc (str | None) –
- Return type
collections.abc.Iterable[eth_defi.erc_4626.classification.VaultFeatureProbe]
- detect_vault_features(web3, address, verbose=True)
Detect the ERC-4626 features of a vault smart contract.
Protocols: Harvest, Lagoon, etc.
Does support ERC-7540
Very slow, only use in scripts and tutorials.
Use to pass to
create_vault_instance()to get a correct Python proxy class for the vault institated.
Example:
features = detect_vault_features(web3, spec.vault_address, verbose=False) logger.info("Detected vault features: %s", features) vault = create_vault_instance( web3, spec.vault_address, features=features, )
- Parameters
verbose – Disable for command line scripts
web3 (web3.main.Web3) –
address (Union[eth_typing.evm.HexAddress, str]) –
- Return type
- create_vault_instance(web3, address, features=None, token_cache=None, auto_detect=False)
Create a new vault instance class based on the detected features.
Get a protocol-specific Python instance that can e.g. read the fees of the vault (not standardised).
See also -
detect_vault_features()to determine features for a vault address- Parameters
features (set[eth_defi.erc_4626.core.ERC4626Feature] | None) –
Previously/manually extracted vault feature flags for the type.
Give empty set for generic ERC-4626 vault class.
auto_detect (bool) –
Auto-detect the vault protocol.
Very slow, do not use except in tutorials and scripts. Prefer to manually pass
feature.web3 (web3.main.Web3) –
address (Union[eth_typing.evm.HexAddress, str]) –
token_cache (dict | None) –
- Returns
None if the vault creation is not supported
- Return type
- create_vault_instance_autodetect(web3, vault_address, token_cache=None)
Create any vault instance.
Probes smart contract call first to identify what kind of vault we are dealing with
- Parameters
web3 (web3.main.Web3) –
vault_address (Union[eth_typing.evm.HexAddress, str]) –
token_cache (dict | None) –
- Return type
- HARDCODED_PROTOCOLS = {'0x0000000f2eb9f69274678c76222b35eec7588a65': {ERC4626Feature.yo_like}, '0x01ba69727e2860b37bc1a2bd56999c1afb4c15d8': {ERC4626Feature.yieldnest_like}, '0x06a491e3efee37eb191d0434f54be6e42509f9d3': {ERC4626Feature.spectra_usdn_wrapper_like}, '0x06d47f3fb376649c3a9dafe069b3d6e35572219e': {ERC4626Feature.avant_like}, '0x06fd9d03b3d0f18e4919919b72d30c582f0a97e5': {ERC4626Feature.hyperlend_like}, '0x0ff79b6d6c0fb5faf54bd26db5ce97062a105f81': {ERC4626Feature.renalta_like}, '0x1202f5c7b4b9e47a1a484e8b270be34dbbc75055': {ERC4626Feature.resolv_like}, '0x19ebd191f7a24ece672ba13a302212b5ef7f35cb': {ERC4626Feature.yieldfi_like}, '0x1ce7d9942ff78c328a4181b9f3826fee6d845a97': {ERC4626Feature.yieldfi_like}, '0x28b3a8fb53b741a8fd78c0fb9a6b2393d896a43d': {ERC4626Feature.spark_like}, '0x28e60b466a075cecef930d29f7f1b0facf48f950': {ERC4626Feature.spectra_erc4626_wrapper_like}, '0x2e3c5e514eef46727de1fe44618027a9b70d92fc': {ERC4626Feature.yieldfi_like}, '0x356b8d89c1e1239cbbb9de4815c39a1474d5ba7d': {ERC4626Feature.maple_like}, '0x3a0a97dca5e6cacc258490d5ece453412f8e1883': {ERC4626Feature.liquidity_royalty_like}, '0x3ccff8c929b497c1ff96592b8ff592b45963e732': {ERC4626Feature.foxify_like}, '0x3ed6aa32c930253fc990de58ff882b9186cd0072': {ERC4626Feature.cap_like}, '0x438982ea288763370946625fd76c2508ee1fb229': {ERC4626Feature.csigma_like}, '0x444868b6e8079ac2c55eea115250f92c2b2c4d14': {ERC4626Feature.dolomite_like}, '0x4772d2e014f9fc3a820c444e3313968e9a5c8121': {ERC4626Feature.yieldfi_like}, '0x50d59b785df23728d9948804f8ca3543237a1495': {ERC4626Feature.csigma_like}, '0x7788a3538c5fc7f9c7c8a74eac4c898fc8d87d92': {ERC4626Feature.usdx_money_like}, '0x7d7f72d393f242da6e22d3b970491c06742984ff': {ERC4626Feature.cap_like}, '0x80128dbb9f07b93dde62a6daeadb69ed14a7d354': {ERC4626Feature.spark_like}, '0x80ac24aa929eaf5013f6436cda2a7ba190f5cc0b': {ERC4626Feature.maple_like}, '0x83f20f44975d03b1b09e64809b757c47f942beea': {ERC4626Feature.sky_like}, '0x887d57a509070a0843c6418eb5cffc090dcbbe95': {<ERC4626Feature.royco_like: 'royco_like'>, <ERC4626Feature.zerolend_like: 'zerolend_like'>}, '0x890a5122aa1da30fec4286de7904ff808f0bd74a': {ERC4626Feature.mainstreet_like}, '0x8ba9da757d1d66c58b1ae7e2ed6c04087348a82d': {ERC4626Feature.usdd_like}, '0x99cd4ec3f88a45940936f469e4bb72a2a701eeb9': {ERC4626Feature.sky_like}, '0x9d39a5de30e57443bff2a8307a4256c8797a3497': {ERC4626Feature.ethena_like}, '0xa3931d71877c0e7a3148cb7eb4463524fec27fbd': {ERC4626Feature.sky_like}, '0xa7a31e6a81300120b7c4488ec3126bc1ad11f320': {ERC4626Feature.deltr_like}, '0xb250c9e0f7be4cff13f94374c993ac445a1385fe': {ERC4626Feature.eth_strategy_like}, '0xb9c1344105faa4681bc7ffd68c5c526da61f2ae8': {ERC4626Feature.aarna_like}, '0xbc65ad17c5c0a2a4d159fa5a503f4992c7b545fe': {ERC4626Feature.spark_like}, '0xc5d6a7b61d18afa11435a889557b068bb9f29930': {ERC4626Feature.usdd_like}, '0xc7990369da608c2f4903715e3bd22f2970536c29': {ERC4626Feature.mainstreet_like}, '0xc9f01b5c6048b064e6d925d1c2d7206d4feef8a3': {ERC4626Feature.yearn_tokenised_strategy}, '0xd0ee0cf300dfb598270cd7f4d0c6e0d8f6e13f29': {ERC4626Feature.altura_like}, '0xd5d097f278a735d0a3c609deee71234cac14b47e': {ERC4626Feature.csigma_like}, '0xdbdc1ef57537e34680b898e1febd3d68c7389bcb': {ERC4626Feature.infinifi_like}, '0xe2e7a17dff93280dec073c995595155283e3c372': {ERC4626Feature.spark_like}, '0xe9d33286f0e37f517b1204aa6da085564414996d': {ERC4626Feature.maple_aqru_like}, '0xebfc8c2fe73c431ef2a371aea9132110aab50dca': {ERC4626Feature.yuzu_money_like}, '0xee847a804b67f4887c9e8fe559a2da4278defb52': {ERC4626Feature.frax_like}, '0xf2d2d55daf93b0660297eaa10969ebe90ead5ce8': {ERC4626Feature.dolomite_like}, '0xf4f447e6afa04c9d11ef0e2fc0d7f19c24ee55de': {ERC4626Feature.yieldfi_like}, '0xf94f97677914d298844ec8fa590fab09ccc324d0': {ERC4626Feature.usdd_like}}
Handle problematic protocols.
Some protocols cannot be detected by their vault smart contract structure, because they are using copy-paste smart contracts. For these, we need to do by vault contract address whitelisting here.