My Approach to Recording ETH Staking Rewards in Beancount - Two Tax Events, One Transaction

I’ve been staking ETH for almost two years now, and I want to share what I’ve learned about properly recording staking rewards in Beancount. Fair warning: this gets tax-complicated because a single staking reward actually creates two separate tax events. I learned this the hard way during my first tax season with staking income.

The Core Problem

When you receive a staking reward, the IRS sees it as:

  1. Ordinary income at the moment you gain “dominion and control” over the tokens (taxed at your income rate, 10-37%)
  2. A capital gain or loss when you eventually sell those tokens (taxed at 0-20% if held >1 year)

The fair market value (FMV) at the time you receive the reward becomes both your taxable income AND your cost basis for future capital gains calculations. This is per IRS Revenue Ruling 2023-14.

My Account Structure

Here’s how I set up my accounts:

; Staking-related accounts
2024-01-01 open Assets:Crypto:Staking:ETH       ETH
2024-01-01 open Income:Crypto:Staking:ETH       USD
2024-01-01 open Assets:Crypto:Wallet:ETH        ETH

; For tracking when I sell
2024-01-01 open Income:Crypto:CapitalGains:ETH  USD

Recording a Staking Reward

When I receive a staking reward, I record both the asset acquisition AND the income recognition:

2025-11-15 * "ETH Staking Reward - Validator Payout"
    Assets:Crypto:Staking:ETH    0.0032 ETH {2847.50 USD, 2025-11-15}
    Income:Crypto:Staking:ETH   -9.11 USD

Notice a few important things:

  • The {2847.50 USD, 2025-11-15} creates a specific lot with cost basis and acquisition date
  • The income amount (0.0032 ETH × $2,847.50 = $9.11) is what I’ll report on Schedule 1
  • Each reward gets its own lot, which is crucial for future capital gains tracking

Why Lot Tracking Matters

When I eventually sell staking rewards, Beancount’s lot tracking shines. Let’s say ETH goes to $4,000 and I sell some of my staking rewards:

2026-06-15 * "Sell staking rewards - held >1 year"
    Assets:Crypto:Staking:ETH   -0.0032 ETH {2847.50 USD, 2025-11-15}
    Assets:Bank:Checking         12.80 USD
    Income:Crypto:CapitalGains:ETH  -3.69 USD

Since I held for more than a year, this is a long-term capital gain of $3.69, taxed at the preferential 0-20% rate instead of ordinary income rates.

The Full Picture

So that single staking event results in:

  • 2025 taxes: $9.11 ordinary income (reported on Schedule 1)
  • 2026 taxes: $3.69 long-term capital gain (reported on Form 8949 and Schedule D)

Important 2025 Update

Starting in 2025, the IRS eliminated the “universal wallet method” - you can’t treat all your ETH across different wallets as one pool anymore. Each wallet/account needs separate cost basis tracking. Beancount’s natural structure actually handles this perfectly since we’re already tracking by specific accounts.

Questions for the Community

  1. How do you handle locked staking rewards (like during the pre-Merge ETH staking period)? I’ve been taking the position that locked rewards aren’t taxable until accessible, but I’d love to hear other approaches.

  2. What price sources do you use for FMV? I’ve been using CoinGecko’s API for daily close prices, but I’m curious what others prefer.

  3. Anyone have a good importer for pulling staking data automatically from various validators?

Would love to hear how others are handling this. The intersection of crypto and taxes is messy, but Beancount’s lot tracking has made it manageable for me.

This is an excellent breakdown, @finance_fred. As someone who helps clients navigate crypto taxes professionally, I want to add some important context.

Dominion and Control is Key

Your approach to locked staking rewards is actually aligned with current IRS guidance. Revenue Ruling 2023-14 establishes that you have taxable income when you have “dominion and control” - meaning you can freely sell, exchange, or otherwise dispose of the rewards.

For locked staking scenarios:

  • Pre-Merge ETH staking where rewards were locked? Not taxable until the Merge when they became accessible
  • Bonded staking with unlock periods? Taxable when the unbonding period ends and you can access
  • Auto-compounding protocols where rewards are immediately restaked? This gets murky - technically you may have had momentary control

I recommend documenting your reasoning for any position you take. The IRS has not provided explicit guidance on every scenario.

Watch for 1099-MISC Forms

Many exchanges now report staking rewards on Form 1099-MISC. If you receive one of these, the IRS definitely knows about that income. Make sure your Beancount records match what’s being reported to the IRS, or be prepared to explain discrepancies.

2025 Cost Basis Rules

The elimination of the “universal wallet method” you mentioned is significant. For clients who previously pooled their crypto across exchanges and wallets, this is a major change. The good news: if you’ve been using Beancount with separate accounts per wallet like you show, you’re already compliant.

Looking Ahead

There’s pending legislation (the Lummis Digital Asset Act) that would change staking taxation to only trigger at disposal, not receipt. If passed, this could significantly simplify things. But until then, we work with current rules.

Keep those records detailed - the audit trail Beancount provides is exactly what I recommend to clients.

