Inspiration

Nigeria's forest reserves are being lost, and nobody can say by how much with a number anyone else can check. Carbon and nature finance needs exactly that number: how much forest a reserve holds, how fast it is going, and how much carbon is at stake. Today it usually comes as a consultant's PDF. You cannot rerun it, you cannot tell whether it was edited after the fact, and nothing stops two projects drawn over the same ground from both counting it.

At Kam Edge we had already built Kanopy as a desk study of two reserves from open satellite data. Omo Forest Reserve in Ogun State has lost 14,920 ha of tree cover since 2001, and only 16.6% of it is still undisturbed moist forest. The numbers were real, but a reader still had to trust us. ClimateChain asked the right question: what would it take for a reader not to have to trust us?

What it does

Kanopy measures a forest reserve from open satellite data. It then writes a fingerprint of that measurement into a public registry on Ethereum Sepolia, so anyone can recompute it and check it.

  • Measure. For each reserve Kanopy reports area, tree-cover loss by year, forest condition, canopy height, and carbon stock with its uncertainty. Omo holds 17.7 ± 11.1 Mt CO₂e above ground.
  • Attest. Four SHA-256 fingerprints go on-chain: the boundary, the ten input rasters, the analysis code, and the result file. The area and carbon figures go on-chain too, as numbers. Versions are append-only.
  • Verify. The verifier page recomputes the fingerprints in your browser and compares them with the registry. Press Alter one figure and two checks turn red. tools/verify.py goes further: it reruns the whole analysis from the rasters and compares every fingerprint.
  • Prevent double counting. The world is cut into a fixed grid of 0.01° cells (about 122 ha each). A project claims cells for a year, and the contract refuses any cell that is already claimed for that year. To show this, we registered a synthetic rectangle across Omo's north-east edge. 173 of its 300 cells collide with Omo, and the contract rejects its claim with CellsAlreadyClaimed.

It does not issue, price or trade credits. It is the measurement and the ledger of who counts which ground, which is the part that has to be right before any credit exists.

How we built it

Measurement (Python: rasterio, numpy, shapely). Kanopy clips six public datasets to each boundary: Hansen Global Forest Change, the JRC Tropical Moist Forest map, ESA WorldCover, ETH Global Canopy Height, ESA CCI Biomass and Sentinel-2. Pixel areas come from latitude rather than a reprojection. Carbon is the IPCC default conversion of above-ground biomass:

$$ \text{CO}_2\text{e} = \sum_i \text{AGB}_i \, A_i \times 0.47 \times \tfrac{44}{12} $$

We carry the biomass map's own per-pixel uncertainty \( \sigma_i \) through as an upper bound. We treat pixel errors as fully correlated, because we cannot show that they are not:

$$ \sigma_{\text{CO}_2\text{e}} \le \sum_i \sigma_i \, A_i \times 0.47 \times \tfrac{44}{12} $$

The grid. A cell is \( i = \lfloor (\text{lat} + 90)/0.01 \rfloor,\ j = \lfloor (\text{lon} + 180)/0.01 \rfloor \). It belongs to a reserve when its centre lies inside the boundary, so cells are never split. On-chain, cells are packed 256 to a storage word, as rows of \( (i,\ j \gg 8,\ \text{mask}) \). Two claims overlap exactly when \( \text{mask}_a \wedge \text{mask}_b \ne 0 \). That packing is why all 1,083 cells of Omo fit in one transaction (2,986,545 gas).

Registry (Solidity, Hardhat). KanopyRegistry.sol holds reserves, attestations and claims. Approved attesters write measurements, and each reserve's steward makes its claims. Fifteen tests run on the real footprints and manifests, so they also check that Python, JavaScript and Solidity agree on what a row and a hash are.

Verifier (plain HTML/JS, ethers v6). The page needs no wallet. The claim simulation is a read-only eth_call from the steward's address, so it shows exactly what a real transaction would do without sending one.

Challenges we ran into

  • The same file hashed differently on Windows and Linux. Python's text mode wrote CRLF line endings on Windows only. Every fingerprint is over raw bytes, so we now write results as bytes and tell git never to touch line endings. Reproducibility starts at the byte level.
  • Pandam Wildlife Park has no published boundary. Neither the World Database on Protected Areas nor OpenStreetMap has a polygon for the park itself. We used the Ramsar wetland polygon, which covers 19,759 ha against the 22,400 ha reported, and say so on every page.
  • Standard forest conventions read nothing in savanna. The usual rule counts loss only on pixels with at least 30% canopy, and only 0.2% of Pandam passes it. We report loss on every pixel instead.
  • We could not redistribute the boundaries. The protected-area polygons come with terms that restrict redistribution, so the repository holds their hash rather than the files.
  • The network fought us. The package install failed on a connection reset, and the Solidity compiler download stalled until we fetched it by hand over IPv4 and checked it against the official hash.
  • Testnet details. Wallets reserve gas limit × maximum fee before sending, so a 3M-gas claim needed about 0.012 test ETH set aside even though it spends far less. We made the deploy script resumable so a failure part way never means paying for a second registry.

