Most articles about phantom gains, including ours, explain the mechanism and stop there. This one runs it on a real wallet cluster and publishes the number.

We took the most public address cluster on Ethereum — vitalik.eth plus the Etherscan-tagged VB, Vb 2 and Vb 3 addresses and one media-documented cold wallet — and computed realized gains on its native-ETH history twice. Same engine, same data, same classifications. The only difference between the two runs: whether transfers between the entity's own wallets carry their cost basis, or lose it.

Losing it is what per-wallet tools do when they don't link the wallets together. On this cluster it overstates lifetime realized gains by $44,975,739.

realized gain (genesis → 2023-03-31)
naive per-wallet tool (transfers lose basis) $164,130,459
transfer-aware $119,154,719
overstated "phantom" gain $44,975,739

To be explicit about what this is and isn't: this is a measurement of how two ways of handling self-transfers diverge on one public dataset. It is not a claim about anyone's actual tax position, filings, or liability. We have no visibility into either. Every address here is identified by an on-chain ENS name, an Etherscan public name tag, or mainstream press coverage — there is nothing here that wasn't already public. This is not tax advice.

Why this cluster

We needed a subject that does the specific things that break naive tools, and that we could name without exposing anyone.

This cluster does all of them: multi-hop self-transfers (VB → vitalik.eth, VB → Safe → cold wallet), self-staking, WETH wraps, and large disposals years after the transferred coins were acquired. The five addresses:

address label how it's attributed
0xd8da6bf2…96045 vitalik.eth ENS name, on-chain
0xab5801a7…aec9b VB (legacy) Etherscan public name tag
0x1db3439a…a6ee6 Vb 2 Etherscan public name tag
0x220866b1…a3a9d Vb 3 (Safe) Etherscan public name tag
0xd04daa65…28fd7 cold wallet received 70,000 ETH from Vb 3 after a 1-ETH test send; widely reported

The moves that a per-wallet tool books at $0 basis on arrival are large and old:

date from to amount transaction
2021-05-12 VB (legacy) Vb 3 (Safe) 320,000 ETH 0x422026…f11b0
2016-08-05 VB (legacy) Vb 2 100,000 ETH 0x5ec109…39edf
2016-08-10 Vb 2 VB (legacy) 79,462.66 ETH 0xd59d4c…b85df
2022-11-24 Vb 3 (Safe) cold wallet 40,000 ETH 0xe467d3…e04ae
2022-05-16 Vb 3 (Safe) cold wallet 30,000 ETH 0x2909ee…4320f

Every move links to the transaction on Etherscan — the same evidence standard the scan holds itself to, one tx-hash per line. The two 2022 moves to the cold wallet are internal transfers executed by the Vb 3 Gnosis Safe, so the top-level transaction shows 0 ETH and the amount rides in the internal call the Safe made; Etherscan's "Internal Txns" tab on each shows the transfer. Coins acquired in 2015 and moved in 2016 get sold in 2021. A tool that lost the basis at the 2016 transfer prices that 2021 sale against zero.

The damage concentrates in two years

year naive transfer-aware overstatement
2015 −$656 −$657 $1
2016 $5,216,955 $5,065,243 $151,711
2017 $38,034,500 $37,728,650 $305,849
2018 $3,932,439 $3,793,849 $138,590
2019 $1,636,279 $1,533,193 $103,085
2020 $2,734,481 $2,627,965 $106,516
2021 $55,404,397 $32,238,166 $23,166,232
2022 $31,336,181 $10,476,703 $20,859,478
2023 $25,835,884 $25,691,607 $144,277

A note for anyone adding these up — please do: every dollar figure on this page is rounded to the nearest dollar independently, and the overstatement column is the exact difference rounded once, not the subtraction of the two rounded cells. So recomputing any rounded figure from other rounded figures can land within $1 of the printed value. The underlying ledger is exact; the per-year rows, the lifetime totals and the overstatement are all cuts of the same unrounded per-disposal list, and they reconcile to the cent before display rounding.

2022 is the clearest case. The naive run reports $31.3M of realized gains. Carry the basis correctly across the entity's own transfers and the same disposals come out at $10.5M.

Look at what happens at the level of individual disposals, and the sign flips:

date transaction naive gain actual gain phantom
2021-12-14 0xad231f…385a6 $7,565,791 −$799,790 $8,365,581
2021-09-26 0x404b80…fc99b $4,413,005 −$1,860,762 $6,273,767
2021-07-01 0xce25ec…ffb8c $2,279,354 −$1,903,436 $4,182,790
2022-01-09 0x9d931b…ce7c6 $2,318,839 −$818,254 $3,137,093

Each row links to the disposal itself on Etherscan: 2,000, 1,499.9, 1,000 and 750 ETH sent out of vitalik.eth. The chain will show you the transaction; the two gain figures are what the same transaction looks like depending on whether the coins it spends kept the basis they arrived with.

These are losses being reported as multi-million-dollar gains. That is the part worth sitting with: the error isn't a percentage off a large number, it's the wrong direction.

Why you can trust the arithmetic

