# EVM Portfolio API: A Complete Guide

> Reading an EVM wallet means every chain it has touched, not just Ethereum — plus the receipt tokens, NFT positions and proxies that break naive decoding.

- **URL:** https://octav.fi/blog/evm-portfolio-api-guide
- **Published:** 2026-08-19
- **Author:** Octav Team — Portfolio Intelligence for Digital Assets
- **Topic:** Chains
- **Tags:** api, developers, defi
- **Source:** Octav, Practical guides on crypto NAV reporting, multi-chain portfolio management and digital asset APIs, from the team behind Octav.

---
<LogoRow items="ethereum,base,bnb,optimism,arbitrum,uniswap,aave,weth" caption="Chains and protocols in this guide" />

"EVM support" sounds like one feature. It is not — it is the same integration
problem repeated on every chain a wallet has ever touched, and the count is
higher than most teams assume.

A single portfolio request for `vitalik.eth` returns value on **44 EVM chains**,
out of 66 the response enumerates. Ethereum holds 93.2% of it. The other 43
chains hold $77,714 — the part a report either includes or silently loses.

![Bar chart of the non-Ethereum EVM chains holding value for one address: Base $35,469, BNB Chain $25,490, Optimism $8,607, Manta $4,483, and a long tail down to X Layer at $145](./images/figure-evm-chain-tail.png)

Ethereum is left off that chart on purpose. At linear scale it flattens
everything else to nothing — which is exactly the mistake the chart is arguing
against.

## Why EVM is not one problem

Solana is one chain with hard-to-decode programs. EVM is the opposite: the
decoding is well understood, and the difficulty is that you have to do it
everywhere, forever.

| | Solana | EVM |
| --- | --- | --- |
| Chains to index | 1 | Dozens, and rising |
| Same protocol, many deployments | Rare | Normal — Aave and Uniswap run on most L2s |
| Contract addresses | Stable per program | Different on every chain |
| New surface area | New programs | New chains *and* new protocols |

The multiplication is the whole story. Supporting Aave is one integration.
Supporting Aave *across chains* is one integration re-verified on every chain it
deploys to, because the addresses differ and the deployments drift.

Here is what that looks like in a real response — the same protocol, one wallet,
two chains, five separate positions:

| Chain | Protocol | Position |
| --- | --- | --- |
| Base | Uniswap V3 | DOGE / WETH |
| Base | Uniswap V3 | NMB404 / WETH |
| Ethereum | Uniswap V3 | DGENV2 / WETH |
| Ethereum | Uniswap V3 | BARK / WETH |
| Ethereum | Uniswap V3 | MIERDA / WETH |

An API that indexes Ethereum and calls it "Uniswap support" returns three of
those five.

## What actually sits in an EVM wallet

Four position types, only one of which a balance query returns correctly:

| Type | What it looks like on-chain | Naive result |
| --- | --- | --- |
| Spot tokens | ERC-20 balance | Correct |
| Lending | Receipt token (`aToken`) + debt token | Debt counted as an asset |
| Liquidity | ERC-721 NFT (Uniswap V3) or LP ERC-20 | Missing, or valued at face |
| Vaults / staking | Share token whose price drifts from 1:1 | Undervalued |

The lending case is the one that inverts meaning rather than nudging a number.
A wallet supplying 6,586 WETH against 2,294,767 USDC of borrow holds a net
position near $10.3M — but summing the tokens it *holds* adds the debt as a
positive and reports something closer to $12.6M. The mechanics are in
[Tracking Aave Positions](/tracking-aave-positions).

## The four things that break EVM decoding

**Receipt tokens look like ordinary ERC-20s.** `aUSDC`, `cDAI`, `stETH` and
thousands of vault shares are transferable tokens with a balance and a symbol.
Treat them as spot holdings and you double-count the underlying.

**Liquidity is often not a token at all.** A Uniswap V3 position is an NFT whose
contents depend on the pool's current tick. There is no balance to read — the
amounts have to be derived. See
[Valuing Uniswap V3 Positions](/valuing-uniswap-v3-positions).

**Proxies hide the implementation.** Most major EVM protocols sit behind
upgradeable proxies, so the address you integrated against is not the logic you
decoded. Upgrades change response shapes without changing addresses.

**The same symbol is not the same asset.** `USDC` on Ethereum, bridged `USDC.e`
on an L2 and a third-party bridge wrapper are different assets with different
risk. Collapsing them by symbol produces a tidy, wrong total.

## Querying every chain in one request

The practical requirement is that chain count stops being your problem. One
address in, every chain out:

```bash
curl -s https://api.octav.fi/v1/portfolio \
  -H "Authorization: Bearer $OCTAV_API_KEY" \
  -G --data-urlencode "addresses=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
```

Positions come back grouped by protocol, then chain, so per-chain exposure is a
read rather than a reconciliation. Batching several addresses into one request
is also the main cost lever — the full parameter and credit table is in the
[endpoint reference](/crypto-portfolio-api-endpoint-reference).

If you would rather not hold a key at all while evaluating,
[Authless](/octav-authless-no-api-key) answers the same question for any EVM
address with no account.

## How to evaluate an EVM provider

Run these against a wallet whose contents you can verify independently. Each one
fails a different class of provider:

1. **Query an address with activity on an L2 you rarely think about.** Does the
   position appear at all? This is chain coverage, and it is where most of the
   variance lives.
2. **Query a wallet with an open lending borrow.** Is the debt negative in the
   total, or added to it?
3. **Query a wallet with a Uniswap V3 position.** Is it present, and are both
   sides of the pair itemised?
4. **Check a vault or staked position.** Is it valued at the share price or at
   1:1?
5. **Ask what happens on an unsupported protocol.** "Omitted silently" and
   "flagged as unsupported" are very different products.

Question 1 is the one to weight. Decoding gaps are visible once you look;
missing chains are invisible by construction, because nothing in the response
says a chain was never checked.

Measured results across nine providers, including where competitors beat us, are
in [the benchmark](/crypto-portfolio-api-benchmark) — and the mechanism behind
the disagreements is in
[Why Portfolio APIs Disagree](/why-portfolio-apis-disagree).

## Where to go next

| If you want | Go to |
| --- | --- |
| The general shape, not EVM-specific | [Crypto portfolio API guide](/crypto-portfolio-api-guide) |
| The Solana equivalent of this page | [Solana portfolio API guide](/solana-portfolio-api-guide) |
| Every endpoint and credit cost | [Endpoint reference](/crypto-portfolio-api-endpoint-reference) |
| To evaluate providers properly | [How to choose a crypto portfolio API](/choosing-a-crypto-portfolio-api) |
| A working dashboard on this data | [Build a portfolio dashboard](/build-crypto-portfolio-dashboard) |
| An AI agent to consume it | [AI agent tools for portfolio data](/ai-agent-tools-crypto-data) |

The multi-chain problem in the abstract — why enumeration is the hard part — is
covered in
[Tracking DeFi Positions Across Multiple Chains](/track-defi-positions-multichain).
