ERC-4626: current APY of a vault

Here is a Python example how to estimate the ERC-4626 APY.

  • Reads the most recent APY of given ERC-4626 vault

  • The APY is calculated using the price difference of the vault share token

  • Only uses EVM JSON-RPC and archive node, no external services needed. Public RPC nodes won’t work, because they are not archive nodes. Get your Base node JSON-RPC access from dRPC or Ethereumnodes.com.

  • Supported vaults include all ERC-4626, including but not limited to: Morpho, Euler, Lagoon Finance, Superform, IPOR, Yearn, Fluid

Then to run this script:

# Get JSON-RPC archive node
export JSON_RPC_BASE=...
python scripts/erc-4626/read-live-apy.py

Output looks like:

Vault: IPOR USDC Lending Optimizer Base (0x45aa96f0b3188d47a1dafdbefce1db6b37f58216)
Estimated APY: 5.53%
Period: 2025-05-19 11:08:31 - 2025-05-26 11:08:31
Block range: 30,431,782 - 30,734,182
Share price at begin: 1.042212618930521299088288235 ipUSDCfusion / USDC
Share price at end: 1.043318675169052799414866657 ipUSDCfusion / USDC
Share price diff: 0.001106056238531500326578422 ipUSDCfusion / USDC

Further reading

"""An example script to estimate the live APY of an ERC-4626 vault.

- Archive JSON-RPC node needed, public endpoint may not work.

To run:

.. code-block:: shell

    python scripts/erc-4626/read-live-apy.py
"""

import os
import datetime

from eth_defi.chain import get_chain_name
from eth_defi.erc_4626.classification import create_vault_instance
from eth_defi.erc_4626.profit_and_loss import estimate_4626_recent_profitability
from eth_defi.provider.multi_provider import create_multi_provider_web3


def main():
    JSON_RPC_BASE = os.environ.get("JSON_RPC_BASE")
    assert JSON_RPC_BASE, "Please set JSON_RPC_BASE environment variable to your JSON-RPC endpoint."

    web3 = create_multi_provider_web3(JSON_RPC_BASE)
    chain_id = web3.eth.chain_id

    assert chain_id == 8453, "This script is designed to run on Base chain (chain ID 8453)."

    # IPOR USDC Base
    # Lending Optimizer
    # https://app.ipor.io/fusion/base/0x45aa96f0b3188d47a1dafdbefce1db6b37f58216
    vault_address = "0x45aa96f0b3188d47a1dafdbefce1db6b37f58216"
    vault = create_vault_instance(web3, vault_address)

    profitability_data = estimate_4626_recent_profitability(vault, lookback_window=datetime.timedelta(days=7))

    estimated_apy = profitability_data.calculate_profitability(annualise=True)
    start_block, end_block = profitability_data.get_block_range()
    start_at, end_at = profitability_data.get_time_range()
    start_price, end_price = profitability_data.get_share_price_range()
    diff = end_price - start_price

    print(f"Vault: {vault.name} ({vault_address})")
    print(f"Chain: {get_chain_name(chain_id)}")
    print(f"Estimated APY: {estimated_apy:.2%}")
    print(f"Period: {start_at} - {end_at} ({(end_at - start_at).days} days)")
    print(f"Block range: {start_block:,} - {end_block:,}")
    print(f"Share price at begin: {start_price} {vault.share_token.symbol} / {vault.denomination_token.symbol}")
    print(f"Share price at end: {end_price} {vault.share_token.symbol} / {vault.denomination_token.symbol}")
    print(f"Share price diff: {diff} {vault.share_token.symbol} / {vault.denomination_token.symbol}")


if __name__ == "__main__":
    main()