midas.registry

Documentation for eth_defi.midas.registry Python module.

Midas deployed contract registry.

This module is a Pythonised snapshot of the public Midas TypeScript address registry. The upstream source is:

https://raw.githubusercontent.com/midas-apps/contracts/main/config/constants/addresses.ts

Snapshot metadata:

  • Repository: midas-apps/contracts

  • Branch: main

  • Commit: 9151f86df2af21f41f6f0efa0bd361c6d3dc3adf

  • Commit timestamp: 2026-07-09T14:26:21Z

How this file was generated

This registry has two data sources.

The address snapshot is generated from the upstream Midas contract repository. The MIDAS_ADDRESSES_PER_NETWORK data comes from addresses.ts by evaluating the exported TypeScript object literals as JavaScript and serialising them as Python dictionaries. TypeScript undefined values are converted to None. The companion MIDAS_CHAIN_IDS mapping is generated from:

https://raw.githubusercontent.com/midas-apps/contracts/main/config/networks/index.ts

The deployment metadata in MIDAS_PRODUCT_DEPLOYMENTS is generated by a live archive-node scan over each product token address. The scanner performs binary search with historical eth_getCode calls to find the first block where the product token bytecode exists, then reads that block timestamp. This step only covers products whose registry entry has both token and dataFeed and whose Midas network has a configured local JSON-RPC environment variable in MIDAS_NETWORK_RPC_ENV_VARS.

Manual update process

  1. Fetch the latest upstream TypeScript files:

    curl -L https://raw.githubusercontent.com/midas-apps/contracts/main/config/constants/addresses.ts -o /tmp/midas-addresses.ts
    curl -L https://raw.githubusercontent.com/midas-apps/contracts/main/config/networks/index.ts -o /tmp/midas-networks.ts
    
  2. Convert the exported midasAddressesPerNetwork, sanctionListContracts and ustbContracts objects to Python dictionaries. TypeScript undefined values should become None. Computed [chainIds.*] keys in the smaller maps should become integer chain ids.

  3. Replace only the upstream-generated constants in this file and update MIDAS_REGISTRY_SOURCE_COMMIT and MIDAS_REGISTRY_SOURCE_COMMIT_DATE.

  4. Refresh deployment blocks and timestamps from archive nodes:

    source .local-test.env && UPDATE_REGISTRY=true poetry run python scripts/midas/scan-deployments.py
    

    The scan output is a tabulate audit table. Products on networks without a configured RPC environment variable are skipped instead of guessed.

  5. Run:

    poetry run ruff format eth_defi/midas/registry.py
    poetry run ruff check eth_defi/midas/registry.py
    

The active vault scanner allow-list is generated from this registry. A product is promoted to the shared scanner once it has an mToken, a Midas datafeed and deployment metadata. Products without a local RPC mapping or deployment scan remain visible here, but are not used by the scanner until the missing metadata is generated. If a product’s registry feeds cannot currently produce a positive NAV/share, record it in MIDAS_PRODUCT_SCAN_EXCLUSIONS with the observed reason instead of silently letting production scans fail.

Module Attributes

MIDAS_NETWORK_RPC_ENV_VARS

Registry networks and their local JSON-RPC environment variable names.

MIDAS_PRODUCT_DEPLOYMENTS

Scanned deployment blocks for Midas products.

MIDAS_REGISTRY_NON_PRODUCT_KEYS

Non-product registry sections.

MIDAS_REDEMPTION_VAULT_FIELDS

Redemption vault fields in preference order for scanner diagnostics.

MIDAS_CUSTOM_FEED_FIELDS

Custom oracle fields in preference order for share price fallback reads.

MIDAS_DEPOSIT_VAULT_FIELDS

Deposit vault fields in preference order for scanner diagnostics.

MIDAS_PRODUCT_SCAN_EXCLUSIONS

Products whose registry entries are intentionally not promoted to scanning.

Functions

get_midas_registry_products_by_chain(*[, ...])

Group Midas registry products by chain id.

iter_midas_registry_products(*[, ...])

Iterate product-like entries from the Pythonised Midas registry.

Classes

