erc_4626.vault_protocol.bulla.vault

Documentation for eth_defi.erc_4626.vault_protocol.bulla.vault Python module.

Bulla Network invoice-factoring vault support.

Bulla Factoring pools stablecoin liquidity to finance invoices and direct loan offers. The protocol uses Bulla Claim v2 receivables and BullaFrendLend v2.

Pool participation is permissioned. Deposit, redemption and factoring rights are separately configured by the pool, and redemptions can be queued when liquidity is unavailable. Therefore this read adapter deliberately does not certify the generic public deposit manager.

Module Attributes

BULLA_BLOCKED_FLOW_REASON

Public transaction flows need a pool-specific permission and redemption-queue adapter.

BULLA_BASIS_POINT_DENOMINATOR

Bulla stores percentage values in basis points, e.g.

BULLA_ABI_WORD_BYTES

Every view used below returns one ABI word, except the mapping getter.

Classes

BullaFeeData

Bulla Factoring pool fees in the protocol's native representation.

BullaInvoiceFeeData

Bulla's per-invoice fee terms, including the underwriter spread.

BullaVault

Read a Bulla Network Factoring vault.

BULLA_BLOCKED_FLOW_REASON = 'Bulla Network deposit manager is blocked: permissioned deposits and queued redemptions are not implemented'

Public transaction flows need a pool-specific permission and redemption-queue adapter.

BULLA_BASIS_POINT_DENOMINATOR = 10000

Bulla stores percentage values in basis points, e.g. 30 means 0.30%.

Source: the verified BullaFactoringV2_1 contract on Arbiscan.

BULLA_ABI_WORD_BYTES = 32

Every view used below returns one ABI word, except the mapping getter.

Keeping this explicit makes the selector-only reader fail closed if a deployment returns malformed data instead of a Solidity uint value.

class BullaFeeData

Bases: object

Bulla Factoring pool fees in the protocol’s native representation.

Bulla has two pool-wide fee rates and two corresponding accrued token balances. The protocol rate is withheld when an invoice is funded, while the administrator rate is time-prorated as part of the invoice fee calculation. The public source explains that calculation in FeeCalculations.sol.

The underwriter’s spreadBps deliberately does not appear here: it is selected per approved invoice, rather than configured as a pool-wide getter. Use BullaInvoiceFeeData for that native invoice record. Likewise, target_yield_bps is an investment return target, not a fee. It is retained so applications cannot confuse it with the administrator or underwriter charge.

block_identifier: Union[Literal['latest', 'earliest', 'pending', 'safe', 'finalized'], eth_typing.evm.BlockNumber, eth_typing.evm.Hash32, eth_typing.encoding.HexStr, int]

Block at which every value in this snapshot was read.

protocol_fee_bps: int

Protocol fee rate in basis points from protocolFeeBps().

The contract takes this amount off the top when it funds an invoice and earmarks it for the Bulla DAO; it is not an annual management fee.

admin_fee_bps: int

Administrator fee rate in basis points from adminFeeBps().

FeeCalculations.calculateFees() prorates this rate over an invoice’s financing period. It is therefore the closest available counterpart to the shared annual management-fee field.

protocol_fee_balance: decimal.Decimal

Amount currently accrued for the protocol in denomination-token units.

This is protocolFeeBalance() after token-decimal conversion, not a fee rate and not necessarily an amount immediately withdrawable by a LP.

admin_fee_balance: decimal.Decimal

Amount currently accrued for the administrator in denomination-token units.

Bulla adds realised administrator fees and invoice-level underwriter spreads to this balance, so it must not be interpreted as admin fees alone.

target_yield_bps: int

Pool-wide target investor yield in basis points from targetYieldBps().

This is included as Bulla-native fee context only; it does not map to a generic fee field because it is a target return for liquidity providers.

property protocol_fee: float

Return the one-off protocol fee as a fractional percentage.

Returns

For example, 0.003 for a 30 basis point protocol fee.

property admin_fee: float

Return the time-prorated administrator fee as a fractional percentage.

