Track alignment

Track 1, Carbon Markets and Emissions Transparency. The track names "lack of transparency, double counting, and complex verification". ClaimCheck turns a sentence in an ESG report into a check against the public retirement record, and its registry contract rejects a second registration of an overlapping serial range on chain.

Project description

Problem. In 10 real report sentences with a tonne quantity (found in 8 of the 40 public reports we read), companies claim 13,907,928 tCO2e of offsets, and 13,074,194 t of it cannot be traced to Gold Standard today (other registries not looked up; a gap is a lead, not proof). One real sentence does match the public record: United Internet's 2024 report says its Business Access segment retired 4,713 Gold Standard credits, and the registry holds one retired block of exactly 4,713 credits under the group company 1&1 Versatel. Today a reader has to find the serial, open a registry and compare by hand; one live ClaimCheck registry request takes a median 1.8 s (15 requests, Node, not a browser; docs/LIVE_LATENCY.json). Paris Agreement Article 6.2 asks Parties for robust accounting that avoids double counting (https://unfccc.int/sites/default/files/english_paris_agreement.pdf); ClaimCheck applies the same principle at the level of one company's offset sentence. It is not an Article 6 compliance tool.

Solution. ClaimCheck checks the sentence against public Gold Standard retirement records (by credit serial, or by the company named as beneficiary when the report prints no serial), and a Sepolia contract reverts a second registration of an overlapping serial range (citing the credits in a report is not blocked). Roles: the registry record decides the verdict, the contract locks the credit range, and AI only warns about wording (optional, after a click, never in the verdict). Paste the sentence; ClaimCheck extracts the serial and the quantity, looks the serial up, and returns one verdict: Match, Mismatch (not retired, or quantity differs), Not found, Double use, or No serial. Without a serial it reads the company, the year and the quantity, asks the registry for retired blocks that name the company as beneficiary, and shows the candidates, their total and whether the total equals the sentence. Every line shows the registry URL and the read time. A Solidity registry (RetirementRegistry) stores each used serial range per batch and reverts with RangeOverlap when a second registration overlaps it; the page's Double use answer is a read of that contract on Sepolia.

Climate impact (real reports, first). In the 10 real sentences with a tonne quantity that we found (in 8 of the 40 public reports read), companies claim 13,907,928 tCO2e; 833,734 t of it can be traced to retired Gold Standard blocks under the company's own name, leaving 13,074,194 t that a reader cannot trace to Gold Standard today (other registries are not looked up; 0 of 10 sentences equal the registry total). Script and output: docs/IMPACT_NUMBERS.txt, scripts/impact_numbers.py in the repository. This is a lead for a reviewer, not a finding of over-claiming.

Evidence. 320/320 verdicts as expected (pipeline test on templated sentences, not real reports), 83/83 second claims refused, 153 tests pass, and a live reverted transaction on Sepolia: https://eth-sepolia.blockscout.com/tx/0x43ab85cf22d4f85514a8ed25e015d137a4efdeb6671e138cd1a192e380b3db8b

Limit. Gold Standard only, and a Match means the public record agrees with the sentence; it is not an audit. The optional wording check catches a changed fact 10 times in 36 (27.8%) and raises a false alarm on matching wording 1 time in 36 (2.8%); the page shows these two numbers in the wording box title and "Not an audit · Gold Standard record only" on every Match card.

Who it is for. ESG auditors and sustainability teams who buy offsets, and journalists or NGOs who check corporate claims.

Scale. Gold Standard's public endpoint lists 166,956 retired credit blocks covering 255,174,202 credits (single source, the registry's own response headers, read 2026-10-21 11:30 KST: X-Total-Count and X-Total-Number-Of-Credits headers of https://public-api.goldstandard.org/credits?retired=true). We stored a sample of 140 real records and look up any other serial live, one request each.

Do real reports print a serial? We scanned 10 public sustainability and annual reports (Microsoft, Apple, Google, easyJet x2, Commerzbank, Storebrand x2, AIXTRON, Netflix): 0 of 10 print a credit serial (docs/SERIAL_PREVALENCE.md). On the same reports the no-serial path: 3 of 10 have a retirement sentence with a quantity, 2 of 10 get candidates, 0 of 10 match the quantity (docs/BENEFICIARY_EVAL.md). The 10 reports are in-sample for the serial question and first-time sentences for this path. (The 24 labelled sentences used to test the extractor come from retirement certificates that six organisations post, a different sample from these 10 reports: "serial 18/18" belongs to those certificates, "0 of 10 print a serial" to the reports.)