MidasRegistryProduct

Scanner-friendly Midas product entry.

MIDAS_NETWORK_RPC_ENV_VARS: Final[dict[str, str]] = {'arbitrum': 'JSON_RPC_ARBITRUM', 'base': 'JSON_RPC_BASE', 'bsc': 'JSON_RPC_BINANCE', 'hyperevm': 'JSON_RPC_HYPERLIQUID', 'katana': 'JSON_RPC_KATANA', 'main': 'JSON_RPC_ETHEREUM', 'monad': 'JSON_RPC_MONAD', 'optimism': 'JSON_RPC_OPTIMISM', 'plasma': 'JSON_RPC_PLASMA', 'tac': 'JSON_RPC_TAC'}

Registry networks and their local JSON-RPC environment variable names.

Keep this map explicit because Midas network names do not always match eth_defi.chain.CHAIN_NAMES aliases.

MIDAS_PRODUCT_DEPLOYMENTS: Final[dict[tuple[str, str], tuple[int, datetime.datetime]]] = {('arbitrum', 'mBASIS'): (310831851, datetime.datetime(2025, 2, 28, 15, 55, 55)), ('arbitrum', 'mEDGE'): (311756173, datetime.datetime(2025, 3, 3, 8, 39, 59)), ('arbitrum', 'mMEV'): (311756840, datetime.datetime(2025, 3, 3, 8, 42, 45)), ('arbitrum', 'mRE7'): (311757192, datetime.datetime(2025, 3, 3, 8, 44, 13)), ('arbitrum', 'mTBILL'): (310814679, datetime.datetime(2025, 2, 28, 14, 44, 25)), ('base', 'mBASIS'): (21444525, datetime.datetime(2024, 10, 23, 10, 13, 17)), ('base', 'mEDGE'): (26499551, datetime.datetime(2025, 2, 17, 10, 34, 9)), ('base', 'mEVUSD'): (37775645, datetime.datetime(2025, 11, 5, 11, 3, 57)), ('base', 'mLIQUIDITY'): (30256530, datetime.datetime(2025, 5, 15, 9, 46, 47)), ('base', 'mMEV'): (26500311, datetime.datetime(2025, 2, 17, 10, 59, 29)), ('base', 'mRE7'): (26499775, datetime.datetime(2025, 2, 17, 10, 41, 37)), ('base', 'mSL'): (29566149, datetime.datetime(2025, 4, 29, 10, 14, 5)), ('base', 'mTBILL'): (19975742, datetime.datetime(2024, 9, 19, 10, 13, 51)), ('bsc', 'cUSDO'): (64016550, datetime.datetime(2025, 10, 9, 12, 10, 43)), ('bsc', 'mXRP'): (63687212, datetime.datetime(2025, 10, 6, 15, 32, 6)), ('hyperevm', 'dnETH'): (15226933, datetime.datetime(2025, 9, 30, 11, 2)), ('hyperevm', 'dnFART'): (13375947, datetime.datetime(2025, 9, 9, 9, 14)), ('hyperevm', 'dnHYPE'): (11445176, datetime.datetime(2025, 8, 18, 9, 28)), ('hyperevm', 'dnPUMP'): (12423459, datetime.datetime(2025, 8, 29, 12, 57)), ('hyperevm', 'dnTEST'): (15230410, datetime.datetime(2025, 9, 30, 11, 59)), ('hyperevm', 'hbUSDC'): (10226740, datetime.datetime(2025, 8, 4, 12, 29)), ('hyperevm', 'hbUSDT'): (3270801, datetime.datetime(2025, 5, 2, 10, 28, 32)), ('hyperevm', 'hbXAUt'): (5474555, datetime.datetime(2025, 6, 11, 8, 27, 34)), ('hyperevm', 'kitBTC'): (13021617, datetime.datetime(2025, 9, 5, 8, 24)), ('hyperevm', 'kitHYPE'): (13017103, datetime.datetime(2025, 9, 5, 7, 10)), ('hyperevm', 'kitUSD'): (12955859, datetime.datetime(2025, 9, 4, 14, 26)), ('hyperevm', 'liquidHYPE'): (8725211, datetime.datetime(2025, 7, 18, 9, 3)), ('hyperevm', 'lstHYPE'): (8115617, datetime.datetime(2025, 7, 11, 10, 25)), ('hyperevm', 'obeatUSD'): (15403040, datetime.datetime(2025, 10, 2, 11, 9)), ('hyperevm', 'wNLP'): (15223761, datetime.datetime(2025, 9, 30, 10, 10)), ('hyperevm', 'wVLP'): (10921614, datetime.datetime(2025, 8, 12, 10, 23)), ('katana', 'kmiUSD'): (9366730, datetime.datetime(2025, 8, 25, 8, 12, 21)), ('katana', 'mHYPER'): (22684661, datetime.datetime(2026, 1, 26, 11, 37, 52)), ('katana', 'mRE7SOL'): (4540503, datetime.datetime(2025, 6, 30, 11, 35, 14)), ('main', 'JIV'): (23274808, datetime.datetime(2025, 9, 2, 10, 25, 11)), ('main', 'acremBTC1'): (23367405, datetime.datetime(2025, 9, 15, 8, 52, 23)), ('main', 'bondBTC'): (24869298, datetime.datetime(2026, 4, 13, 7, 16, 23)), ('main', 'bondETH'): (24850328, datetime.datetime(2026, 4, 10, 15, 49, 35)), ('main', 'bondUSD'): (24849841, datetime.datetime(2026, 4, 10, 14, 11, 59)), ('main', 'carryTradeUSDTRYLeverage'): (25128195, datetime.datetime(2026, 5, 19, 8, 53, 35)), ('main', 'hypeBTC'): (22517088, datetime.datetime(2025, 5, 19, 12, 44, 47)), ('main', 'hypeETH'): (22516836, datetime.datetime(2025, 5, 19, 11, 54, 11)), ('main', 'hypeUSD'): (22530554, datetime.datetime(2025, 5, 21, 10, 4, 23)), ('main', 'mAPOLLO'): (22924553, datetime.datetime(2025, 7, 15, 12, 22, 35)), ('main', 'mBASIS'): (20068373, datetime.datetime(2024, 6, 11, 11, 46, 11)), ('main', 'mBTC'): (20991269, datetime.datetime(2024, 10, 18, 8, 31, 47)), ('main', 'mEDGE'): (21665964, datetime.datetime(2025, 1, 20, 13, 20, 35)), ('main', 'mEVETH'): (25172925, datetime.datetime(2026, 5, 25, 14, 30, 23)), ('main', 'mEVUSD'): (23496808, datetime.datetime(2025, 10, 3, 10, 58, 35)), ('main', 'mFARM'): (23073881, datetime.datetime(2025, 8, 5, 9, 11, 11)), ('main', 'mFONE'): (22437927, datetime.datetime(2025, 5, 8, 9, 27, 23)), ('main', 'mHYPER'): (22924118, datetime.datetime(2025, 7, 15, 10, 55, 11)), ('main', 'mHyperBTC'): (23576630, datetime.datetime(2025, 10, 14, 14, 46, 59)), ('main', 'mHyperETH'): (23547132, datetime.datetime(2025, 10, 10, 11, 47, 59)), ('main', 'mKRalpha'): (24083710, datetime.datetime(2025, 12, 24, 16, 35, 35)), ('main', 'mLIQUIDITY'): (22466394, datetime.datetime(2025, 5, 12, 9, 43, 59)), ('main', 'mM1USD'): (24534309, datetime.datetime(2026, 2, 25, 13, 44, 35)), ('main', 'mMEV'): (21771599, datetime.datetime(2025, 2, 4, 7, 19, 11)), ('main', 'mPortofino'): (23675979, datetime.datetime(2025, 10, 28, 12, 40, 11)), ('main', 'mRE7'): (21786049, datetime.datetime(2025, 2, 6, 7, 44, 47)), ('main', 'mRE7BTC'): (23288661, datetime.datetime(2025, 9, 4, 8, 48, 59)), ('main', 'mROX'): (24425757, datetime.datetime(2026, 2, 10, 10, 24, 35)), ('main', 'mSL'): (22274978, datetime.datetime(2025, 4, 15, 14, 28, 23)), ('main', 'mTBILL'): (18691255, datetime.datetime(2023, 12, 1, 11, 25, 59)), ('main', 'mWIN'): (25236860, datetime.datetime(2026, 6, 3, 12, 27, 23)), ('main', 'mWildUSD'): (23432101, datetime.datetime(2025, 9, 24, 9, 48, 11)), ('main', 'mevBTC'): (22867636, datetime.datetime(2025, 7, 7, 13, 32, 47)), ('main', 'msyrupUSD'): (23232613, datetime.datetime(2025, 8, 27, 12, 59, 35)), ('main', 'msyrupUSDp'): (23339333, datetime.datetime(2025, 9, 11, 10, 50, 47)), ('main', 'qHVNUSD'): (25286287, datetime.datetime(2026, 6, 10, 9, 55, 35)), ('main', 'sGold'): (25338248, datetime.datetime(2026, 6, 17, 15, 45, 11)), ('main', 'stockMarketTRBasisTrade'): (25122809, datetime.datetime(2026, 5, 18, 14, 52, 35)), ('main', 'tBTC'): (22594563, datetime.datetime(2025, 5, 30, 9, 9, 23)), ('main', 'tETH'): (22594497, datetime.datetime(2025, 5, 30, 8, 55, 59)), ('main', 'tUSDe'): (22594324, datetime.datetime(2025, 5, 30, 8, 21, 11)), ('main', 'turtlePST'): (25387099, datetime.datetime(2026, 6, 24, 11, 12, 47)), ('main', 'zeroGBTCV'): (23274478, datetime.datetime(2025, 9, 2, 9, 18, 47)), ('main', 'zeroGETHV'): (23274171, datetime.datetime(2025, 9, 2, 8, 16, 47)), ('main', 'zeroGUSDV'): (23269210, datetime.datetime(2025, 9, 1, 15, 34, 35)), ('monad', 'mEDGE'): (41557850, datetime.datetime(2025, 12, 12, 13, 16, 35)), ('monad', 'mHYPER'): (48387891, datetime.datetime(2026, 1, 13, 6, 43, 5)), ('monad', 'mHyperBTC'): (61813077, datetime.datetime(2026, 3, 16, 13, 57, 2)), ('optimism', 'liquidRESERVE'): (149938537, datetime.datetime(2026, 4, 6, 11, 44, 11)), ('optimism', 'liquidRWA'): (152185362, datetime.datetime(2026, 5, 28, 11, 58, 21)), ('optimism', 'mRe7ETH'): (149716831, datetime.datetime(2026, 4, 1, 8, 33, 59)), ('optimism', 'weEUR'): (149935744, datetime.datetime(2026, 4, 6, 10, 11, 5)), ('plasma', 'mHYPER'): (2828525, datetime.datetime(2025, 10, 6, 13, 35, 7)), ('plasma', 'plUSD'): (2210548, datetime.datetime(2025, 9, 29, 9, 55, 30)), ('plasma', 'splUSD'): (2213033, datetime.datetime(2025, 9, 29, 10, 36, 55)), ('tac', 'mRE7'): (12121424, datetime.datetime(2026, 1, 8, 10, 29, 38)), ('tac', 'tacTON'): (6292451, datetime.datetime(2025, 9, 26, 11, 14, 55))}