Returns

For example, 0.01 for a 100 basis point annualised rate.

property target_yield: float

Return the pool’s target yield as a fractional percentage.

Returns

For example, 0.08 for an 800 basis point target yield.

as_generic_fee_data()

Map Bulla fees to the shared schema as internalised skimming.

adminFeeBps is time-prorated over invoice financing and is the only pool-level rate with the same shape as a generic management fee. The protocol fee and the underwriter’s spreadBps are financing terms, not LP entry, exit or vault performance fees. The spread is also set separately for each approved invoice, so it has no truthful pool-wide percentage to place in FeeData.

Bulla accounts for these charges before calculating the value backing LP shares. In the verified V2.1 implementation, reconcileSingleInvoice() passes realised interest, admin fee and underwriter spread to incrementProfitAndFeeBalances(). That helper records the admin fee and spread in adminFeeBalance but adds only the LP’s net interest to paidInvoicesGain. calculateCapitalAccount() then derives the capital account from deposits, paidInvoicesGain and withdrawals; ERC-4626 previewRedeem() and previewWithdraw() use that capital account. Thus the fee amounts are already excluded from the amount supporting shares, rather than deducted at redemption.

The protocol fee follows the same investor-facing pattern: Bulla reserves it when funding an invoice and tracks it in protocolFeeBalance. It is not an ERC-4626 deposit or withdrawal charge. See the verified BullaFactoringV2_1 source and FeeCalculations.sol.

Therefore the generic record uses internalised_skimming. The known administrator rate remains in management; the unsupported performance, deposit and withdrawal fee fields are known to be zero. Call fetch_bulla_invoice_fee_data() when native protocol-fee or invoice-spread detail is required.

Returns

Generic fee record for Bulla’s fees-net share value.

Return type

eth_defi.vault.fee.FeeData

classmethod fetch(vault, block_identifier)

Fetch every pool-wide Bulla V2.1 fee value in one coherent snapshot.

Only stable, zero-argument view selectors are used instead of copying the large explorer ABI. The verified V2.1 source declares the five getters used here: BullaFactoringV2_1 on Arbiscan.

Parameters
  • vault (eth_defi.erc_4626.vault_protocol.bulla.vault.BullaVault) – Bulla vault from which to read the configuration.

  • block_identifier (Union[Literal['latest', 'earliest', 'pending', 'safe', 'finalized'], eth_typing.evm.BlockNumber, eth_typing.evm.Hash32, eth_typing.encoding.HexStr, int]) – Block tag or number shared by all calls.

Returns

Pool-wide Bulla rates, balances and yield target.

Return type

eth_defi.erc_4626.vault_protocol.bulla.vault.BullaFeeData

__init__(block_identifier, protocol_fee_bps, admin_fee_bps, protocol_fee_balance, admin_fee_balance, target_yield_bps)
Parameters
  • block_identifier (Union[Literal['latest', 'earliest', 'pending', 'safe', 'finalized'], eth_typing.evm.BlockNumber, eth_typing.evm.Hash32, eth_typing.encoding.HexStr, int]) –

  • protocol_fee_bps (int) –

  • admin_fee_bps (int) –

  • protocol_fee_balance (decimal.Decimal) –

  • admin_fee_balance (decimal.Decimal) –

  • target_yield_bps (int) –

Return type

None

class BullaInvoiceFeeData

Bases: object

Bulla’s per-invoice fee terms, including the underwriter spread.

The verified V2.1 approvedInvoices(uint256) getter returns a nested FeeParams tuple containing the target-yield, spread, upfront, protocol and administrator rates. The struct is documented in the verified BullaFactoringV2_1 source.

This is intentionally separate from BullaFeeData: a pool can have many invoices with different underwriter spreads, so there is no truthful aggregate percentage to inject into generic vault fee metadata.

invoice_id: int

Bulla Claim invoice identifier supplied to approvedInvoices.

approved: bool

Whether the underwriter has approved this invoice for funding.

target_yield_bps: int

