Security
Attack tests
Each attempt to cheat the system, what refused it, and whether a transaction exists.
In plain terms: Deliberate attempts to cheat, such as selling the same clean energy twice or faking a signature, and what stopped each one.
8 of 8 refused
6 by a contract, 2 by the prover. The run fails if any attempt gets through.
Why most attacks have no transaction
Before a transaction is sent, its is estimated by simulating it. An attack that the contract rejects already fails in that simulation, with the contract's own error, so it is never broadcast. Attacks on the proofs fail even earlier: the prover cannot build a proof of a false statement. The run then checks on-chain that nothing changed.
Every attempt
8 attempts, in the order the run made them.
- 01Refused
Registry B re-sells 50 MWh of hour 57 that the buyer already claimed
A second registry tries to sell clean energy the buyer has already claimed for that hour. The shared ledger counts every hour's MWh once, so the sale is refused.
- Expected
- SliceAlreadyClaimed
- Observed
- SliceAlreadyClaimed
- Refused by
- A contract
- Refused before broadcast · no transaction
Set-up transaction (legitimate on its own; the attack is the re-sale after it):
- registry B issues the SAME MWh (legitimately signed)0xd7b0d4…0b0fefblock 48,239,412 · 1,423,887 gas
- 02Refused
Issuer certifies 1 MWh more than the metered production of that hour
An issuer tries to certify more clean energy than was produced in that hour. The contract compares it with the oracle's metered production.
- Expected
- ExceedsProduction
- Observed
- ExceedsProduction
- Refused by
- A contract
- Refused before broadcast · no transaction
- 03Refused
Someone impersonates issuer A with a different ML-DSA key
Someone signs a certificate batch with a different key, pretending to be the issuer. The contract checks the post-quantum signature against the issuer's registered key.
- Expected
- BadIssuerSignature
- Observed
- BadIssuerSignature
- Refused by
- A contract
- Refused before broadcast · no transaction
- 04Refused
Buyer tries to prove 77.48% (one basis point above the truth)
The buyer tries to prove a coverage just above its true value. A false statement has no valid proof, so the prover cannot produce one.
Recorded by the run: coverage >= 77.48% is false for this data; no proof can exist
- Expected
- ProverRefused
- Observed
- ProverRefused
- Refused by
- The prover, locally
- Refused by the prover · no transaction
- 05Refused
Buyer resubmits the valid proof claiming 5 points more
The buyer reuses a valid proof but claims a higher coverage. The contract rebuilds the proof's public inputs itself, so the proof no longer matches.
- Expected
- ProofRejected
- Observed
- ProofRejected
- Refused by
- A contract
- Refused before broadcast · no transaction
- 06Refused
Buyer tries to prove residual ≤ 546.124 t (1 kg below the truth)
The buyer tries to prove emissions just below the truth. The prover cannot produce a proof of a false bound.
Recorded by the run: coverage >= 75.00% and residual <= 546,124 kg is false for this data; no proof can exist
- Expected
- ProverRefused
- Observed
- ProverRefused
- Refused by
- The prover, locally
- Refused by the prover · no transaction
- 07Refused
Oracle re-posts hour 104 (133 g/kWh) 100 g/kWh cleaner
The oracle tries to replace an hour's posted grid intensity with a cleaner value. Posted values cannot be changed.
- Expected
- AlreadyPosted
- Observed
- AlreadyPosted
- Refused by
- A contract
- Refused before broadcast · no transaction
- 08Refused
Buyer proves residual ≤ 379.2 t on a fake intensity vector 30 % cleaner than the oracle's
The buyer proves against its own, cleaner intensity data. The contract rebuilds the intensities from the oracle, so the proof fails.
- Expected
- ProofRejected
- Observed
- ProofRejected
- Refused by
- A contract
- Refused before broadcast · no transaction