Scanned deployment blocks for Midas products.

This table is maintained by live archive-node scans over the product token addresses, not by the upstream TypeScript registry. To refresh it, run:

source .local-test.env && UPDATE_REGISTRY=true poetry run python scripts/midas/scan-deployments.py

Keys are (Midas network key, product symbol) and values are (first bytecode block, first bytecode block timestamp). Timestamps are naive UTC datetimes.

MIDAS_REGISTRY_NON_PRODUCT_KEYS: Final[frozenset[str]] = frozenset({'accessControl', 'paymentTokens', 'timelock'})

Non-product registry sections.

MIDAS_REDEMPTION_VAULT_FIELDS: Final[tuple[str, ...]] = ('redemptionVault', 'redemptionVaultSwapper', 'redemptionVaultMToken', 'redemptionVaultUstb', 'redemptionVaultAave', 'redemptionVaultMorpho', 'redemptionVaultBuidl')

Redemption vault fields in preference order for scanner diagnostics.

MIDAS_CUSTOM_FEED_FIELDS: Final[tuple[str, ...]] = ('customFeed', 'customFeedGrowth', 'customFeedDv', 'customFeedRv')

Custom oracle fields in preference order for share price fallback reads.

MIDAS_DEPOSIT_VAULT_FIELDS: Final[tuple[str, ...]] = ('depositVault', 'depositVaultMToken', 'depositVaultUstb', 'depositVaultAave', 'depositVaultMorpho')