Ease of adoption. A static web page, no wallet, no login, no key. Cost per claim: one free read request and, if recorded on chain, one transaction of about 162k gas (first range of a batch) to about 223k gas (40th range of one batch) at today's mainnet storage price. Who would use it: assurance providers and auditors, who register the serial ranges they verified. Today the attestor set is one address (ours); adding an auditor is one transaction of 47,602 gas. Cost: hosting $0, registry reads free, and 1,000 registrations a month would cost about $21.9 a month on Ethereum L1 at the 2026-10-19 reading (docs/COST.md; a reading, not a forecast). Why a chain and not a signed database: anyone can verify on an explorer, without trusting us, that an overlapping second registration was refused; what was registered in the first place is still the word of one signer (us). Limit: this prototype has one signer; a multi-signer set is designed, not built.

What is new, and what is not (similar tools)

Our own part: it starts from the report sentence, with or without a serial. Serial and quantity (or, with no serial, the company's retired blocks and their total) are checked against the public retirement record, and a second registration of the same serial range reverts on chain, shown as one flow with one set of credits on Sepolia. None of the tools below does all three in one flow. On-chain refusal of reused serials alone is not new (see the patent and EcoGuard rows).

First-time real sentences (honest numbers): of 10 real reports, 0 print a serial; 3 contain a retirement sentence with a quantity, 2 get registry candidates by company name and 0 have a candidate total equal to it. On 30 further public reports (picked from the registry's own beneficiary list, rule in docs/REAL_SENTENCE_HUNT.md) 6 contain such a sentence and 0 equal the registry total; this sample is an upper bound because every company is a Gold Standard retirer. One real company sentence found by a targeted search does match: United Internet, Sustainability Report 2024, 4,713 credits retired = one retired Gold Standard block of 4,713 credits under the group company 1&1 Versatel (the demo uses it; it names a segment, so the page needs the group company name).

Tool What it does What it does not do
IEEE 3218-2022 / 3234 (blockchain standards by this hackathon's own organiser, https://blockchain.ieee.org/standards) Framework and data format for blockchain carbon-market applications No check of a report sentence (standard text is paywalled; we read its scope only)
Climate Action Data Trust (World Bank, IETA, Singapore; https://climateactiondata.org) Aggregates registry metadata to expose double-counting risk Does not read a company sentence or refuse a second claim; registry-to-registry double counting is its job, not ours
Gold Standard and Verra registries (https://registry.goldstandard.org, https://registry.verra.org) Status and quantity per serial Do not read a sentence or compare the claimed quantity
CarbonPlan OffsetsDB (https://carbonplan.org/research/offsets-db) Project, issuance and retirement snapshots of five registries Project level; no sentence-to-serial check, no refusal
Toucan and similar tokenisation (https://toucan.earth); Verra suspended tokenisation of retired credits on 2022-05-25 Retired credits as on-chain tokens No ESG-sentence check
EcoGuard on GenLayer (https://github.com/linoxbt/ecoguard) LLM validators audit project evidence; rejects a duplicate (serial, vintage) issuance No company report sentence against a public retirement record
US11694258B2, Miovision/BlueOwl (https://patents.google.com/patent/US11694258B2/en) Serial-level retirement on a blockchain ledger to remove double counting No sentence check
CBlock (Devfolio project, 2025-08, https://devfolio.co/projects/cblock-8484) and DeCarbon (HackQuest project, https://www.hackquest.io/ja/projects/HDBank-Hackathon-Galaxy-of-Innovation-2025-DeCarbon) Token issue and retire lifecycle No check of a report sentence against a public record described; no double-use refusal described (we read the project listings, not their code)
EmeraldMind (https://www.cse.uoi.gr/~tsap/publications/EmeraldMind_WWWDemo.pdf) and Stammbach et al., ACL 2023 (https://aclanthology.org/2023.acl-short.91) Greenwashing judgement of ESG sentences; environmental-claim detection No registry record behind the verdict, no chain

Why it matters now: Directive (EU) 2024/825 applies in the EU from 27 September 2026 and targets claims that a product is climate neutral or has reduced climate impact by way of offsetting (text: EUR-Lex 32024L0825 https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32024L0825, Art. 4 and recital 12; second source: EU Transition Pathways https://transition-pathways.europa.eu/legislation/directive-eu-2024825-empowering-consumer-green-transition). It applies to consumer-facing claims, not to a company's own ESG report, so it raises the pressure to back offset wording with a record; it is not a rule that ClaimCheck enforces.

Cost to keep running: hosting is static files on GitHub Pages ($0), registry reads are free, a verification costs nothing, and recording one claim on chain is about 2 to 3 US cents on Ethereum L1 at the 2026-10-19 reading (docs/COST.md). Next steps: a Verra lookup if a free endpoint appears, and more auditor addresses in the attestor set.

What we measured

  • 140 real registry records (120 retired, 20 issued), 320 claims built from them: 320/320 verdicts as expected. These sentences are templated from real rows, so this tests the pipeline, not real reports.
  • Quantity inflated by 10%+1: 120/120 caught. Issued-but-not-retired: 20/20 caught. Second claimant refused: 60/60 full overlap and 23/23 partial overlap.
  • Live endpoint agrees with the stored sample: 11/11.
  • Live lookup time, 15 single requests to the Gold Standard endpoint: median 1.8 s, min 1.7 s, max 2.2 s, 15/15 found (Node fetch from the author's machine, not a browser; docs/LIVE_LATENCY.json, measured 2026-10-21).
  • Extraction on 10 held-out phrasings: serial 8/8, quantity 8/9 (miss: "12.5k tonnes").
  • Wording check (Backed / May conflict / No receipt), 72 frozen pairs, in the browser: false May conflict on matching wording 2.8% (1/36), Backed on matching wording 80.6% (29/36), median 95 ms per sentence. Weakness: of 36 changed sentences only 27.8% (10/36) were flagged May conflict; the rest ended as No receipt, none as Backed.
  • On Sepolia, a second registration on an already registered range was sent as a real transaction and reverted with RangeOverlap: https://eth-sepolia.blockscout.com/tx/0x43ab85cf22d4f85514a8ed25e015d137a4efdeb6671e138cd1a192e380b3db8b (block 11958923, status Failed, contract source verified).
  • Sentence without a serial, 10 real reports: 3 of 10 have a retirement sentence with a quantity, 2 of 10 get registry candidates, 0 of 10 have a candidate total equal to the sentence; 7 of 10 reports are from a company with retired Gold Standard blocks under its own name (docs/BENEFICIARY_EVAL.md).
  • One flow, one set of credits, on Sepolia: a sentence we wrote from the public record ("In 2024 Google retired 131,201 tCO2e ...") finds 2 Gold Standard candidates with total 131,201 t; both ranges were registered (txs https://eth-sepolia.blockscout.com/tx/0xec12e7852eaf117c14594119ec54553faeba119bbb4006bda5a68c5c254cd1eb and https://eth-sepolia.blockscout.com/tx/0xbc7cdcc9aecebe640dbddfa3c1a396daa747d8796d4e6b396309f7a523be2e8b); a second claim on the first range reverted with RangeOverlap (https://eth-sepolia.blockscout.com/tx/0x3567dcd9d2407764415eba66acda8cc30ea6b5540f9fa44544756f1819259118, block 11959278, status Failed). Google did not publish that sentence.
  • Gas: the first registration costs about 162k on the local test chain and 683,777 on Sepolia for the same call. Cause measured (docs/gas-diagnosis.json): the deployed bytecode equals ours, the same calldata replayed locally costs 161,857, a trace shows the same 6 new storage slots, and Sepolia charges about 111k per new slot against 22k locally (5.03 times). A read-only probe of Ethereum mainnet (nothing sent) costs 22,320 per new slot, like the local chain; Sepolia's latest block header carries blockAccessListHash and slotNumber, mainnet's does not. We did not read client source, so we name no fork or EIP. The 2 to 3 US cent figure is priced at today's mainnet rule and would rise if mainnet adopts Sepolia's schedule.
  • 122 domain tests and 31 contract tests pass; the beneficiary, chain-read and gas tests were written first and seen failing.

Limits

Only Gold Standard is looked up; Verra serials are parsed but not looked up: five scripted requests to registry.verra.org all returned the page shell, never data, so there is no free scriptable endpoint. Extraction and the verdict are rules; the only model is the optional wording check. A company search gives candidates, not proof: the registry names a beneficiary for only some blocks and other registries are not looked up. A Match means the public record agrees with the sentence; it is not an audit and says nothing about project quality or ownership. The contract is deployed on the Sepolia testnet (test ETH only): https://sepolia.etherscan.io/address/0xbBC97a57c7f81F77dbA1b1b2FbC29898b87F7bDF. Trust sits in the attestor set (one owner address in this prototype; nobody else has registered, so the chain answers only for our own flows). The registry sits behind bot protection, so live lookup can be blocked on some networks; the stored sample is the default. The wording check is a small pre-trained model and catches a changed fact only 27.8% of the time. Real reports rarely print a serial (0 of 10 scanned) and the no-serial path matched the quantity on 0 of 10 first-sample reports and 0 of 30 further reports (one hand-found real match). No personal data is collected and no model is trained. Threat model: https://github.com/Ryugi62/climatechain-claimcheck/blob/main/docs/THREAT_MODEL.md

Built with

Solidity 0.8.24, Hardhat, Sepolia testnet, JavaScript (ES modules), GitHub Pages, a pre-trained NLI model (inference only). Registry data from the Gold Standard public read endpoint.

AI use

Code, tests and text were drafted with Anthropic's Claude and then run, measured and edited by the author. The verdict is deterministic rules; the only model in the product is the optional wording check, a pre-trained NLI model (Xenova/nli-deberta-v3-xsmall) running in the viewer's browser for inference only, off the verdict path.

Links

Built With

Share this project:

Updates

Submission history