Base liquidity-provider return target in basis points; not a fee.

underwriter_spread_bps: int

Underwriter-selected invoice spread in basis points.

upfront_bps: int

Maximum creditor upfront funding percentage in basis points; not a fee.

protocol_fee_bps: int

Protocol fee copied into the immutable invoice approval in basis points.

admin_fee_bps: int

Administrator fee copied into the immutable invoice approval in basis points.

protocol_fee_amount: decimal.Decimal

Protocol fee amount reserved when this invoice was funded, in asset units.

property underwriter_spread: float

Return the invoice-specific spread as a fractional percentage.

Returns

For example, 0.015 for a 150 basis point spread.

classmethod fetch(vault, invoice_id, block_identifier)

Fetch one invoice’s native Bulla fee parameters.

approvedInvoices is a Solidity public-mapping getter. Its return tuple is decoded from the verified V2.1 ABI rather than a hand-written contract ABI file. The field order below follows the explorer ABI: 11 scalar approval fields, a five-value FeeParams tuple, then the pre-calculated per-second interest rate. Only the fee-related values are retained in this focused data class.

Parameters
  • vault (eth_defi.erc_4626.vault_protocol.bulla.vault.BullaVault) – Bulla vault holding the invoice approval mapping.

  • invoice_id (int) – Bulla Claim invoice identifier.

  • block_identifier (Union[Literal['latest', 'earliest', 'pending', 'safe', 'finalized'], eth_typing.evm.BlockNumber, eth_typing.evm.Hash32, eth_typing.encoding.HexStr, int]) – Block tag or number at which to read the record.

Returns

Invoice-level Bulla fee record, including the underwriter spread.

Return type

eth_defi.erc_4626.vault_protocol.bulla.vault.BullaInvoiceFeeData

__init__(invoice_id, approved, target_yield_bps, underwriter_spread_bps, upfront_bps, protocol_fee_bps, admin_fee_bps, protocol_fee_amount)
Parameters
  • invoice_id (int) –

  • approved (bool) –

  • target_yield_bps (int) –

  • underwriter_spread_bps (int) –

  • upfront_bps (int) –

  • protocol_fee_bps (int) –

  • admin_fee_bps (int) –

  • protocol_fee_amount (decimal.Decimal) –

Return type

None

class BullaVault

Bases: eth_defi.erc_4626.vault.ERC4626Vault

Read a Bulla Network Factoring vault.

The vault exposes the standard asset and share-accounting interface, but its operational flows are governed by Bulla’s permission and redemption queue contracts. This adapter supplies safe read support only until a permissioned end-to-end transaction flow can be certified.

Parameters
  • web3 – Connection we bind this instance to

  • spec – Chain, address tuple

  • token_cache

    Cache used with fetch_erc20_details() to avoid multiple calls to the same token.

    Reduces the number of RPC calls when scanning multiple vaults.

  • features – Pass vault feature flags along, externally detected.

  • default_block_identifier

    Override block identifier for on-chain metadata reads.

    When None, use get_safe_cached_latest_block_number() (the default, safe for broken RPCs). Set to "latest" for freshly deployed vaults whose contracts do not exist at the safe-cached block.

  • require_denomination_token – If True, accessing denomination_token will raise RuntimeError when the on-chain lookup returns None.

property bulla_metadata: Optional[eth_defi.erc_4626.vault_protocol.bulla.offchain_metadata.BullaVaultMetadata]

Return the reviewed public metadata for this exact Bulla pool.

Bulla does not provide a public, per-pool metadata API comparable to Lagoon’s. The address-scoped lookup uses only Bulla’s public TCS pages and returns None for every unreviewed pool, avoiding incorrect reuse of the TCS description or manager name.

Returns

Public Bulla pool metadata, if available.

property description: Optional[str]

Return the public long description for this reviewed Bulla pool.

property short_description: Optional[str]

Return the public one-line summary for this reviewed Bulla pool.

property manager_name: Optional[str]

Return Bulla’s published pool-manager attribution, if available.