A number this size is only worth anything if the ledger reconciles to the chain. Here is the balance tie-out at the cutoff block (16,950,600), with gas priced from each transaction's own receipt:

wallet ledger (ETH) on-chain (ETH) diff tie-out
vitalik.eth 5149.62524 5149.62524 0 PASS
VB (legacy) 59.41928 59.41928 0 PASS
Vb 2 7.904313 7.904313 0 PASS
Vb 3 (Safe) 244001.011354 244001.011354 0 PASS
cold wallet 50001.094312 50001.094312 0 PASS

Five of five wallets reconcile within 0.0001 ETH. The cutoff is deliberately before Shapella withdrawals began, so the native-ETH ledger is closed under transaction lists plus proposer fees — any residual would be a data defect, not an excuse.

The method, in short: 5,334 raw rows from the key-less Blockscout public API became 6,175 canonical events. Every one of the 2,671 transaction receipts was read for exact gas (gasUsed × effectiveGasPrice). Prices are DefiLlama daily closes. Validator deposits and WETH wraps are not sales. Safe delegatecall traces are dropped, because Blockscout reports them with the parent call's value and any pipeline that keeps them double-counts every Safe execution.

Two defects we found in our own pipeline

Both were producing an "ETH from nowhere" signature, and both invalidated every figure this analysis carried before 2026-07-29. We are publishing them because a tie-out that only ever passes is a tie-out nobody is testing.

Gas came from the explorer's indexed fields. Neither gasUsed nor gasPrice as indexed is the receipt value — gasPrice is maxFeePerGas under EIP-1559. Fees are modeled as mini-disposals, so a wrong fee is a wrong realized gain as well as a broken tie-out. Fixing it moved vitalik.eth from −0.685055 ETH to exactly zero.

Proposer income was cached as zero when the fetch failed. 270 of Vb 2's 627 proposed blocks were stored with a zero priority fee and a null timestamp, because rate-limited responses were read optimistically. They are real income: 4.29 ETH recorded against 7.16 ETH on chain. Repaired, Vb 2's difference fell from −3.04 ETH to −0.18 ETH.

What remains is contract-internal ETH that block explorers don't index per address. We bisected it to the block: VB (legacy) first diverges at block 13,787,699, where the on-chain balance rises by 0.0085 ETH with no transaction and no internal transaction returned for that address. Closing it needs trace-level ingestion — and one caveat we measured while testing that: trace_filter returns frames from reverted sub-calls, and counting them naively over-credited VB by 0.067 ETH. Trace ingestion has to prune every subtree under a reverted ancestor before it's an improvement.

What this means for a normal wallet

You almost certainly don't move 320,000 ETH between your own addresses. But the mechanism doesn't care about size, and two things make it more likely to hit you now than it used to:

Since 2025, Rev. Proc. 2024-28 requires per-wallet basis tracking rather than a universal pool. Per-wallet is exactly the mode in which an unlinked self-transfer looks like an acquisition at zero.

And Form 1099-DA reporting means brokers now send the IRS their own view of your disposals. Where a broker never saw your acquisition — because it happened in a wallet, on another exchange, or years earlier — the basis field is where the gap shows up.

The check is the same at any size: for each sale in your report, find the acquisition it was matched against. If the tool can't show you one, that line is priced against zero.

Reproduce this yourself

The point of naming every source is that you don't have to take the number on faith. Everything this pipeline reads is public and key-less.

The addresses, in full:

The cutoff: block 16,950,600 (2023-03-31T23:59:35Z) — deliberately before Shapella withdrawals, so transaction lists plus proposer fees close the native-ETH ledger.

The data: transaction lists, internal transactions and proposed blocks from the key-less Blockscout public API (eth.blockscout.com); gas from each transaction's own receipt (gasUsed × effectiveGasPrice) over public JSON-RPC; contract-internal ETH from trace_filter, pruning every subtree under a reverted frame; ETH/USD from DefiLlama daily closes.

The rules: run the same cost-basis engine twice on identical events — once with transfers between the five addresses carrying their basis, once with basis lost on transfer. Validator deposits and WETH wraps are not sales. Safe delegatecall traces are dropped, because the explorer reports them with the parent call's value.

The check that keeps you honest: rebuild each wallet's balance at block 16,950,600 from your ingested events and compare it to eth_getBalance at that block. If any wallet is off by more than 0.0001 ETH, your data is missing something — that one gate is what caught both of the defects above in our own pipeline. Don't publish a dollar figure until it passes.

If what you actually want to audit is your own wallet rather than Vitalik's, the free scan runs this same engine and this same balance tie-out gate on the addresses you paste — read-only, up to 5 wallets and 500 events. It won't replay this cluster (6,175 events is well past the free cap); it applies the method described here to yours.


This is not tax advice, and none of the above is a substitute for a qualified tax professional looking at your actual records.

If you'd rather have the breaks in your basis chain found for you, Verilot Check reads your wallets directly on-chain and flags every transfer between your own addresses that would otherwise be booked as a sale, with a tx-hash on every line. Free and read-only — no wallet connection, no sign-up, up to 5 wallets and 500 events per scan, on Ethereum mainnet, Base or Arbitrum One (one chain per scan). Run my free scan.