Deposit vault fields in preference order for scanner diagnostics.

MIDAS_PRODUCT_SCAN_EXCLUSIONS: Final[dict[tuple[str, str], str]] = {('base', 'mRE7'): 'dataFeed is deprecated and customFeed.latestRoundData() returns a zero answer'}

Products whose registry entries are intentionally not promoted to scanning.

These rows stay in MIDAS_ADDRESSES_PER_NETWORK, but the shared vault adapter cannot produce a reliable NAV/share from their current on-chain feeds. Re-check this list with:

source .local-test.env && DAYS=4 REQUIRE_ALL_SUCCESS=true poetry run python scripts/midas/scan-history.py
class MidasRegistryProduct

Bases: object

Scanner-friendly Midas product entry.

network: str

Midas Hardhat network key from the upstream registry.

chain_id: int

EVM chain id.

symbol: str

Midas product symbol, e.g. mTBILL.

token: Optional[str]

mToken address. None for incomplete or bridge-only entries.

data_feed: Optional[str]

Midas IDataFeed contract exposing getDataInBase18().

custom_feed: Optional[str]

Chainlink-compatible public product feed, when present.

deposit_vault: Optional[str]

Preferred deposit vault address, when present.

redemption_vault: Optional[str]

Preferred redemption vault address, when present.

