Inspiration

In Ota, where I live, the power goes off and within a minute you hear the generators start up across the street. A lot of homes and schools nearby have added rooftop solar to cut that diesel bill. Every hour those panels run during an outage, a generator stays off and real emissions are avoided. None of that is counted anywhere.

Certificate markets weren’t built for a 5 kW rooftop. Registering for I-RECs costs more than a small site’s certificates are worth, so the cleanest hours on the continent go unrecorded. On the other side, companies trying to prove they run on clean power hour by hour, not just on annual paper, can’t find supply they can trust. We wanted to connect the two and make the certificate tell the truth about what each hour actually replaced.

What it does

How we built it

Contract (Solidity, Foundry): a device registry, EIP-712 signatures from the device checked on-chain alongside a verifier co-signature, a one-certificate-per-device-hour rule, and retire(), which burns and emits a public receipt. Deployed to testnet. Verifier (Rust, Axum): signature, freshness, physics and displacement checks, then co-signs and submits the mint. The hour’s twelve readings are rolled into a Merkle root so the chain stores one commitment, not twelve records. Meters: a Rust simulator running six sites in six countries on real solar curves, with outage schedules for the generator-heavy sites, plus an ESP32 reference meter design with a secure element for key storage. Frontend: a web app that installs on phones, in a dark interface with a light mode for the public Trace page.

Challenges we ran into

Proving a generator was displaced. A meter can say the grid was down, but that alone isn’t proof. We settled on two conditions together (a signed 0 V grid reading and a generator registered on-chain) and made the conservative grid factor the default whenever either is missing. Physics checks without false alarms. Cloud edges and panel tilt make real output spiky. Tolerances had to be tight enough to catch a fake 2 a.m. reading but loose enough not to reject a sunny noon. Keeping verification on-chain without burning gas. Checking every 5-minute signature on-chain was too expensive. Signing an hourly summary bound to a Merkle root of the readings kept the device signature verifiable on-chain at one check per hour. Being honest about nights. Solar can’t cover them. We chose to show those hours as gaps in the match rather than quietly fill them with annual credits.

Accomplishments that we're proud of

The meter’s own signature is checked by the contract, so even our backend can’t mint a certificate the meter didn’t sign. Break it: six real attacks, six stops, all visible to the judges. The fake-blackout attack isn’t simply rejected; it gets minted at the grid factor, so lying earns nothing. Carbon weighting surfaced something we didn’t expect: per tonne of CO₂, solar that displaces generators is the cheapest real impact on the market, roughly four times cheaper than solar on a clean grid in our demo data. Any certificate can be traced from receipt back to device in one page, with no account needed.

What we learned

Emission factors vary enormously between places, and that difference matters more for climate impact than the kWh total does. The energy industry is already moving toward hourly, granular certificates. The hard part isn’t the token; it’s trustworthy data at the edge. Designing for a dishonest meter changes everything. Every field we sign, and every default we pick, came from asking how someone would cheat with it.

What's next for SUNMINT

Close the night gaps with wind and battery-discharge certificates. Cross-check blackout claims against utility outage feeds and neighbouring meters. An open-hardware meter kit cheap enough for a single household. Registry bridges so certificates can map into existing standards like I-REC. A buyer API for sustainability reporting. A pilot with a school or clinic mini-grid in Lagos or Ogun State, moving from testnet to real readings.

Built With

Share this project:

Updates

Submission history