How every number here is made
If you cannot check a tax figure, it is worth nothing. This page is the whole method, including the parts that are inconvenient.
Prices
The token side
A Pons trade carries its own price. CurveBuy emits the ETH paid and the tokens received;
CurveSell emits the tokens sold and the ETH received. The price is the quotient, and it is the price
that actually executed — not a daily average, not an index, not an oracle. Every disposal in a report links to the
transaction that produced its price.
For an operation with no trade of its own — an airdrop, a transfer from a friend — the price is taken from the nearest trade on that token's curve, and the report says how far away it was. Beyond seven days, the price is reported as unknown instead.
The dollar side
USD per ETH is the close of the Coinbase Exchange ETH-USD hourly candle containing the timestamp
(api.exchange.coinbase.com/products/ETH-USD/candles?granularity=3600). If Coinbase is unreachable, the
same hour from Kraken's XETHZUSD is used and the row is labelled with which source it came from.
Candles are cached, so an outage at either exchange cannot change a report that was already built.
Why not read the price from the chain
Robinhood Chain prunes historical state after roughly 1 000 to 10 000 blocks. An eth_call against the
block of an old trade fails outright — there is no past price to read. Logs, on the other hand, are kept forever.
That is why this service is built on events rather than on state.
Accounting rules
- ETH is an asset. Spending ETH to buy a token is a disposal of ETH with its own gain or loss. Reports that track only tokens get the year wrong.
- Fees ride with the trade. Pons' protocol fee and snipe tax and the network gas are added to the cost of a purchase and subtracted from the proceeds of a sale. The ETH consumed by gas leaves its lots at its own basis so it is never counted twice.
- A move between your own addresses is not a disposal. The lots carry across with their original cost and acquisition date — which is what decides long against short term. This only works if you enter all your addresses together.
- An unpriced acquisition is recorded as unpriced. Not as free. Booking cost zero would maximise your taxable gain, and doing that silently would be the worst thing this service could do to you.
- Selling more than we saw you acquire is reported. It means an address is missing, and the report says so on the row rather than inventing a basis.
What this cannot see
| Blind spot | Why | What the report does |
|---|---|---|
| ETH moved by an internal call | No trace_* or debug_* on the RPC; the explorer has no internal-transaction endpoint | Flags the operation for manual classification |
| Proceeds of a Uniswap v4 sale | In v4 the swap's sender is a router, and the ETH arrives internally | Shows the token leg, marks the row review |
| Very large wallets | Paging hundreds of thousands of rows would exceed a request | Stops, says how many were found, asks you to narrow the range |
| Your jurisdiction | Nobody's software knows it from an address | Gives you the arithmetic and the evidence; the filing is yours |
Reclassifying a row
Our label is a reading of what the chain shows. Yours wins. Press edit on any row, choose a classification and sign the change with the address it belongs to. The signature is proof of ownership, it moves nothing, and it costs no gas. Overridden rows are printed in pen-blue everywhere they appear, including the exports, so an accountant can see which decisions were yours.