fetch_bulla_fee_data(block_identifier='latest')

Fetch all pool-wide Bulla fee configuration and accrued balances.

Parameters

block_identifier (Union[Literal['latest', 'earliest', 'pending', 'safe', 'finalized'], eth_typing.evm.BlockNumber, eth_typing.evm.Hash32, eth_typing.encoding.HexStr, int]) – Block tag or number shared by all fee reads.

Returns

Bulla-native pool fee snapshot.

Return type

eth_defi.erc_4626.vault_protocol.bulla.vault.BullaFeeData

fetch_bulla_invoice_fee_data(invoice_id, block_identifier='latest')

Fetch native fee terms for one Bulla invoice approval.

Parameters
  • invoice_id (int) – Bulla Claim invoice identifier.

  • block_identifier (Union[Literal['latest', 'earliest', 'pending', 'safe', 'finalized'], eth_typing.evm.BlockNumber, eth_typing.evm.Hash32, eth_typing.encoding.HexStr, int]) – Block tag or number at which to read the terms.

Returns

Per-invoice Bulla fee record, including underwriter spread.

Return type

eth_defi.erc_4626.vault_protocol.bulla.vault.BullaInvoiceFeeData

get_fee_data()

Map Bulla’s pool configuration into the shared fee-data schema.

This is an internalised-skimming record: Bulla removes financing fees before they contribute to the capital account backing the share price. The administrator rate is retained as management; performance, deposit and withdrawal rates are explicitly zero. See BullaFeeData.as_generic_fee_data() for the source-linked accounting rationale and the Bulla-native fields that remain outside the shared model.

Returns

Generic fee data with a fees-net share price.

Return type

eth_defi.vault.fee.FeeData

get_management_fee(block_identifier)

Return Bulla’s administrator rate as the generic management fee.

The rate is prorated over invoice financing periods by Bulla’s fee library, making it the closest mapped value in the shared interface.

Parameters

block_identifier (Union[Literal['latest', 'earliest', 'pending', 'safe', 'finalized'], eth_typing.evm.BlockNumber, eth_typing.evm.Hash32, eth_typing.encoding.HexStr, int]) – Block at which the fee would be read.

Returns

Administrator fee ratio, such as 0.01 for 100 basis points.

Return type

float

get_performance_fee(block_identifier)

Return zero because Bulla has no vault-wide performance fee.

An underwriter can set an invoice-specific spreadBps, but this is part of the invoice financing calculation, not a percentage of vault investment profits. The V2.1 reconciliation logic puts that spread in adminFeeBalance before it calculates the capital account used for share redemptions. It is therefore represented by the internalised_skimming mode rather than this generic field. See the verified BullaFactoringV2_1 source.

Parameters

block_identifier (Union[Literal['latest', 'earliest', 'pending', 'safe', 'finalized'], eth_typing.evm.BlockNumber, eth_typing.evm.Hash32, eth_typing.encoding.HexStr, int]) – Unused because this fee is structurally zero.

Returns

Always 0.0.

Return type

float

get_deposit_fee(block_identifier)

Return zero because Bulla V2.1 does not charge an ERC-4626 entry fee.

Bulla’s protocol charge applies when a pool finances an invoice, not when a liquidity provider deposits into the ERC-4626 share contract.

Parameters

block_identifier (Union[Literal['latest', 'earliest', 'pending', 'safe', 'finalized'], eth_typing.evm.BlockNumber, eth_typing.evm.Hash32, eth_typing.encoding.HexStr, int]) – Unused because this fee is structurally zero.

Returns

Always 0.0.

Return type

float

get_withdraw_fee(block_identifier)

Return zero because Bulla V2.1 does not charge an ERC-4626 exit fee.

A redemption can be permissioned or queued, but the reviewed contract does not expose a percentage fee deducted from the LP’s withdrawal.

Parameters

block_identifier (Union[Literal['latest', 'earliest', 'pending', 'safe', 'finalized'], eth_typing.evm.BlockNumber, eth_typing.evm.Hash32, eth_typing.encoding.HexStr, int]) – Unused because this fee is structurally zero.

