All Developer News

v3.10.0 – v3.11.0

SDK/CLI

These releases add five chains to the vault tooling, Aave V4 lending health per Spoke and a HyperCore cross-chain example, with fixes for vaults deployed before the August 2024 audit and for providers that cap block ranges. They apply to developers who read vaults with the CLI or the SDK, and to builders of cross-chain flows.

New

1. HyperCore cross-chain example (preview) (v3.10.0)

Now: a runnable example of the composed flow. An Arbitrum hub funds a HyperCore vault on HyperEVM over CCIP, and the vault trades on HyperCore. Nothing is signed.

Usage: the example is examples/composed_hypercore_flow_arbitrum_hyperevm.py in the SDK repository.

2. Adding vaults to a cross-chain lane (preview) (v3.10.0)

Before: to add a vault without replacing the list, callers had to drop to enter(UPDATE_VAULTS, …, vaults_replace=False).

Now: CcipCrosschainCommandFuse.update_vaults(replace=False) adds the given vaults to the dispatcher’s allowlist. The default is unchanged: the given vaults replace the list.

Usage: update_vaults(..., replace=False) adds to the allowlist. Without replace, the call replaces it.

3. External State reads (v3.10.0)

Before: no contract exposed the External State market’s vault state as getters. The pause flag was visible only through the fuse’s event.

Now: read_external_state(ctx, vault) reads, at one block, the executor the vault deployed, the balance fuse’s cached total, the custodian timestamp the fuse last checked and the pause flag. The executor wrapper adds get_balance_fuse_snapshot, which returns the live total, the threshold and the last confirmed custodian update.

Usage: read_external_state is imported from ipor_fusion and returns an ExternalStateVaultState. get_balance_fuse_snapshot is called on the executor wrapper and returns a BalanceFuseSnapshot.

4. Preview status for cross-chain and HyperCore (v3.10.0)

Now: the SDK states that the cross-chain market (54) and the HyperCore market (55) are preview. Their interfaces may change between minor versions. The status is in PREVIEW_FEATURES and PREVIEW_STATEMENT. It appears in server_info.preview_features (MCP), in the fusion changelog output, in the README and in the module docstrings.

Impact: ipor_fusion.crosschain, ipor_fusion.fuses.crosschain and the HyperCore fuses, readers and events are marked preview.

5. Aave V4 lending health per Spoke (v3.10.2)

Before: vault_info.lending_health covered Morpho and Aave V3 only. Vaults leveraged on Aave V4 reported no LTV or health factor, and worst_ltv_usage_percent stayed null.

Now: lending health has one row per Aave V4 Spoke, read from getUserAccountData. LendingMarketHealth in the vault_info JSON and the MCP model carries substrate_id: the Morpho market id or the Aave V4 Spoke.

Impact: each lending_health row is identified by its substrate_id, including when a vault has several Morpho rows.

6. Unichain, Plasma, Avalanche, Katana and Monad (v3.11.0)

Now: SUPPORTED_CHAIN_IDS adds 130, 9745, 43114, 747474 and 143. vault info and vault oracle-mapping complete on every live vault of those chains.

Impact: fusion vault info and fusion vault oracle-mapping accept vaults on these five chains.

Fixes

1. Silo V2 markets (v3.10.0)

Before: fetching vault data failed for any vault with a granted Silo V2 config substrate. Decoding getSilos() raised a TypeError, and the whole vault data fetch aborted.

Now: the getSilos() pair is decoded as one tuple.

Impact: None for existing code.

2. Unpriceable tokens the vault does not hold (v3.10.0)

Before: vault info reported every granted substrate whose token cannot be priced as CRITICAL. This included Morpho collateral the vault never holds.

Now: a token the vault does not hold is reported as WARNING. A token the vault holds stays CRITICAL. Each warning ends with a fix:.

Impact: on supply-only vaults, these findings move from the criticals to the warnings.

3. Vaults without market settings getters (v3.10.1)

Before: Plasma Vaults deployed before the August 2024 audit answer getMarketSubstrates, getTotalSupplyCap and getPriceOracleMiddleware with empty data. vault info aborted on them with EmptyCallResultError.

Now: those getters are read as optional. A getter that returns no data is recorded in unimplemented_getters and reported as a health-check warning.

Impact: None for existing code.

4. External State snapshot block (v3.10.1)

Before: read_external_state treated every non-numeric default_block as latest. A context pinned to finalized, safe, earliest or a block hash read current state.

Now: a tag reads the block it denotes. A block hash reads that block. pending is rejected.

Impact: read_external_state raises an error for a context whose default_block is pending.

5. Oversized storage values in External State reads (v3.10.1)

Before: a storage word longer than 32 bytes became an arbitrary-width integer.

Now: a storage word longer than 32 bytes raises an error.

Impact: None for existing code.

6. Price oracle of older vaults (v3.11.0)

Before: vault oracle-mapping read getPriceOracleMiddleware() directly. Plasma Vaults deployed before the August 2024 audit name the getter getPriceOracle(), and the command aborted with EmptyCallResultError.

Now: PlasmaVault.price_oracle_address() falls back to getPriceOracle(). It raises UnsupportedVaultVersionError when the vault answers neither, and the command reports that error.

Impact: None for existing code.

7. Balance fuses and withdraw manager (v3.11.0)

Before: PlasmaVault.get_balance_fuses() and withdraw_manager_address() replayed events from block 0 on every call. On chains whose providers cap the block range, this took thousands of eth_getLogs requests. The withdraw manager was stale where a maintenance fuse swapped it without emitting WithdrawManagerChanged.

Now: balance fuses come from getActiveMarketsInBalanceFuses(). The withdraw manager is read from vault storage the way the contracts resolve it. Vaults that predate these views still replay events.

Impact: None for existing code.

8. Event history in pages (v3.11.0)

Before: every event scan sent a single eth_getLogs from block 0 to latest. Providers rejected it, for example with a 10,000-block range cap on Unichain, Ink and Plasma.

Now: Web3Context.get_logs pages the scan from the contract’s creation block. Pages shrink when the provider rejects one. A scan that cannot complete within log_scan_max_requests (1,000 by default) or log_scan_timeout_s raises LogScanError.

Impact: vault info reports role_accounts and pending withdraw requests as null when their scan cannot complete. Its JSON output can carry null in these fields.


Upgrade with pip install -U ipor-fusion. Full changelog: v3.10.0 on GitHub, v3.10.1 on GitHub, v3.10.2 on GitHub, v3.11.0 on GitHub.

These notes describe changes to the IPOR Fusion SDK. They are not operational or financial advice. Operators are responsible for testing changes against their own vaults and configuration before use.