Thanks for this detailed walkthrough, @finance_fred! As a software engineer just getting into tracking my crypto in Beancount, I have a few questions:

Fair Market Value Confusion

You mention using CoinGecko’s daily close price for FMV. But staking rewards can come in at any time of day. If I get a reward at 3am when ETH is at $2,900, but the daily close is $2,847.50, which should I use?

Is there a “good enough” standard here, or do I need to be pulling hourly/minute prices? My developer brain wants to over-engineer this with real-time API calls, but that feels like overkill.

Automation Questions

I’m staking on multiple validators (Lido, Rocket Pool, and a solo validator). Each has different reward structures and data export formats. Do you have any importers that work across platforms, or is everyone building their own?

I’m comfortable writing Python scripts - I’ve seen the magicbeans repo mentioned in other threads. Has anyone used it specifically for staking rewards, or is it more focused on trading?

Missing Rewards Anxiety

Here’s what keeps me up at night: how do I make sure I’m not missing any staking rewards? With solo validating especially, rewards come in as tiny attestation rewards throughout the day. Is there a reconciliation strategy to make sure my Beancount ledger matches what’s actually on-chain?

This feels like the financial equivalent of git - I want my local state to match the source of truth. Any tips on building that confidence?

Appreciate any guidance from the more experienced folks here!

Hey @newbie_accountant - great questions, and I remember having the exact same anxieties when I started tracking crypto. Let me share what I’ve learned:

On FMV Precision: Start Simple

Here’s my unpopular opinion: daily prices are fine for most people. Yes, technically the IRS says fair market value at time of receipt, but in practice:

  • The dollar difference between 3am spot price and daily close is usually minimal for small staking rewards
  • The IRS has never defined a required price source
  • Being consistent matters more than being perfect

I use CoinGecko’s daily close for everything. If you’re ever audited, you can demonstrate a consistent, reasonable methodology. That’s what matters.

That said, if you’re receiving large rewards and want precision, hourly data from CoinGecko’s API is free. But don’t over-engineer this on day one.

Automation Approach

For multi-platform staking, I actually started simple:

  1. Week 1: Manual entry for everything (painful but educational)
  2. Month 1: Simple Python script that pulls from one platform
  3. Month 3: Expanded to other platforms as I understood patterns

For Lido specifically, their subgraph API is pretty clean. Rocket Pool has good tooling too. Solo validators are trickier - I use beaconcha.in’s export feature.

The magicbeans project is excellent but it’s more focused on trading with exchange data. For staking, you’ll likely end up writing custom importers. Start with one platform and iterate.

Reconciliation Strategy

This is the “git pull” equivalent you’re looking for:

2026-01-28 balance Assets:Crypto:Staking:ETH    3.2847 ETH

Add balance assertions regularly! I do monthly “balance checks” where I:

  1. Export my actual on-chain balance
  2. Add a balance assertion to my ledger
  3. Let Beancount tell me if something’s off

If the assertion fails, you know you’re missing something. It’s exactly like running git status to see if your working tree is clean.

Don’t stress about perfection. Start tracking something, even imperfectly. You can always adjust your approach later.

@finance_fred, excellent methodology. From a professional CPA perspective, I want to emphasize a few points about audit readiness that will serve everyone well:

Documentation is Everything

The IRS doesn’t just want you to report the right numbers - they want to see how you got there. Beancount’s plain text format is genuinely advantageous here because:

  1. Every transaction is human-readable
  2. Git history (if you’re using it) shows exactly when entries were made
  3. The data can’t be retroactively modified without detection

I recommend linking source documents directly in your ledger:

2025-11-15 * "ETH Staking Reward" ^coinbase-staking-export-2025-11.csv
    Assets:Crypto:Staking:ETH    0.0032 ETH {2847.50 USD, 2025-11-15}
    Income:Crypto:Staking:ETH   -9.11 USD

The ^ link to source documents makes audit responses much easier.

Specific Identification Saves Money

The approach @finance_fred showed using lot notation ({2847.50 USD, 2025-11-15}) enables the specific identification method. This is crucial for tax optimization because it lets you choose which lots to sell.

Want to minimize gains? Sell your highest cost-basis lots.
Want to realize losses for tax-loss harvesting? Sell your lowest cost-basis lots.

Just document your method and be consistent. The IRS accepts specific identification for crypto as long as you can prove which units you sold.

Don’t Forget Quarterly Estimates

If your staking rewards are substantial, remember you may owe quarterly estimated taxes. The IRS expects you to pay as you earn - not just at year end.

Receiving $10,000+ in annual staking income? You should probably be making quarterly payments to avoid underpayment penalties.

Form 8949 Considerations

When you eventually sell staking rewards, each lot becomes a line item (or gets aggregated if you have many). Keep this in mind - 500 tiny staking reward lots sold in one transaction can become 500 8949 lines unless you’re using summary reporting procedures.

This is another reason I prefer weekly or monthly aggregated reward entries over daily ones for clients with high-volume staking.