ipor-fusion 4.0.0.dev303__tar.gz → 4.0.0.dev308__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/PKG-INFO +2 -2
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/README.md +1 -1
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/pyproject.toml +1 -1
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/__init__.py +4 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/__init__.py +4 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/access.py +104 -1
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_access_manager.py +98 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_public_api.py +4 -0
- ipor_fusion-4.0.0.dev308/tests/test_simulate_timelock_base.py +51 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/.claude-plugin/marketplace.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/.claude-plugin/plugin.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/.env.example +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/.gemini/settings.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/.git-blame-ignore-revs +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/.github/workflows/cd.yml +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/.github/workflows/ci.yml +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/.github/workflows/commit-lint.yml +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/.github/workflows/notify-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/.github/workflows/python-build.yml +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/.github/workflows/python-publish.yml +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/.github/workflows/release.yml +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/.github/workflows/report-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/.gitignore +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/.pre-commit-config.yaml +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/.python-version +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/AGENTS.md +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/CHANGELOG.md +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/CLAUDE.md +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/CODEOWNERS +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/LICENSE +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/MIGRATION_4.md +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/build.sh +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/examples/CONTRIBUTING.md +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/examples/README.md +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/examples/advanced_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/examples/advanced_euler_v2_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/examples/composed_hypercore_flow_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/examples/external_state_margin_leg_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/examples/simple_aave_v3_supply_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/pytest.ini +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/scripts/commit-check.sh +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/scripts/crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/skills/ipor-deploy-vault/SKILL.md +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/about.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cache.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/chains.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/address_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/config_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/config_store.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/main.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/market_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/options.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/preflight_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/vault_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/vault_health.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/vault_info_view.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/vault_markets_view.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/vault_rendering.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/config/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/config/roles.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/address.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/context.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/context_manager.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/contract.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/erc20.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/external_state_executor.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/fuse.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/fuse_action.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/fuse_decoding.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/fusion_factory.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/logs.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/multicall.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/oracle.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/plasma_vault.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/simulation.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/simulation_result.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/discovery.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/errors.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/fuses/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/fuses/base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/fuses/ccip.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/fuses/stargate.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/lane.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/logs.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/messages.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/simulation.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/stargate/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/stargate/layerzero.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/stargate/transport.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/transport.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/dependency_graph.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/entry_cli.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/entry_mcp.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/errors.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/explorer.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/field_docs.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/aave_v3.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/async_action.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/erc4626.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/events.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/external_state.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/external_state_event_decoding.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/hypercore_event_decoding.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/merkl.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/morpho.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/fuses/universal.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/guide/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/guide/architecture.md +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/guide/glossary.md +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/guide/invariants.md +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/guide/quickstart.md +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/hypercore/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/market_ids.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/market_info.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/mcp/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/mcp/guide.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/mcp/models.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/mcp/server.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/morpho_api.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/preflight.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/py.typed +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/readers/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/readers/aave_v3.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/readers/aave_v4.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/readers/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/readers/hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/readers/lending_health.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/readers/morpho.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/readers/oracle_mapping_nodes.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/readers/oracle_mapping_reader.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/readers/position_manager.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/readers/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/readers/unpriceable.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/registry.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/substrates.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/types.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/validation.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/vault_data.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/vault_erc20.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/vault_info.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/vault_managers.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/vault_positions.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/vault_reads.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/UniswapV3UniversalRouter.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/_crosschain_recovery.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/_euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/_event_args.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/_fake_rpc.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/_foundry.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/_golden.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/_guide.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/_hypercore_model.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/_hypercore_shadow.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/_live.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/_oracle_mapping_fake.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/_simulate.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/_validation.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/addresses.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/conftest.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/constants.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/hypercore_hip3_flow.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/hypercore_market55.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/hypercore_official.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/market_golden/meta_morpho_v1.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/market_golden/meta_morpho_v1.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/market_golden/meta_morpho_v2.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/market_golden/meta_morpho_v2.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/market_golden/morpho_api/market.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/market_golden/morpho_api/vault_v1.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/market_golden/morpho_api/vault_v2.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/market_golden/morpho_api/vault_v2_not_found.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/market_golden/morpho_blue.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/market_golden/morpho_blue.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/market_golden/morpho_blue_api_error.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/market_golden/morpho_blue_api_error.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/market_golden/morpho_blue_no_api.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/market_golden/morpho_blue_no_api.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/oracle_mapping_golden/mapping.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/oracle_mapping_golden/mapping.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/simulate_v1_request.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/vault_info_golden/clean.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/vault_info_golden/clean.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/vault_info_golden/clean.txt +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/vault_info_golden/deployment_error.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/vault_info_golden/deployment_error.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/vault_info_golden/deployment_error.txt +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/vault_info_golden/fetched.cli.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/vault_info_golden/fetched.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/vault_info_golden/fetched.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/vault_info_golden/full.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/vault_info_golden/full.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/vault_info_golden/full.txt +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/vault_info_golden/rich.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/vault_info_golden/rich.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/fixtures/vault_info_golden/rich.txt +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_about.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cache.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_chains.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cli_address.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cli_changelog.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cli_commands.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cli_config_store.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cli_helpers.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cli_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cli_lending_health.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cli_market_golden.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cli_market_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cli_mcp_parity.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cli_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cli_oracle_mapping_golden.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cli_pending_requests_scan.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cli_preflight.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cli_role_accounts.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cli_vault_info_golden.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cli_vault_predates_getters.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_cli_vault_validate.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_contract_call.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_contract_encoder.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_crosschain_ccip_events.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_crosschain_ccip_indexer.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_crosschain_ccip_quote.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_crosschain_chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_crosschain_contracts.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_crosschain_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_crosschain_errors.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_crosschain_lane.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_crosschain_layering.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_crosschain_readiness_report.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_crosschain_transport.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_docs_typing.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_erc20.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_error_hierarchy.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_examples_composed_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_examples_euler_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_examples_vaults.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_explorer.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_external_state_events.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_external_state_executor.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_fuse_decoding.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_fuse_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_fusion_instance.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_governance_wrappers.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_guide.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_hypercore_deployment.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_hypercore_events.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_hypercore_flow.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_hypercore_live.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_hypercore_readers.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_hypercore_simulation.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_logs.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_mcp_address.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_mcp_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_mcp_models.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_mcp_preflight.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_mcp_server.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_mcp_vault_validate.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_oracle.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_plasma_vault.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_preflight.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_public_type_reachability.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_reader_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_readiness_selection.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_registry.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_revert_decoding.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_roles.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_sdk_layering.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_claim_morpho_rewards.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_crosschain_canary.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_crosschain_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_crosschain_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_euler_v2_batch_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_examples_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_examples_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_external_state_executor_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_looping_aave_v3_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_pilot_v3.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_pilot_v5_ramses.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_preflight_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_readers_integration.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_release_funds.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_swap_on_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulate_vault_from_scratch_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulation_errors.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_simulation_observation.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_solidity_compiler.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_solidity_mirrors.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_substrates.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_types_and_events.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_unpriceable_tokens.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_validation.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_vault_data_block.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_vault_dep_graph.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_vault_info_fetched_golden.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_vault_info_onchain_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_vault_reconciliation_onchain_base.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_vault_simulator_blocks.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_web3_context.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/test_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/typed_client/consumer.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/tests/typed_client/rejected.py +0 -0
- {ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ipor-fusion
|
|
3
|
-
Version: 4.0.0.
|
|
3
|
+
Version: 4.0.0.dev308
|
|
4
4
|
Summary: The IPOR Fusion SDK for Python
|
|
5
5
|
Project-URL: homepage, https://ipor.io
|
|
6
6
|
Project-URL: repository, https://github.com/IPOR-Labs/ipor-fusion.py
|
|
@@ -476,7 +476,7 @@ Fuse.method() --> FuseAction --> PlasmaVault.execute([actions]) --> Call
|
|
|
476
476
|
| `PlasmaVault` | ERC-4626 vault — execute, deposit, withdraw, previews, fuse, market, fee and limit configuration |
|
|
477
477
|
| `VaultSimulator` | Batch `execute` + reads through `eth_simulateV1`, multi-block, no local node |
|
|
478
478
|
| `FusionFactory` | Deploy a new vault (`clone`, `clone_supervised`) |
|
|
479
|
-
| `AccessManager` | Role-based access control |
|
|
479
|
+
| `AccessManager` | Role-based access control; `read_call_plan(ctx, call, caller=)` says whether a restricted call goes now, must be scheduled (execution delay), waits, is ready or is forbidden, and gives the call to send now; `schedule`, `execute` and `cancel` build the timelock calls |
|
|
480
480
|
| `RewardsManager` | Claim and vest rewards |
|
|
481
481
|
| `WithdrawManager` | Time-windowed withdrawal requests |
|
|
482
482
|
| `FeeManager` | Deposit, performance, and management fee configuration and harvesting |
|
|
@@ -427,7 +427,7 @@ Fuse.method() --> FuseAction --> PlasmaVault.execute([actions]) --> Call
|
|
|
427
427
|
| `PlasmaVault` | ERC-4626 vault — execute, deposit, withdraw, previews, fuse, market, fee and limit configuration |
|
|
428
428
|
| `VaultSimulator` | Batch `execute` + reads through `eth_simulateV1`, multi-block, no local node |
|
|
429
429
|
| `FusionFactory` | Deploy a new vault (`clone`, `clone_supervised`) |
|
|
430
|
-
| `AccessManager` | Role-based access control |
|
|
430
|
+
| `AccessManager` | Role-based access control; `read_call_plan(ctx, call, caller=)` says whether a restricted call goes now, must be scheduled (execution delay), waits, is ready or is forbidden, and gives the call to send now; `schedule`, `execute` and `cancel` build the timelock calls |
|
|
431
431
|
| `RewardsManager` | Claim and vest rewards |
|
|
432
432
|
| `WithdrawManager` | Time-windowed withdrawal requests |
|
|
433
433
|
| `FeeManager` | Deposit, performance, and management fee configuration and harvesting |
|
|
@@ -27,6 +27,8 @@ from ipor_fusion.config.roles import Roles
|
|
|
27
27
|
from ipor_fusion.core.access import (
|
|
28
28
|
AccessManager,
|
|
29
29
|
CallPermission,
|
|
30
|
+
CallPlan,
|
|
31
|
+
CallPlanKind,
|
|
30
32
|
RoleAccount,
|
|
31
33
|
RoleAccountJson,
|
|
32
34
|
RoleAccountsJson,
|
|
@@ -556,6 +558,8 @@ __all__ = [
|
|
|
556
558
|
"RoleAccount",
|
|
557
559
|
"RoleAccountJson",
|
|
558
560
|
"CallPermission",
|
|
561
|
+
"CallPlan",
|
|
562
|
+
"CallPlanKind",
|
|
559
563
|
"RoleStatus",
|
|
560
564
|
"resolve_access_manager",
|
|
561
565
|
"role_account_sort_key",
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from ipor_fusion.core.access import (
|
|
2
2
|
AccessManager,
|
|
3
3
|
CallPermission,
|
|
4
|
+
CallPlan,
|
|
5
|
+
CallPlanKind,
|
|
4
6
|
RoleAccount,
|
|
5
7
|
RoleAccountJson,
|
|
6
8
|
RoleAccountsJson,
|
|
@@ -107,6 +109,8 @@ __all__ = [
|
|
|
107
109
|
"RoleAccount",
|
|
108
110
|
"RoleAccountJson",
|
|
109
111
|
"CallPermission",
|
|
112
|
+
"CallPlan",
|
|
113
|
+
"CallPlanKind",
|
|
110
114
|
"RoleStatus",
|
|
111
115
|
"RewardsManager",
|
|
112
116
|
"VestingData",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from collections.abc import Callable, Sequence
|
|
2
2
|
from dataclasses import dataclass
|
|
3
|
-
from typing import TypedDict
|
|
3
|
+
from typing import Literal, TypedDict
|
|
4
4
|
|
|
5
5
|
from eth_abi import decode, encode
|
|
6
6
|
from eth_abi.exceptions import InsufficientDataBytes
|
|
@@ -68,6 +68,33 @@ class CallPermission:
|
|
|
68
68
|
return self.immediate or self.delay > 0
|
|
69
69
|
|
|
70
70
|
|
|
71
|
+
# schedule(when=0): as soon as the sender's execution delay allows.
|
|
72
|
+
_ASAP = Timestamp(0)
|
|
73
|
+
|
|
74
|
+
CallPlanKind = Literal["immediate", "schedule", "waiting", "ready", "forbidden"]
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@dataclass(frozen=True, slots=True)
|
|
78
|
+
class CallPlan:
|
|
79
|
+
"""How ``caller`` gets a restricted call through the access manager now.
|
|
80
|
+
|
|
81
|
+
- ``immediate``: send the call itself (``next_call``).
|
|
82
|
+
- ``schedule``: the caller has an execution delay and nothing is scheduled;
|
|
83
|
+
``next_call`` schedules it, executable ``delay`` seconds after it lands.
|
|
84
|
+
- ``waiting``: scheduled, executable at ``scheduled_at``; nothing to send yet.
|
|
85
|
+
- ``ready``: scheduled and executable; ``next_call`` is the call itself (or
|
|
86
|
+
the manager's ``execute`` with ``via_manager``), valid until the schedule
|
|
87
|
+
expires a week after ``scheduled_at``; an expired one plans ``schedule``.
|
|
88
|
+
- ``forbidden``: the caller has no role for it, or the target is closed.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
kind: CallPlanKind
|
|
92
|
+
permission: CallPermission
|
|
93
|
+
operation: ScheduleId
|
|
94
|
+
scheduled_at: Timestamp | None
|
|
95
|
+
next_call: Call[None] | None
|
|
96
|
+
|
|
97
|
+
|
|
71
98
|
def _call_permission_decoder(values: tuple[bool, int]) -> CallPermission:
|
|
72
99
|
immediate, delay = values
|
|
73
100
|
return CallPermission(immediate=immediate, delay=Period(delay))
|
|
@@ -204,6 +231,82 @@ class AccessManager(ContractWrapper):
|
|
|
204
231
|
Web3.keccak(encode(["address", "address", "bytes"], [caller, target, data]))
|
|
205
232
|
)
|
|
206
233
|
|
|
234
|
+
def schedule(
|
|
235
|
+
self, target: ChecksumAddress, data: bytes, when: Timestamp = _ASAP
|
|
236
|
+
) -> Call[None]:
|
|
237
|
+
"""Schedule ``data`` on ``target`` for the sender, executable at ``when``;
|
|
238
|
+
0 means as soon as the sender's execution delay allows, and a nonzero
|
|
239
|
+
time before that reverts."""
|
|
240
|
+
return self._write("schedule(address,bytes,uint48)", target, data, when)
|
|
241
|
+
|
|
242
|
+
def execute(self, target: ChecksumAddress, data: bytes) -> Call[None]:
|
|
243
|
+
"""Run ``data`` on ``target`` through the manager: an immediate call, or
|
|
244
|
+
the sender's scheduled operation once it is executable (it is consumed)."""
|
|
245
|
+
return self._write("execute(address,bytes)", target, data)
|
|
246
|
+
|
|
247
|
+
def cancel(
|
|
248
|
+
self, caller: ChecksumAddress, target: ChecksumAddress, data: bytes
|
|
249
|
+
) -> Call[None]:
|
|
250
|
+
"""Cancel ``caller``'s scheduled ``data`` on ``target``: the caller itself,
|
|
251
|
+
an ADMIN_ROLE member, or the guardian of the role ``target`` maps the
|
|
252
|
+
function's selector to may."""
|
|
253
|
+
return self._write("cancel(address,address,bytes)", caller, target, data)
|
|
254
|
+
|
|
255
|
+
def read_call_plan(
|
|
256
|
+
self,
|
|
257
|
+
ctx: Web3Context,
|
|
258
|
+
call: Call[object],
|
|
259
|
+
*,
|
|
260
|
+
caller: ChecksumAddress,
|
|
261
|
+
via_manager: bool = False,
|
|
262
|
+
) -> CallPlan:
|
|
263
|
+
"""What ``caller`` sends now to get ``call`` executed: an access and
|
|
264
|
+
timelock plan from ``canCall`` and, for a delayed caller, the schedule of
|
|
265
|
+
exactly ``call``'s calldata, all read at the block ``ctx.default_block``
|
|
266
|
+
names (a number, hash or tag, resolved once). It does not run the target's own checks
|
|
267
|
+
(redemption lock, pre-hooks, balances): simulate the call for those.
|
|
268
|
+
|
|
269
|
+
A ready operation is sent as ``call`` itself, from ``caller``: the target
|
|
270
|
+
consumes the schedule and still sees ``caller`` as the sender, which
|
|
271
|
+
deposits, withdrawals and other sender-dependent calls need.
|
|
272
|
+
``via_manager`` sends it through the manager's ``execute`` instead, for a
|
|
273
|
+
target that does not consume schedules; the manager is then the sender.
|
|
274
|
+
|
|
275
|
+
Raises ``ValueError`` for a call on the access manager itself: its
|
|
276
|
+
authorization is function-specific (role grants depend on the role's
|
|
277
|
+
admin, target configuration on the target's admin delay, and the IPOR
|
|
278
|
+
manager's own restricted functions on ``canCall``), which this plan does
|
|
279
|
+
not model.
|
|
280
|
+
"""
|
|
281
|
+
if call.to == self.address:
|
|
282
|
+
raise ValueError(
|
|
283
|
+
"read_call_plan does not plan calls on the access manager itself:"
|
|
284
|
+
" their authorization is function-specific"
|
|
285
|
+
)
|
|
286
|
+
block = ctx.web3.eth.get_block(ctx.default_block)
|
|
287
|
+
ctx = ctx.at_block(block["number"])
|
|
288
|
+
selector = bytes(call.data[:4])
|
|
289
|
+
permission = self.can_call(caller, call.to, selector).call(ctx)
|
|
290
|
+
operation = self.hash_operation(caller, call.to, call.data)
|
|
291
|
+
direct = Call[None](to=call.to, data=call.data)
|
|
292
|
+
if permission.immediate:
|
|
293
|
+
return CallPlan("immediate", permission, operation, None, direct)
|
|
294
|
+
if permission.delay == 0:
|
|
295
|
+
return CallPlan("forbidden", permission, operation, None, None)
|
|
296
|
+
scheduled_at = self.get_schedule(operation).call(ctx)
|
|
297
|
+
if scheduled_at == 0:
|
|
298
|
+
return CallPlan(
|
|
299
|
+
"schedule",
|
|
300
|
+
permission,
|
|
301
|
+
operation,
|
|
302
|
+
None,
|
|
303
|
+
self.schedule(call.to, call.data),
|
|
304
|
+
)
|
|
305
|
+
if scheduled_at > block["timestamp"]:
|
|
306
|
+
return CallPlan("waiting", permission, operation, scheduled_at, None)
|
|
307
|
+
ready = self.execute(call.to, call.data) if via_manager else direct
|
|
308
|
+
return CallPlan("ready", permission, operation, scheduled_at, ready)
|
|
309
|
+
|
|
207
310
|
def can_call(
|
|
208
311
|
self, caller: ChecksumAddress, target: ChecksumAddress, selector: bytes
|
|
209
312
|
) -> Call[CallPermission]:
|
|
@@ -15,8 +15,11 @@ from ipor_fusion import (
|
|
|
15
15
|
ContractNotFoundError,
|
|
16
16
|
NotPlasmaVaultError,
|
|
17
17
|
OwnerNotFoundError,
|
|
18
|
+
PlasmaVault,
|
|
18
19
|
RoleAccount,
|
|
20
|
+
Roles,
|
|
19
21
|
parse_access_manager_address,
|
|
22
|
+
parse_plasma_vault_address,
|
|
20
23
|
resolve_access_manager,
|
|
21
24
|
role_account_sort_key,
|
|
22
25
|
)
|
|
@@ -317,3 +320,98 @@ def test_hash_operation_matches_the_deployed_manager():
|
|
|
317
320
|
assert AccessManager.hash_operation(caller, vault, data).hex() == (
|
|
318
321
|
"449c1b0678d9666078c86be94b86c7f4bfe8fe012bdacb56246db911e78b7ebb"
|
|
319
322
|
)
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
class TestCallPlan:
|
|
326
|
+
manager = AccessManager(parse_access_manager_address(MANAGER_ADDR))
|
|
327
|
+
target_call = PlasmaVault(parse_plasma_vault_address(VAULT_ADDR)).execute([])
|
|
328
|
+
NOW = 10_000
|
|
329
|
+
|
|
330
|
+
def _ctx(self, *, immediate: bool, delay: int, scheduled: int = 0):
|
|
331
|
+
def handler(_to: str, data: bytes) -> bytes:
|
|
332
|
+
selector = bytes(data[:4])
|
|
333
|
+
if selector == Web3.keccak(text="canCall(address,address,bytes4)")[:4]:
|
|
334
|
+
return encode(["bool", "uint32"], [immediate, delay])
|
|
335
|
+
assert selector == Web3.keccak(text="getSchedule(bytes32)")[:4]
|
|
336
|
+
return encode(["uint48"], [scheduled])
|
|
337
|
+
|
|
338
|
+
ctx = MagicMock()
|
|
339
|
+
ctx.default_block = "finalized"
|
|
340
|
+
ctx.at_block.return_value = ctx
|
|
341
|
+
ctx.call.side_effect = multicall_aware(handler)
|
|
342
|
+
ctx.web3.eth.get_block.return_value = {"number": 777, "timestamp": self.NOW}
|
|
343
|
+
return ctx
|
|
344
|
+
|
|
345
|
+
def _plan(self, *, via_manager: bool = False, **kwargs):
|
|
346
|
+
return self.manager.read_call_plan(
|
|
347
|
+
self._ctx(**kwargs), self.target_call, caller=ALICE, via_manager=via_manager
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
def test_immediate_sends_the_call_itself(self):
|
|
351
|
+
plan = self._plan(immediate=True, delay=0)
|
|
352
|
+
assert plan.kind == "immediate"
|
|
353
|
+
assert plan.next_call is not None
|
|
354
|
+
assert (plan.next_call.to, plan.next_call.data) == (
|
|
355
|
+
self.target_call.to,
|
|
356
|
+
self.target_call.data,
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
def test_the_block_the_context_names_is_resolved_once_and_pinned(self):
|
|
360
|
+
ctx = self._ctx(immediate=False, delay=3600, scheduled=self.NOW)
|
|
361
|
+
self.manager.read_call_plan(ctx, self.target_call, caller=ALICE)
|
|
362
|
+
ctx.web3.eth.get_block.assert_called_once_with("finalized")
|
|
363
|
+
ctx.at_block.assert_called_once_with(777)
|
|
364
|
+
|
|
365
|
+
def test_forbidden_sends_nothing(self):
|
|
366
|
+
plan = self._plan(immediate=False, delay=0)
|
|
367
|
+
assert (plan.kind, plan.next_call) == ("forbidden", None)
|
|
368
|
+
|
|
369
|
+
def test_a_delayed_caller_schedules_first(self):
|
|
370
|
+
plan = self._plan(immediate=False, delay=3600)
|
|
371
|
+
assert plan.kind == "schedule"
|
|
372
|
+
assert plan.next_call is not None
|
|
373
|
+
assert plan.next_call.data == Web3.keccak(
|
|
374
|
+
text="schedule(address,bytes,uint48)"
|
|
375
|
+
)[:4] + encode(
|
|
376
|
+
["address", "bytes", "uint48"],
|
|
377
|
+
[self.target_call.to, self.target_call.data, 0],
|
|
378
|
+
)
|
|
379
|
+
assert plan.operation == AccessManager.hash_operation(
|
|
380
|
+
ALICE, self.target_call.to, self.target_call.data
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
def test_waiting_then_ready_through_the_manager(self):
|
|
384
|
+
waiting = self._plan(immediate=False, delay=3600, scheduled=self.NOW + 1)
|
|
385
|
+
assert (waiting.kind, waiting.scheduled_at, waiting.next_call) == (
|
|
386
|
+
"waiting",
|
|
387
|
+
self.NOW + 1,
|
|
388
|
+
None,
|
|
389
|
+
)
|
|
390
|
+
ready = self._plan(immediate=False, delay=3600, scheduled=self.NOW)
|
|
391
|
+
assert ready.kind == "ready"
|
|
392
|
+
assert ready.next_call is not None
|
|
393
|
+
# Sent as the call itself, so the target consumes the schedule and still
|
|
394
|
+
# sees the caller as the sender.
|
|
395
|
+
assert (ready.next_call.to, ready.next_call.data) == (
|
|
396
|
+
self.target_call.to,
|
|
397
|
+
self.target_call.data,
|
|
398
|
+
)
|
|
399
|
+
relayed = self._plan(
|
|
400
|
+
immediate=False, delay=3600, scheduled=self.NOW, via_manager=True
|
|
401
|
+
)
|
|
402
|
+
assert relayed.next_call is not None
|
|
403
|
+
assert relayed.next_call.to == MANAGER_ADDR
|
|
404
|
+
assert relayed.next_call.data == Web3.keccak(text="execute(address,bytes)")[
|
|
405
|
+
:4
|
|
406
|
+
] + encode(["address", "bytes"], [self.target_call.to, self.target_call.data])
|
|
407
|
+
|
|
408
|
+
def test_calls_on_the_manager_itself_are_not_planned(self):
|
|
409
|
+
grant = self.manager.grant_role(Roles.ALPHA_ROLE, ALICE, Period(0))
|
|
410
|
+
with pytest.raises(ValueError, match="access manager itself"):
|
|
411
|
+
self.manager.read_call_plan(MagicMock(), grant, caller=ALICE)
|
|
412
|
+
|
|
413
|
+
def test_cancel_encodes_caller_target_and_data(self):
|
|
414
|
+
call = self.manager.cancel(ALICE, VAULT_ADDR, b"\x01")
|
|
415
|
+
assert call.data == Web3.keccak(text="cancel(address,address,bytes)")[
|
|
416
|
+
:4
|
|
417
|
+
] + encode(["address", "address", "bytes"], [ALICE, VAULT_ADDR, b"\x01"])
|
|
@@ -82,6 +82,8 @@ _ALL_SNAPSHOT: dict[str, frozenset[str]] = {
|
|
|
82
82
|
"CacheKey",
|
|
83
83
|
"Call",
|
|
84
84
|
"CallPermission",
|
|
85
|
+
"CallPlan",
|
|
86
|
+
"CallPlanKind",
|
|
85
87
|
"ChainId",
|
|
86
88
|
"ChainlinkDetailJson",
|
|
87
89
|
"ChangelogEntry",
|
|
@@ -548,6 +550,8 @@ _ALL_SNAPSHOT: dict[str, frozenset[str]] = {
|
|
|
548
550
|
"BlockOverrides",
|
|
549
551
|
"Call",
|
|
550
552
|
"CallPermission",
|
|
553
|
+
"CallPlan",
|
|
554
|
+
"CallPlanKind",
|
|
551
555
|
"CloneArgs",
|
|
552
556
|
"ContextManager",
|
|
553
557
|
"DecodedFuseAction",
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""A timelocked governance call on a live Base vault, end to end in one
|
|
2
|
+
eth_simulateV1 run: the plan says schedule, the scheduled call is not executable
|
|
3
|
+
before the delay, and runs through the manager after it. Skipped without an
|
|
4
|
+
archive ``BASE_PROVIDER_URL`` that serves ``eth_simulateV1``."""
|
|
5
|
+
|
|
6
|
+
from _live import archive_context
|
|
7
|
+
from web3 import Web3
|
|
8
|
+
|
|
9
|
+
from ipor_fusion import AccessManager, PlasmaVault, Shares, VaultSimulator
|
|
10
|
+
from ipor_fusion.types import parse_plasma_vault_address
|
|
11
|
+
|
|
12
|
+
VAULT = parse_plasma_vault_address("0xc4c00d8b323f37527eeda27c87412378be9f68ec")
|
|
13
|
+
# Holds the vault's ATOMIST role with a three-day execution delay.
|
|
14
|
+
ATOMIST = Web3.to_checksum_address("0xF6a9bd8F6DC537675D499Ac1CA14f2c55d8b5569")
|
|
15
|
+
BLOCK = 52973779
|
|
16
|
+
NEW_CAP = Shares(10**30)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_schedule_wait_and_execute_a_delayed_call(web3_base):
|
|
20
|
+
ctx = archive_context("BASE_PROVIDER_URL", BLOCK, VAULT)
|
|
21
|
+
vault = PlasmaVault(VAULT)
|
|
22
|
+
manager = AccessManager(vault.get_access_manager_address().call(ctx))
|
|
23
|
+
cap = vault.set_total_supply_cap(NEW_CAP)
|
|
24
|
+
|
|
25
|
+
plan = manager.read_call_plan(ctx, cap, caller=ATOMIST)
|
|
26
|
+
assert plan.kind == "schedule"
|
|
27
|
+
assert plan.permission.delay == 3 * 24 * 3600
|
|
28
|
+
assert plan.next_call is not None
|
|
29
|
+
|
|
30
|
+
early = VaultSimulator(web3_base, block=BLOCK)
|
|
31
|
+
early.add_call(plan.next_call, from_=ATOMIST, label="schedule")
|
|
32
|
+
early.next_block(3600)
|
|
33
|
+
early.add_call(cap, from_=ATOMIST, label="early")
|
|
34
|
+
scheduled, too_early = early.run().calls
|
|
35
|
+
assert scheduled.success
|
|
36
|
+
assert not too_early.success
|
|
37
|
+
assert too_early.error is not None
|
|
38
|
+
assert "0x18cb6b7a" in too_early.error # AccessManagerNotReady(bytes32)
|
|
39
|
+
|
|
40
|
+
# Once ready, the vault consumes the schedule on a direct call from the
|
|
41
|
+
# atomist, or the manager relays it.
|
|
42
|
+
for ready in (cap, manager.execute(cap.to, cap.data)):
|
|
43
|
+
sim = VaultSimulator(web3_base, block=BLOCK)
|
|
44
|
+
sim.add_call(plan.next_call, from_=ATOMIST)
|
|
45
|
+
when = sim.observe(manager.get_schedule(plan.operation))
|
|
46
|
+
sim.next_block(int(plan.permission.delay) + 1)
|
|
47
|
+
sim.add_call(ready, from_=ATOMIST)
|
|
48
|
+
after = sim.observe(vault.get_total_supply_cap())
|
|
49
|
+
assert sim.run().all_success
|
|
50
|
+
assert when.value > 0
|
|
51
|
+
assert after.value == NEW_CAP
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/examples/advanced_euler_v2_looping_arbitrum.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/examples/external_state_margin_leg_base.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/examples/simple_aave_v3_supply_base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/oracle_mapping_view.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/vault_info_view.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/vault_markets_view.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/cli/vault_rendering.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/context_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/fusion_factory.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/rewards_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/simulation_result.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/core/withdraw_manager.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/__init__.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/ccip/__init__.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/ccip/chainlink.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/ccip/codec.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/ccip/contracts.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/ccip/events.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/ccip/indexer.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/ccip/lane.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/ccip/quote.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/ccip/transport.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/contracts.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/discovery.py
RENAMED
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/fuses/__init__.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/fuses/base.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/fuses/ccip.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/fuses/stargate.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/messages.py
RENAMED
|
File without changes
|
{ipor_fusion-4.0.0.dev303 → ipor_fusion-4.0.0.dev308}/src/ipor_fusion/crosschain/simulation.py
RENAMED
|
File without changes
|