Architecture Overview
EnergyAS is built as a two-contract system on top of the Ethereum Attestation Service. This separation of concerns enables upgradeable validation logic without migrating state.
System Layers
The protocol consists of four layers, each with a distinct responsibility:
┌─────────────────────────────────────────────┐
│ EnergyAS Protocol (your application) │
│ Watchers → Projects → Attestations │
├─────────────────────────────────────────────┤
│ EnergyAttestationResolver (replaceable) │
│ Validates attestation data + permissions │
├─────────────────────────────────────────────┤
│ EnergyRegistry (permanent) │
│ Stores all state, events, and accumulators │
├─────────────────────────────────────────────┤
│ Ethereum Attestation Service (EAS) │
│ Permissionless attestation protocol │
└─────────────────────────────────────────────┘Data Flow
When an attester submits energy readings, the data flows through the stack:
Attester calls eas.attest(schemaUID, data)
→ EAS stores the attestation
→ EAS calls resolver.onAttest(attestation)
→ Resolver decodes and validates the data
→ Resolver checks attester authorization
→ Resolver computes energyWh and toTimestamp
→ Resolver calls registry.recordAttestation(...)
→ Registry checks for duplicate periods
→ Registry updates energy accumulators
→ Registry emits EnergyAttested eventDesign Principles
The architecture follows three core principles:
Permanent state, replaceable logic. The EnergyRegistry holds all data and is never replaced. The EnergyAttestationResolver contains validation logic and can be swapped without any data migration.
On-chain verification, off-chain evidence. Core data (readings, timestamps, energy totals) lives on-chain. Supporting evidence (audit PDFs, IoT exports) is anchored via optional IPFS metadata URIs.
Permissionless with tenant isolation. Anyone can register and participate, but each watcher's data is completely isolated from others at the EVM level.
The registry contract uses OpenZeppelin's Ownable2Step for safe ownership transfer and the resolver uses Pausable for emergency stops — both are battle-tested patterns.