Returns

Always 0.0.

Return type

float

has_custom_fees()

Report that Bulla invoice-financing fees exceed the shared model.

The generic zero performance/deposit/withdraw values do not mean Bulla has no fees. The protocol supports distinct protocol, administrator and underwriter-spread components, and the latter differs between financing operations. Those charges are reflected in the fees-net share value and can be inspected through the Bulla-native data classes.

Returns

Always True for Bulla Factoring vaults.

Return type

bool

get_estimated_lock_up()

Return no fixed lock-up estimate for the pool.

Withdrawals depend on pool liquidity and can enter a FIFO redemption queue, so no reliable time period can be inferred from the contract.

Returns

None because redemption timing is pool-state dependent.

Return type

Optional[datetime.timedelta]

get_deposit_manager()

Block the generic ERC-4626 transaction manager.

Bulla pools can gate deposits and redemptions through distinct permission managers, while redemption can require a queued claim when liquidity is unavailable. A generic synchronous manager would promise a lifecycle this adapter has not certified.

Raises

NotImplementedError – Always, by deliberate transaction-safety policy.

Return type

eth_defi.vault.deposit_redeem.VaultDepositManager

fetch_deposit_closed_reason()

Explain why public deposits are unavailable through this adapter.

Returns

Permanent transaction-adapter block reason.

Return type

str

fetch_redemption_closed_reason()

Explain why public redemptions are unavailable through this adapter.

Returns

Permanent transaction-adapter block reason.

Return type

str

Return Bulla’s public pool dashboard.

The dashboard is the protocol’s public entry point and does not expose a stable per-vault URL pattern for every permissioned pool.

Parameters

referral (Optional[str]) – Unused optional referral value.

Returns

URL for Bulla Finance liquidity pools.

Return type

str

__init__(web3, spec, token_cache=None, features=None, default_block_identifier=None, require_denomination_token=False)
Parameters
  • web3 (web3.main.Web3) – Connection we bind this instance to

  • spec (eth_defi.vault.base.VaultSpec) – Chain, address tuple

  • token_cache (Optional[dict]) –

    Cache used with fetch_erc20_details() to avoid multiple calls to the same token.

    Reduces the number of RPC calls when scanning multiple vaults.

  • features (Optional[set[eth_defi.erc_4626.core.ERC4626Feature]]) – Pass vault feature flags along, externally detected.

  • default_block_identifier (Optional[Union[Literal['latest', 'earliest', 'pending', 'safe', 'finalized'], eth_typing.evm.BlockNumber, eth_typing.evm.Hash32, eth_typing.encoding.HexStr, hexbytes.main.HexBytes, int]]) –

    Override block identifier for on-chain metadata reads.

    When None, use get_safe_cached_latest_block_number() (the default, safe for broken RPCs). Set to "latest" for freshly deployed vaults whose contracts do not exist at the safe-cached block.

  • require_denomination_token (bool) – If True, accessing denomination_token will raise RuntimeError when the on-chain lookup returns None.

property address: eth_typing.evm.HexAddress

Get the vault smart contract address.

can_check_deposit()

Check if maxDeposit(address(0)) can be used to check global deposit availability.

Most ERC-4626 vaults implement maxDeposit in a way that returns meaningful values when called with address(0):

  • Returns 0 when deposits are globally closed/capped

  • Returns a positive value indicating maximum deposit allowed

Override to return False in subclasses where maxDeposit(address(0)) doesn’t provide meaningful global availability information.

Returns

True if maxDeposit(address(0)) returns meaningful values for global deposit availability checking.

Return type

bool

can_check_redeem()

Check if maxRedeem(address(0)) can be used to check global redemption availability.

Most protocols return 0 for maxRedeem(address(0)) because that address has no balance/shares, not because redemptions are closed:

  • Gearbox: maxRedeem returns min(balanceOf(owner), convertToShares(availableLiquidity))

  • Most vaults: Return 0 because address(0) has no shares