first_seen_at_block: Optional[int]

First block where the product token bytecode exists, when scanned.

first_seen_at: Optional[datetime.datetime]

Timestamp of first_seen_at_block as naive UTC datetime, when scanned.

raw: dict[str, Any]

Raw product dictionary from MIDAS_ADDRESSES_PER_NETWORK.

property rpc_env_var: Optional[str]

Get the local JSON-RPC environment variable for this product chain.

property has_required_historical_contracts: bool

Can this product be read with the Midas historical datafeed scanner.

property has_required_adapter_data: bool

Can this product be promoted to the shared vault scanner adapter.

__init__(network, chain_id, symbol, token, data_feed, custom_feed, deposit_vault, redemption_vault, first_seen_at_block, first_seen_at, raw)
Parameters
Return type

None

iter_midas_registry_products(*, require_historical_contracts=False, require_adapter_data=False)

Iterate product-like entries from the Pythonised Midas registry.

Payment token and access-control sections are skipped. If require_historical_contracts is true, only entries with both token and dataFeed are yielded. These are the minimum contracts needed for historical share price and TVL reads. If require_adapter_data is true, deployment metadata is also required so the shared scanner can create a historical lead with a deterministic start block.

Parameters
  • require_historical_contracts (bool) – Filter to entries that can be sampled by the Midas datafeed scanner.

  • require_adapter_data (bool) – Filter to entries that can be exposed through eth_defi.midas.

Returns

Iterator of typed registry product entries.

Return type

collections.abc.Iterator[eth_defi.midas.registry.MidasRegistryProduct]

get_midas_registry_products_by_chain(*, require_historical_contracts=False, require_adapter_data=False)

Group Midas registry products by chain id.

Parameters
  • require_historical_contracts (bool) – Filter to products with both mToken and datafeed addresses.

  • require_adapter_data (bool) – Filter to products with token, datafeed and deployment metadata.

Returns

Mapping of chain id to products.

Return type

dict[int, list[eth_defi.midas.registry.MidasRegistryProduct]]