Every rule this software applies, with the law it comes from.
Below is every UK tax rule the gains.tax engine applies to your figures. Each one is listed with the section of the Taxation of Chargeable Gains Act 1992 it comes from, the HMRC worked example it is tested against, and what the test checks. If one of these tests fails, this page does not publish and the software does not ship.
29 rules, 111 assertions, all passing. Recorded 2026-08-26 04:42 UTC, engine build 2026-08-26 04:42 UTC. The 13 law rules cite statute. The 16 behaviour rules do not, because they are not statute, they are how the engine handles your data, reconciliation, transfer linking, the confidence score, and the published rates and allowances it checks against GOV.UK. Where the engine cites no statute, this page claims none.
Fits a file. One page per few rules, links printed as cited.
The whole record in one table
| Rule | Statute | HMRC reference | Assertions | Status |
|---|---|---|---|---|
| HMRC CRYPTO22251, Victoria, section 104 pool | TCGA 1992 section 104 | CRYPTO22251 | 3 | Passing |
| HMRC CRYPTO22255, Melanie, 30 day rule | TCGA 1992 section 106A | CRYPTO22255 | 3 | Passing |
| matching order, same day beats 30 day beats pool | TCGA 1992 section 106A, TCGA 1992 section 105, TCGA 1992 section 104 | None | 3 | Passing |
| 30 day window is forward only | TCGA 1992 section 106A | None | 1 | Passing |
| crypto to crypto trade is a disposal, CRYPTO22100 | Engine behaviour, no statute claimed | CRYPTO22100 | 3 | Passing |
| income, s37 TCGA, taxed at receipt then base cost | TCGA 1992 section 37 | None | 2 | Passing |
| allowable costs, s38, fees both sides | TCGA 1992 section 38 | None | 1 | Passing |
| NFTs are not pooled and no matching rules apply, CRYPTO22200 | Engine behaviour, no statute claimed | CRYPTO22200 | 2 | Passing |
| spouse transfer is no gain no loss, s58 | TCGA 1992 section 58 | None | 4 | Passing |
| gift to charity is no gain no loss, s257 | TCGA 1992 section 257 | None | 2 | Passing |
| gift to anyone else is a disposal at market value, s17 | TCGA 1992 section 17 | None | 1 | Passing |
| losing a key is not a disposal, CRYPTO22400 | TCGA 1992 section 24 | CRYPTO22400 | 4 | Passing |
| transfers between your own wallets are not disposals | Engine behaviour, no statute claimed | None | 3 | Passing |
| transfer linking, fee aware, cross wallet, best match first | Engine behaviour, no statute claimed | None | 10 | Passing |
| an unpaired transfer is flagged, the classic inflated gain | Engine behaviour, no statute claimed | None | 1 | Passing |
| disposal with no acquisition history | Engine behaviour, no statute claimed | None | 3 | Passing |
| diagnostics catch bad rows | Engine behaviour, no statute claimed | None | 8 | Passing |
| tax computation, bands and losses | Engine behaviour, no statute claimed | None | 6 | Passing |
| tax year assignment, 6 April boundary | Engine behaviour, no statute claimed | None | 3 | Passing |
| multi year split, one figure per tax year | Engine behaviour, no statute claimed | None | 13 | Passing |
| brought forward losses never waste the exempt amount | Engine behaviour, no statute claimed | None | 3 | Passing |
| current year losses are used in full even where that wastes allowance | Engine behaviour, no statute claimed | None | 3 | Passing |
| 2024-25 split year, 30 October rate change, beneficial allocation | Engine behaviour, no statute claimed | None | 8 | Passing |
| years before 2021-22 are computed but not estimated | Engine behaviour, no statute claimed | None | 3 | Passing |
| the pool ledger knows which row moved it | Engine behaviour, no statute claimed | None | 2 | Passing |
| reconciliation confidence score | Engine behaviour, no statute claimed | None | 5 | Passing |
| wallet labels survive expansion, the UI attributes findings by them | Engine behaviour, no statute claimed | None | 1 | Passing |
| a trade with no received side is flagged, not silently ignored | Engine behaviour, no statute claimed | None | 3 | Passing |
| fork gets its own pool, CRYPTO22300 | TCGA 1992 section 52(4) | CRYPTO22300 | 7 | Passing |
Status can only ever read passing. The record is written by the test run itself and only on a clean run, so a failure produces no file, and no file means no page.
The 13 rules that come from the law
HMRC CRYPTO22251, Victoria, section 104 pool
TCGA 1992 section 104 , HMRC worked example CRYPTO22251
The scenario the test runs
1 Jan 2024 buy 100 TOKENA for £1,000; 18 Sept 2024 buy 50 TOKENA for £125,000; 1 Dec 2024 sell 50 TOKENA for £300,000. The engine must produce gain = 258,000, pool cost left = 84,000, pool qty left = 100.
What the test proves. The suite asserts 3 facts about this scenario and every one must hold for this file to exist. (3 assertions)
HMRC CRYPTO22255, Melanie, 30 day rule
TCGA 1992 section 106A , HMRC worked example CRYPTO22255
The scenario the test runs
1 Jan 2024 buy 14000 TOKENE for £200,000; 30 Aug 2024 sell 4000 TOKENE for £160,000; 11 Sept 2024 buy 500 TOKENE for £17,500. The engine must produce gain = 92,500, pool qty = 10,500, pool cost = 150,000.
What the test proves. The suite asserts 3 facts about this scenario and every one must hold for this file to exist. (3 assertions)
matching order, same day beats 30 day beats pool
TCGA 1992 section 106A, TCGA 1992 section 105, TCGA 1992 section 104
The scenario the test runs
1 Jan 2024 buy 10 X for £1,000; 1 Jun 2024 sell 5 X for £2,000; 1 Jun 2024 buy 2 X for £600; 10 Jun 2024 buy 1 X for £400. The engine must produce cost = 1,200, rules used in order = "same,thirty,pool", pool left = 8.
What the test proves. The suite asserts 3 facts about this scenario and every one must hold for this file to exist. (3 assertions)
30 day window is forward only
The scenario the test runs
1 Jan 2024 buy 10 X for £1,000; 1 Jun 2024 sell 10 X for £5,000; 2 Jul 2024 buy 10 X for £9,000. The engine must produce day 31 stays in pool = 4,000.
What the test proves. The suite asserts 1 fact about this scenario and every one must hold for this file to exist. (1 assertion)
crypto to crypto trade is a disposal, CRYPTO22100
HMRC worked example CRYPTO22100
The scenario the test runs
1 Jan 2024 buy 1 BTC for £20,000; 1 Jun 2024 trade 1 BTC for £30,000 into 10 ETH. The engine must produce BTC gain on the swap = 10,000, ETH enters the pool at the swap value = 30,000, ETH pool qty = 10.
What the test proves. The suite asserts 3 facts about this scenario and every one must hold for this file to exist. (3 assertions)
income, s37 TCGA, taxed at receipt then base cost
The scenario the test runs
1 May 2024 income 2 ETH for £4,000; 1 Nov 2024 sell 2 ETH for £5,200. The engine must produce income total = 4,000, gain is only the uplift after receipt = 1,200.
What the test proves. The suite asserts 2 facts about this scenario and every one must hold for this file to exist. (2 assertions)
allowable costs, s38, fees both sides
The scenario the test runs
1 Jan 2024 buy 10 X for £1,000 with a £100 fee; 1 Jun 2024 sell 10 X for £2,000 with a £50 fee. The engine must produce gain net of both fees = 850.
What the test proves. The suite asserts 1 fact about this scenario and every one must hold for this file to exist. (1 assertion)
NFTs are not pooled and no matching rules apply, CRYPTO22200
HMRC worked example CRYPTO22200
The scenario the test runs
1 Jan 2024 buy 1 PUNK123 for £5,000; 1 Jun 2024 sell 1 PUNK123 for £9,000; 10 Jun 2024 buy 1 PUNK123 for £40,000. The engine must produce NFT gain uses its own cost, not the 30 day buy = 4,000, no matching rules recorded = "pool".
What the test proves. The suite asserts 2 facts about this scenario and every one must hold for this file to exist. (2 assertions)
spouse transfer is no gain no loss, s58
The scenario the test runs
1 Jan 2024 buy 10 X for £1,000; 1 Jun 2024 gift-spouse 5 X for £9,999. The engine must produce no disposal recorded = 0, no gain = 0, half the cost leaves the pool with the units = 500, flags the spouse rule, the SPOUSE_NGNL finding is raised.
What the test proves. The suite asserts 4 facts about this scenario and every one must hold for this file to exist. (4 assertions)
gift to charity is no gain no loss, s257
The scenario the test runs
1 Jan 2024 buy 10 X for £1,000; 1 Jun 2024 gift-charity 10 X for £50,000. The engine must produce no taxable gain on the donation = 0, pool emptied = 0.
What the test proves. The suite asserts 2 facts about this scenario and every one must hold for this file to exist. (2 assertions)
gift to anyone else is a disposal at market value, s17
The scenario the test runs
1 Jan 2024 buy 10 X for £1,000; 1 Jun 2024 gift-out 10 X for £8,000. The engine must produce taxed on market value = 7,000.
What the test proves. The suite asserts 1 fact about this scenario and every one must hold for this file to exist. (1 assertion)
losing a key is not a disposal, CRYPTO22400
TCGA 1992 section 24 , HMRC worked example CRYPTO22400
The scenario the test runs
1 Jan 2024 buy 10 X for £1,000; 1 Jun 2024 lost 10 X for £0. The engine must produce no disposal = 0, no loss allowed automatically = 0, units stay in the pool = 10, explains the negligible value route, the LOST_NOT_DISPOSAL finding is raised.
What the test proves. The suite asserts 4 facts about this scenario and every one must hold for this file to exist. (4 assertions)
fork gets its own pool, CRYPTO22300
TCGA 1992 section 52(4) , HMRC worked example CRYPTO22300
The scenario the test runs
1 Jan 2024 buy 1 BTC for £20,000; 1 Aug 2024 fork 1 BCH for £0; 1 Sept 2024 sell 1 BCH for £300. The engine must produce forked asset has its own pool = true, BTC pool untouched = 1, dust arrivals are informational = 40, dust costs no confidence = 0, real unpaired arrivals still warn = 25, with 2 further checks.
What the test proves. The suite asserts 7 facts about this scenario and every one must hold for this file to exist. (7 assertions)
The 16 rules that are engine behaviour
These are not statute and are not presented as statute. They are how the engine handles your data, reconciliation, transfer linking, the confidence score, and the rates and allowances checked against the published GOV.UK figures rather than derived from an act. They are tested exactly as strictly as the law rules.
transfers between your own wallets are not disposals
The scenario the test runs
1 Jan 2024 buy 1 BTC for £20,000; 1 Mar 2024 transfer-out 1 BTC for £0; 1 Mar 2024 transfer-in 1 BTC for £0; 1 Sept 2024 sell 1 BTC for £26,000. The engine must produce gain unaffected by the move = 6,000, paired transfer raises nothing, the UNPAIRED_OUT finding is not raised, paired transfer raises nothing in, the UNPAIRED_IN finding is not raised.
What the test proves. The suite asserts 3 facts about this scenario and every one must hold for this file to exist. (3 assertions)
transfer linking, fee aware, cross wallet, best match first
The scenario the test runs
1 Jan 2024 buy 1 BTC for £20,000; 1 Mar 2024 transfer-out 0.5 BTC for £0; 2 Mar 2024 transfer-in 0.4996 BTC for £0. The engine must produce fee delta pair links silently = 1, network fee measured = 0, link carries both rows = "2>3", no unpaired out, the UNPAIRED_OUT finding is not raised, no unpaired in, the UNPAIRED_IN finding is not raised, with 5 further checks.
What the test proves. The suite asserts 10 facts about this scenario and every one must hold for this file to exist. (10 assertions)
an unpaired transfer is flagged, the classic inflated gain
The scenario the test runs
1 Jan 2024 buy 1 BTC for £20,000; 1 Mar 2024 transfer-out 1 BTC for £0. The engine must produce unpaired out flagged, the UNPAIRED_OUT finding is raised.
What the test proves. The suite asserts 1 fact about this scenario and every one must hold for this file to exist. (1 assertion)
disposal with no acquisition history
The scenario the test runs
1 Jun 2024 sell 1000 DOGE for £900. The engine must produce nil cost, whole proceeds are gain = 900, shortfall recorded = 1,000, missing cost basis flagged, the NO_COST_BASIS finding is raised.
What the test proves. The suite asserts 3 facts about this scenario and every one must hold for this file to exist. (3 assertions)
diagnostics catch bad rows
The scenario the test runs
buy 1 X for £100; 1 Jan 2024 wat 1 X for £100; 1 Jan 2024 buy 1 for £100; 1 Jan 2024 buy 0 X for £100; 1 Jan 2024 income 1 X for £0; 1 Jan 2024 gift-out 1 X for £0; and 2 further rows. The engine must produce bad date, the BAD_DATE finding is raised, bad type, the BAD_TYPE finding is raised, no asset, the NO_ASSET finding is raised, no qty, the NO_QTY finding is raised, income with no value, the NO_VALUE finding is raised, with 3 further checks.
What the test proves. The suite asserts 8 facts about this scenario and every one must hold for this file to exist. (8 assertions)
tax computation, bands and losses
The scenario the test runs
The engine must produce at 18 = 8,270, at 24 = 4,795, due = 2,639.4, all in basic band when no income = 0, brought forward losses applied before the allowance = 3,000, with 1 further checks.
What the test proves. The suite asserts 6 facts about this scenario and every one must hold for this file to exist. (6 assertions)
tax year assignment, 6 April boundary
The scenario the test runs
The engine must produce 5 April is the old year = "2024-25", 6 April starts the new year = "2025-26", early January belongs to the year that began the previous April = "2023-24".
What the test proves. The suite asserts 3 facts about this scenario and every one must hold for this file to exist. (3 assertions)
multi year split, one figure per tax year
The scenario the test runs
1 May 2021 buy 4 BTC for £40,000; 10 Jan 2023 sell 1 BTC for £30,000; 10 Jun 2023 sell 1 BTC for £4,000; 10 Jun 2025 sell 1 BTC for £26,000. The engine must produce three years produced = 3, years in order = "2022-23,2023-24,2025-26", 2022-23 uses the £12,300 allowance = 12,300, 2022-23 taxable = 7,700, 2022-23 taxed at the old 10 per cent rate = 10, with 8 further checks.
What the test proves. The suite asserts 13 facts about this scenario and every one must hold for this file to exist. (13 assertions)
brought forward losses never waste the exempt amount
The scenario the test runs
1 May 2025 buy 10 X for £0; 1 Jun 2025 sell 10 X for £10,000. The engine must produce only enough losses used to reach the allowance = 7,000, taxable nil = 0, the rest carries on = 93,000.
What the test proves. The suite asserts 3 facts about this scenario and every one must hold for this file to exist. (3 assertions)
current year losses are used in full even where that wastes allowance
The scenario the test runs
1 May 2025 buy 1 A for £1,000; 1 Jun 2025 sell 1 A for £6,000; 1 May 2025 buy 1 B for £9,000; 1 Jul 2025 sell 1 B for £5,000. The engine must produce net after mandatory loss offset = 1,000, nothing taxable = 0, no loss survives to carry forward = 0.
What the test proves. The suite asserts 3 facts about this scenario and every one must hold for this file to exist. (3 assertions)
2024-25 split year, 30 October rate change, beneficial allocation
The scenario the test runs
1 May 2023 buy 100 X for £1,000; 1 Jun 2024 sell 50 X for £20,000; 1 Dec 2024 sell 50 X for £30,000. The engine must produce one tax year = 1, year is 2024-25 = "2024-25", taxable after £3,000 allowance = 46,000, band count = 3, 10 per cent slice = 8,270, with 3 further checks.
What the test proves. The suite asserts 8 facts about this scenario and every one must hold for this file to exist. (8 assertions)
years before 2021-22 are computed but not estimated
The scenario the test runs
1 Jan 2019 buy 1 X for £1,000; 1 Jun 2019 sell 1 X for £5,000. The engine must produce gain still computed = 4,000, no tax estimate for the year = null, unsupported year flagged, the YEAR_UNSUPPORTED finding is raised.
What the test proves. The suite asserts 3 facts about this scenario and every one must hold for this file to exist. (3 assertions)
the pool ledger knows which row moved it
The scenario the test runs
1 Jan 2024 buy 1 BTC for £20,000; 1 Jun 2024 sell 0.4 BTC for £12,000. The engine must produce acquisition entry carries its row = 1, disposal entry carries its row = 2.
What the test proves. The suite asserts 2 facts about this scenario and every one must hold for this file to exist. (2 assertions)
reconciliation confidence score
The scenario the test runs
1 May 2025 buy 1 X for £1,000; 1 Jun 2025 sell 1 X for £2,000. The engine must produce clean data scores 100 = 100, missing cost basis costs 20 = 80, an unpaired transfer costs 6 = 94, each finding carries its own deduction = 6, heavy errors carry 20 = 20.
What the test proves. The suite asserts 5 facts about this scenario and every one must hold for this file to exist. (5 assertions)
wallet labels survive expansion, the UI attributes findings by them
The scenario the test runs
The engine must produce wallet carried through = "Kraken".
What the test proves. The suite asserts 1 fact about this scenario and every one must hold for this file to exist. (1 assertion)
a trade with no received side is flagged, not silently ignored
The scenario the test runs
1 Jan 2024 buy 1 BTC for £20,000; 1 Jun 2024 trade 0.5 BTC for £15,000. The engine must produce inert trade flagged, the TRADE_NO_COUNTER finding is raised, pool untouched by the inert row = 1, complete trades are not flagged, the TRADE_NO_COUNTER finding is not raised.
What the test proves. The suite asserts 3 facts about this scenario and every one must hold for this file to exist. (3 assertions)
Check it yourself
Every scenario above is reproducible without our help. Open the app, enter the rows from an HMRC worked example, and compare the figure it produces against HMRC's own published answer on their page. The engine's answer and the manual's answer are the same numbers. That is the test, and you can run it.
Recorded 2026-08-26 04:42 UTC from engine build 2026-08-26 04:42 UTC. General information about how this software works, not personal tax advice.