Accomplishments that we're proud of

  • A full loop that a stranger can run: rasters → numbers → fingerprints → chain → browser check → full recompute. On our machine all five fingerprints reproduce for all three areas.
  • Uncertainty is a first-class, on-chain value, not a footnote. The registry stores 17,700 ± 11,100 kt CO₂e for Omo, not just 17,700.
  • Double counting is refused by the contract itself, demonstrated live on a public testnet.
  • Honest limits on the page itself: a matching fingerprint proves the record was not changed, not that the satellites are right.

What we learned

  • The spread is the story. Under standard deductions, Omo's avoided-deforestation potential ranges from 10,298 to 72,415 credits a year, a sevenfold spread that comes from the choice of baseline. That is why the baseline needs to be independent and checkable.
  • Greenness cannot see degradation. Median NDVI in Omo's undisturbed forest is 0.770; in degraded forest it is 0.775. Mean biomass is 100.1 against 93.0 t/ha, with map uncertainty near 60 t/ha. From orbit the two are almost indistinguishable, which is why field plots matter.
  • Where loss happens depends on the reserve. In Pandam, 79.5% of recent loss sits within 2 km of the boundary, which holds 51.4% of the area: pressure from outside. In Omo, recent loss is spread almost evenly through the reserve: pressure from inside.
  • A ledger only helps if the hashing is boring. Most of the engineering went into making the same input produce the same bytes everywhere.

What's next for Kanopy

The satellites tell us where to look. The next step is to measure the forest from the air and on the ground, and to put those readings through the same registry.

  • LiDAR drones. We plan to fly LiDAR drones over sample strips of each reserve. LiDAR measures tree height and the structure under the canopy directly, which is exactly what greenness from orbit cannot see. That is how we expect to separate degraded from undisturbed forest, and to bring the carbon figure's uncertainty down from roughly ±60% to something a buyer can rely on. Each flight's point cloud will be fingerprinted and attested like any other input, so a later reader can check which flight a number came from.
  • IoT devices in the reserve. We plan to install low-power sensors in the field: acoustic monitors that pick up chainsaws, and stations that log soil moisture, temperature and rainfall. Each device will sign its readings. Batches will go on-chain as a single Merkle root,

$$ R = \text{MerkleRoot}\big(H(r_1), H(r_2), \dots, H(r_n)\big), $$

so any one reading can be proved part of the record without storing every reading on-chain. A chainsaw alert then becomes a timestamped, tamper-evident event tied to a grid cell, not a rumour.

  • Field plots in Omo and Pandam to calibrate both the LiDAR and the satellite products, so the carbon figure carries a measured error rather than a map's.
  • Yearly re-attestation as new satellite, drone and sensor data lands, so each reserve builds a public, versioned history.
  • Governance of the registry. Today one owner approves attesters and names stewards. In practice that role belongs with forestry authorities and independent auditors.
  • More reserves, starting with those where boundaries are published, and a way for communities to contest a boundary on the record.

Built With

Share this project:

Updates

posted an update —

Kanopy measures forest reserves from open satellite data and records a fingerprint of each measurement on-chain so anyone can recheck it. This week we pointed the same pipeline at Nigerian cocoa.

From 30 December 2026, an EU importer must show that its cocoa was not grown on forest cleared after 2020, and that it was farmed legally. Kam Origin runs that test on 20 mapped cocoa farms in Ondo, four cocoa estates, and four forest reserves where cocoa farming inside the boundary is documented. It adds the EU's own reference forest map (JRC Global Forest Cover 2020) to Kanopy's existing layers.

What we found:

  • Legality is the bigger risk. 8 of the 20 farms sit inside a gazetted forest reserve. Around the Etung cocoa estates in Cross River, over a third of the land is reserve land.
  • The EU map is kinder to Ondo cocoa than tree-cover maps are. Around the Oda plantation, the EU map calls only 4% of the land forest, while tree-cover layers count 75% as trees that aren't forest. A buyer using only one kind of map would get the wrong answer either way.
  • Oluwa Forest Reserve lost 17,186 ha of tree cover from 2021 to 2025, about 21% of the reserve, the fastest loss of any site we checked.
  • No farm can be cleared or failed from space alone. None of the 20 has a walked boundary; they are survey points, and one sits in a town.

That last point led to the second piece: Kam Field Capture, a phone app for walking a farm boundary. For cocoa it now records the farmer's account of the land's history, counts pods on sample trees, and estimates what the farm can produce. It flags sales of more than twice that estimate, which is how cocoa from one farm gets laundered through another.

Read the cocoa report: https://kamhq.com/kanopy/origin/

This is a desk study from public data. No farm was visited, and farm positions are withheld because several sit inside reserves.

Log in or sign up for Devpost to join the conversation.

Submission history