Some protocols do use maxRedeem(address(0)) meaningfully:

  • Morpho, IPOR, Plutus: Return 0 when redemptions are globally blocked

Override to return True in subclasses that support address(0) redemption checks.

Returns

True if maxRedeem(address(0)) returns meaningful values for global redemption availability checking.

Return type

bool

property chain_id: int

Chain this vault is on

property denomination_token: Optional[eth_defi.token.TokenDetails]

Get the token which denominates the vault valuation

  • Used in deposits and redemptions

  • Used in NAV calculation

  • Used in profit benchmarks

  • Usually USDC

Returns

Token wrapper instance.

Maybe None for broken vaults like https://arbiscan.io/address/0x9d0fbc852deccb7dcdd6cb224fa7561efda74411#code

Note

None results are not cached — the next access will retry the on-chain call. This avoids permanently caching a transient RPC failure.

property deposit_manager: eth_defi.vault.deposit_redeem.VaultDepositManager

Deposit manager assocaited with this vault

property erc_7540: bool

Is this ERC-7540 vault with asynchronous deposits.

  • For example previewDeposit() function and other functions will revert

fetch_available_liquidity(block_identifier='latest')

Get the amount of denomination token available for immediate withdrawal.

Only applicable to lending protocol vaults (IPOR, Euler, Morpho, Gearbox, etc.). Non-lending protocols should leave this method unimplemented.

Note: maxRedeem(address(0)) does NOT work as a proxy for available liquidity because it requires a specific address that has already deposited shares. For address(0), balanceOf is always 0, so maxRedeem returns 0 regardless of actual liquidity.

Parameters

block_identifier (Union[Literal['latest', 'earliest', 'pending', 'safe', 'finalized'], eth_typing.evm.BlockNumber, eth_typing.evm.Hash32, eth_typing.encoding.HexStr, int]) – Block to query. Defaults to “latest”.

Raises

NotImplementedError – For non-lending protocol vaults.

Returns

Amount in denomination token units (human-readable Decimal).

Return type

Optional[decimal.Decimal]

fetch_denomination_token()

Read denomination token from onchain.

Use denomination_token() for cached access.

Return type

Optional[eth_defi.token.TokenDetails]

fetch_denomination_token_address()

Get the asset() denomination token address of this vault.

Results are disk-cached per (chain_id, vault_address) via eth_defi.erc_4626.vault_token when the vault was constructed with a eth_defi.token.TokenDiskCache and no pinned default_block_identifier. The denomination token is immutable post-deployment, so the cached value is correct regardless of which block the caller would have asked for.

Only a definitive non-null answer is persisted. The None path taken on revert / broken contract is never cached, matching the behaviour of eth_defi.vault.base.VaultBase.denomination_token() which explicitly avoids memoising None so transient failures can be retried.

To disable the cache, pass token_cache=None (or any non- TokenDiskCache dict) when constructing the vault, or construct with a pinned default_block_identifier.

Returns

Denomination token address, or None if the vault contract is broken and did not return a valid address.

Return type

Optional[eth_typing.evm.HexAddress]

fetch_deposit_next_open()

Get when deposits will next be open.

  • For epoch-based vaults (Ostium, D2), return calculated window open time

  • For non-epoch vaults (Plutus, IPOR, Morpho), return None

  • Override in protocol-specific subclasses

Returns

Naive UTC datetime when deposits will next be available, or None if:

  • Deposits are currently open

  • Timing is unpredictable (manually controlled)

  • Protocol does not support timing information

Return type

Optional[datetime.datetime]

fetch_info()

Use info() property for cached access.

Returns

See LagoonVaultInfo

Return type

eth_defi.erc_4626.vault.ERC4626VaultInfo

fetch_nav(block_identifier=None)

Fetch the most recent onchain NAV value.

  • In the case of Lagoon, this is the last value written in the contract with updateNewTotalAssets() and ` settleDeposit()`

  • TODO: updateNewTotalAssets() there is no way to read pending asset update on chain

Returns

