Every year, hundreds of thousands of tech employees sell ESPP shares, get a 1099-B from their broker showing the cost basis, file their taxes using TurboTax or H&R Block, and accidentally pay tax twice on the discount portion of their stock purchase. The reason is structural: the cost basis your broker reports on the 1099-B is, by IRS rule, intentionally wrong for ESPP shares. The correct basis lives on a separate document called a "supplemental statement" that broker websites bury behind two clicks and three tabs. If you don't manually adjust on Form 8949, you're filing wrong — and the over-payment can be five figures for a single sale.
This is one of the most-googled tax questions in tech compensation, and the existing content for it is mostly TurboTax help articles that say "be sure to enter the adjusted basis" without showing what the adjustment is or how to compute it. This post walks through the full thing with real numbers: what your 1099-B shows, what your supplemental statement adds, the dual-basis adjustment in concrete dollars, the qualifying-vs-disqualifying disposition rules, and the three traps that catch operators every April.
None of this is tax advice. We are software, not a CPA. Verify against your own situation and your accountant before filing. With that disclaimer landed, let's do the math.
The setup: how an ESPP works mechanically
An Employee Stock Purchase Plan (qualified ESPP under IRC §423) lets you buy your employer's stock at a discount through payroll deduction. The mechanics most plans use:
- Offering period typically 6 months. You enroll, payroll deductions accumulate, on the purchase date the accumulated cash is converted to stock.
- Discount typically 15% off the lower of (a) the price at the start of the offering period, (b) the price at the end of the offering period. This is the "lookback" feature — the most generous version of an ESPP.
- Hold period you can sell immediately or hold. Whether you held matters more than most people realize, which we'll get to.
For the worked example, we'll use these numbers throughout:
Offering period end: Jun 30, 2024 (purchase date)
Stock price Jan 1: $100.00 / share
Stock price Jun 30: $140.00 / share
Lookback / Discount: 15% off the lower of two prices
Discount price: $100 × 0.85 = $85.00 / share
Shares purchased: 100 shares
Cash you paid: 100 × $85 = $8,500
Fair market value at purchase: 100 × $140 = $14,000
Discount amount: $14,000 - $8,500 = $5,500
The "discount amount" — $5,500 — is the bargain element. It's where everything that follows turns. The IRS treats this $5,500 as ordinary income (not capital gain) and it shows up in Box 1 of your W-2 in the year of sale (or the year of purchase, depending on disposition rules — more on this in a moment). The fact that it ends up in W-2 Box 1 is the source of the double-taxation trap, because the broker doesn't know what's in your W-2, so the broker can't reflect this when they compute basis on the 1099-B.
The dual-basis problem in plain English
You sell the 100 shares at $160/share for $16,000 in proceeds. Your true cost basis is the $8,500 you paid plus the $5,500 of discount that's already been treated as ordinary income on your W-2 — total $14,000. That's because you've already paid ordinary-income tax on the $5,500 discount; if it weren't added to basis, you'd pay capital-gains tax on it again. Hence "dual basis": the basis the broker reports vs the basis the IRS expects you to report.
Cash you actually paid: $8,500 (the discounted purchase price)
Discount already in W-2 Box 1: $5,500 (taxed as ordinary income)
Broker-reported basis (1099-B): $8,500 ← intentionally wrong
Correct basis for your tax return: $14,000 ← cash + W-2 inclusion
Reported "gain" if you trust 1099-B: $16,000 - $8,500 = $7,500
Actual gain to report: $16,000 - $14,000 = $2,000
If you don't make the adjustment, you'd report a $7,500 gain instead of the correct $2,000 gain. At a 20% combined federal-plus-state long-term capital-gains rate, that's $1,100 of unnecessary tax on this single sale. Multiply by years of ESPP participation, by hundreds of shares per offering, and the cumulative over-payment can easily clear $10K. This is the exact thing that gets caught by Tax Brain, by competent CPAs, and by nobody else.
Where to find the corrected basis
Your broker generates a separate document — usually called a supplemental statement or stock plan transactions supplement — that shows the adjustment per lot. The location depends on the broker:
- E*TRADE / Morgan Stanley at Work — Tax Documents → "Supplemental Form 1099-B" or "Stock Plan Transactions Supplement." Often a separate PDF from the standard 1099-B, posted at the same time.
- Fidelity NetBenefits — Tax Information → Supplemental Stock Plan Lot Detail. Sometimes split between regular Fidelity and the NetBenefits side.
- Schwab / Charles Schwab Equity Award Center — Documents → Stock Plan Supplemental Information. Look for "Adjusted cost basis."
- Computershare — Tax Forms → 3922 (purchase year) and the supplemental statement. Computershare's supplemental usually requires logging into the participant portal, not just downloading the standard 1099-B.
The supplemental statement shows, per lot: the share count, the actual purchase price (what you paid), the FMV at purchase, the discount (W-2 inclusion amount), and the adjusted basis — which is what you actually report on Form 8949. Confirm the adjusted basis equals (cash paid + W-2 discount), and that the W-2 discount matches the equity-comp portion in your W-2 Box 1.
Qualifying vs disqualifying disposition
The 1099-B / supplemental adjustment is the same in either case. What differs is how much of the gain ends up as ordinary income vs capital gain — which can be a five-figure difference on a meaningful sale.
The IRS distinguishes two cases:
- Qualifying disposition — you held the shares at least 2 years from the offering-period start date AND at least 1 year from the purchase date. (Both requirements; not "or.")
- Disqualifying disposition — you didn't meet both holding-period requirements above. Most "sell immediately" ESPP participations are disqualifying.
The tax math splits as follows:
Disqualifying disposition (the common case)
Ordinary income (W-2 inclusion) = FMV at purchase − purchase price. Everything beyond that is capital gain.
Purchase price: $8,500
Ordinary income (W-2): $5,500
Sale proceeds: $16,000
Adjusted basis: $14,000
Capital gain: $2,000 (short or long-term depending on hold from purchase)
Qualifying disposition (rarer; usually intentional)
Ordinary income (W-2 inclusion) = the lesser of: (a) the discount on the offering-period-start price, or (b) the actual gain on sale. The capital-gain portion is everything beyond ordinary income — and importantly, it gets long-term capital-gain treatment because by definition you've held more than 1 year.
Actual gain (sale - cash paid): $16,000 - $8,500 = $7,500
Lesser of the two = ordinary inc: $1,500
Adjusted basis (purchase + W-2): $8,500 + $1,500 = $10,000
Capital gain (LT, qualifying): $16,000 - $10,000 = $6,000
Compare the two: in the disqualifying case, $5,500 was ordinary income and only $2,000 was capital gain. In the qualifying case, only $1,500 is ordinary income and $6,000 is long-term capital gain. At a 35% federal marginal rate vs a 15% LTCG rate, that swap of $4,000 from ordinary to LTCG is worth $800 in federal tax savings on a single sale of 100 shares — and most operators in the tech-comp band have far more than 100 shares accumulated over multiple offering periods.
The three traps
Trap 1: Filing without the supplemental adjustment
The big one. You import the 1099-B into TurboTax, it shows "Cost basis: $8,500," you click through, you've just paid tax on $7,500 of fake gain. The fix is in TurboTax's "guide me through" flow: after the 1099-B import, there's a question that asks "is this employer stock from ESPP, RSU, NQSO, or ISO." Answering yes triggers a separate flow that asks for the W-2 inclusion amount. That field is what unlocks the basis adjustment.
The reason this trap is so common: if you skip that question or if the import flow forgets to ask, the return files cleanly with the wrong basis, and there's no error message — the IRS happily collects the over-payment.
Trap 2: Multiple lots, partial sale, FIFO surprises
If you've participated in ESPP for several offering periods and you sell some-but-not-all of the shares, the broker reports lot-by-lot. Each lot has its own purchase price, its own FMV-at-purchase, its own W-2 inclusion. The "cash you paid" varies per lot — earlier offering periods may have had different stock prices. The basis adjustment differs per lot. You can't apply one adjustment to the whole sale.
Most brokers' supplemental statements show the lots correctly, but most tax-software import flows treat the sale as one bulk line. If you're selling partial lots, the safe pattern is to override the import — enter each lot manually on Form 8949 with its own (proceeds, adjusted basis, holding period). It's tedious. It's also the only way to get the math right when offering periods straddle a price-volatility window.
Trap 3: Wash-sale interaction with ESPP purchases
This one is the operator killer. You sell ESPP shares at a loss in December (rare but happens — concentrated stock declined). You then participate in the next offering period, which buys you new ESPP shares within 30 days of your loss sale. The IRS considers ESPP-purchased shares to be "substantially identical" to the shares you sold at a loss. Your December loss is disallowed under IRC §1091 wash-sale rules, and the disallowed amount is added to the basis of the new ESPP lot.
This interacts badly with the basis-adjustment math because now your "adjusted basis" has two layers of adjustment: the W-2 inclusion and the wash-sale add-on. Tax software handles each layer in isolation but rarely catches both together. We wrote a whole pillar on the cross-account wash-sale problem; this ESPP case is its equity-comp variant.
What your tax software actually does
TurboTax, H&R Block, FreeTaxUSA, and TaxAct all have ESPP-specific flows. They mostly work, with caveats:
- TurboTax Premier / Self-Employed handles the basis adjustment well if you complete the "guide me" flow and have your supplemental statement open. The plain-import flow without going through the guided ESPP wizard does NOT make the adjustment.
- H&R Block Premium has a similar wizard. Its UI for entering W-2 inclusion per lot is clunky compared to TurboTax's, in our reading.
- FreeTaxUSA supports the adjustment but requires you to manually enter the supplemental data — it doesn't import a separate document.
- TaxAct handles it but the flow is buried; many users miss the question.
The pattern: the software can get this right, but only if you actively engage with the ESPP-specific question. The default import-and-go path silently produces a wrong return.
The 4-step pre-file checklist
Before you submit your return, run this checklist on every ESPP lot you sold during the tax year:
- Pull the supplemental statement from your broker. Don't trust just the 1099-B. Confirm the adjusted basis per lot is shown and equals (cash paid + W-2 inclusion).
- Cross-check the W-2 inclusion against your W-2 Box 1. The discount amount on the supplemental should match (or partially compose) the equity-comp portion of your W-2. If they don't tie out, your employer's payroll provider may have under-reported, and your supplemental's adjustment will overstate basis.
- For each lot sold, override the imported basis on Form 8949 with the adjusted basis. Either via the tax-software wizard or by manual entry. Confirm the resulting capital gain on the form is reasonable (not a five-figure phantom gain).
- Check for wash-sale interactions with your ESPP enrollment schedule. If you had any ESPP loss sale within 30 days before or after a scheduled ESPP purchase, the wash-sale disallowance applies. Adjust accordingly.
Where HELM fits in this workflow
HELM's Tax Brain is built specifically for the cross-instrument, cross-account, cross-year tax-decision workflow that ESPP makes ugly. Specifically:
- Lot-level entry of every ESPP purchase with offering-period start price, purchase price, FMV at purchase, and computed W-2 inclusion. The structured form prevents the "I forgot which offering period this lot was from" failure.
- Pre-computed adjusted basis per lot ready to copy into Form 8949 (or to hand to your CPA as a clean lot table).
- Qualifying-vs-disqualifying disposition tracker so you can see which lots cross which holding-period thresholds at any given date — useful when deciding which lots to sell first to optimize tax treatment.
- Wash-sale interaction detection across your ESPP schedule and any loss sales of the same security in any account, including the cross-account case where the loss was in your spouse's brokerage and the ESPP purchase was at your employer (yes, the IRS considers spousal substantially-identical).
- Quarterly PDF that includes the lot table — drop it into your CPA-prep folder before April and your CPA's first hour of work has been pre-done. The PDF spec is in pillar #9.
HELM doesn't file your taxes. We are not your CPA. What HELM does is keep the lot-level data structured all year, run the wash-sale and disposition math continuously, and produce a document that makes the April conversation with your CPA five times faster and 10× more accurate. The premium pricing is justified the moment HELM catches one wash-sale-on-ESPP interaction that your tax software wouldn't have caught — and most equity-comp operators have at least one of those waiting in their lot history.
Stop paying tax on the same dollar twice.
HELM keeps your ESPP lots in a structured form all year, runs the wash-sale and disposition math, and hands your CPA a lot-level table that drops into Form 8949 with no rework. Founding-operator slot at $79/mo, locked for life of subscription.
See HELM →