Vault NAV, denominated in denomination_token()

Return type

decimal.Decimal

fetch_portfolio(universe, block_identifier=None, allow_fallback=True)

Read the current token balances of a vault.

  • SHould be supported by all implementations

Parameters
Return type

eth_defi.vault.base.VaultPortfolio

fetch_redemption_next_open()

Get when withdrawals/redemptions will next be open.

  • For epoch-based vaults (Ostium, D2), return calculated window open time

  • For non-epoch vaults (Plutus, IPOR, Morpho), return None

  • Override in protocol-specific subclasses

Returns

Naive UTC datetime when withdrawals will next be available, or None if:

  • Withdrawals are currently open

  • Timing is unpredictable (manually controlled)

  • Protocol does not support timing information

Return type

Optional[datetime.datetime]

fetch_scan_record_extra_data()

Fetch protocol-specific private scan row columns.

Some vault protocols expose structured metadata that is useful for the raw scanner output but does not fit the shared human-readable columns. Override this hook in protocol-specific subclasses instead of adding a separate branch to eth_defi.erc_4626.scan.create_vault_scan_record().

Returns

Mapping of private scan-row column names, usually prefixed with _. The default implementation returns no extra data.

Return type

dict[str, object]

fetch_share_price(block_identifier)

Get the current share price.

Returns

The share price in underlying token.

If supply is zero return zero.

Parameters

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]) –

Return type

decimal.Decimal

fetch_share_token()

Read share token details onchain.

Use share_token() for cached access.

Return type

eth_defi.token.TokenDetails

fetch_share_token_address(block_identifier='latest')

Get share token of this vault.

  • Vault itself (ERC-4626)

  • share() accessor (ERC-7575)

Results are disk-cached per (chain_id, vault_address) via eth_defi.erc_4626.vault_token when the vault was constructed with a eth_defi.token.TokenDiskCache. Under normal circumstances the block_identifier argument is effectively ignored on cache hits — ERC-4626 share tokens are immutable post-deployment, so the cached value is correct regardless of which block the caller asked for.

Only a definitive answer from the chain is ever persisted: a successful call, or a revert matching KNOWN_SHARE_TOKEN_ERROR_MESSAGES (which positively classifies the contract as non-ERC-7575). Transient RPC failures (ProbablyNodeHasNoBlock, HTTP 502) fall back to self.vault_address but are not written to the cache, so a flaky node cannot poison a real ERC-7575 vault’s entry.

To disable the cache, pass token_cache=None (or any non- TokenDiskCache dict) when constructing the vault, or construct with a pinned default_block_identifier to force the uncached historical-read path on every call.

Parameters

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]) – Block to query. Cache is only consulted/written when the caller passes the default "latest" and the vault instance has no pinned default_block_identifier.

Return type

eth_typing.evm.HexAddress

fetch_total_assets(block_identifier)

What is the total NAV of the vault.

Example:

assert vault.denomination_token.symbol == "USDC"
assert vault.share_token.symbol == "ipUSDCfusion"
assert vault.fetch_total_assets(block_identifier=test_block_number) == Decimal("1437072.77357")
assert vault.fetch_total_supply(block_identifier=test_block_number) == Decimal("1390401.22652875")
Parameters

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]) –

Block number to read.

Use web3.eth.block_number for the last block.

Returns

The vault value in underlyinh token

Return type

Optional[decimal.Decimal]

fetch_total_supply(block_identifier)

What is the current outstanding shares.

Example:

Parameters

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]) –

Block number to read.

Use web3.eth.block_number for the last block.

Returns

The vault value in underlyinh token

Return type

decimal.Decimal

fetch_utilisation_percent(block_identifier='latest')

Get the percentage of assets currently lent out.

Only applicable to lending protocol vaults (IPOR, Euler, Morpho, Gearbox, etc.). Non-lending protocols should leave this method unimplemented.

Parameters

block_identifier (Union[Literal['latest', 'earliest', 'pending', 'safe', 'finalized'], eth_typing.evm.BlockNumber, eth_typing.evm.Hash32, eth_typing.encoding.HexStr, int]) – Block to query. Defaults to “latest”.

Raises

NotImplementedError – For non-lending protocol vaults.

Returns

Utilisation as float between 0.0 and 1.0 (0% to 100%).

Return type

Optional[float]

fetch_vault_info()

Get all information we can extract from the vault smart contracts.

Return type

eth_defi.erc_4626.vault.ERC4626VaultInfo

property flow_manager: eth_defi.vault.base.VaultFlowManager

Flow manager associated with this vault

get_deposit_manager_capability()

Declare the exact generic ERC-4626 implementation’s two-way flow.

Subclasses need exact-type inclusion in CERTIFIED_SYNCHRONOUS_DEPOSIT_MANAGER_CLASSES. The guarded probe may separately use supports_generic_deposit_manager() as a temporary fallback without advertising it as public metadata.

Returns

Synchronous two-way capability for the exact base class, otherwise None.

Return type

Optional[eth_defi.vault.deposit_redeem.VaultDepositManagerCapability]

get_fee_mode()

Get how this vault accounts its fees.

Return type

Optional[eth_defi.vault.fee.VaultFeeMode]

get_flags()

Get various vault state flags from the smart contract.

Returns

Flag set.

Do not modify in place.

Return type

set[eth_defi.vault.flag.VaultFlag]

get_flow_manager()

Get flow manager to read indiviaul settle events.

Return type

eth_defi.vault.base.VaultFlowManager

get_historical_reader(stateful)

Get share price reader to fetch historical returns.

Parameters

stateful – If True, use a stateful reading strategy.

Returns

None if unsupported

Return type

eth_defi.vault.base.VaultHistoricalReader

get_notes()

Get a human readable message if we know somethign special is going on with this vault.

Return type

Optional[str]

get_protocol_name()

Return the name of the vault protocol.

Return type

str

get_risk()

Get risk profile of this vault.

Return type

Optional[eth_defi.vault.risk.VaultTechnicalRisk]

get_synchronous_deposit_manager_capability()

Build static metadata for a verified synchronous manager.

A caller must already have established the reader class’ guarded fork evidence. This deliberately performs no RPC reads: the capability is static library metadata, not a live vault availability check.

Returns

Synchronous two-way capability.

Return type

eth_defi.vault.deposit_redeem.VaultDepositManagerCapability

has_block_range_event_support()

Does this vault support block range-based event queries for deposits and redemptions.

  • If not we use chain balance polling-based approach

has_deposit_distribution_to_all_positions()

Deposits go automatically to all open positions.

  • Deposits do not land into the vault as cash

  • Instead, smart contracts automatically increase all open positions

  • The behaviour of Velvet Capital

property info: eth_defi.vault.base.VaultInfo

Get info dictionary related to this vault deployment.

  • Get cached data on the various vault parameters

Returns

Vault protocol specific information dictionary

is_valid()

Check if this vault is valid.

  • Call a known smart contract function to verify the function exists

Return type

bool

property name: str

Vault name.

property share_token: eth_defi.token.TokenDetails

ERC-20 that presents vault shares.

  • User gets shares on deposit and burns them on redemption

supports_generic_deposit_manager()

Check whether the live vault exposes the standard ERC-4626 surface.

This is deliberately an interface check, not a public support claim. Callers must still execute a guarded fork probe before relying on the generic manager for a protocol-specific adapter.

Returns

True when asset succeeds with a non-zero asset address. Deposit and redemption availability is established only by a guarded fork transaction, not by ERC-4626 max* advisory values.

Return type

bool

property symbol: str

Vault share token symbol

property underlying_token: eth_defi.token.TokenDetails

Alias for denomination_token()

property vault_contract: web3.contract.contract.Contract

Get vault deployment.

first_seen_at_block: Optional[int]

Block number hint when this vault was deployed.

Must be set externally, as because of shitty Ethereum RPC we cannot query this. Allows us to avoid unnecessary work when scanning historical price data.