Registry & Resolver
The two-contract design is the backbone of EnergyAS. Understanding how the Registry and Resolver interact is essential for working with the protocol.
EnergyRegistry
The registry is the permanent state contract. It stores all watchers, projects, attesters, energy accumulators, and period locks. It is never replaced or migrated.
Responsibilities
| Function | Description |
|---|---|
| Watcher management | Registration, ownership transfer |
| Project management | Registration, deregistration, transfer between watchers |
| Attester management | Per-project and watcher-wide whitelisting |
| Period locking | Prevent duplicate attestations for the same time window |
| Linear chain enforcement | Ensure attestations form a continuous timeline per project |
| Energy accumulators | Running totals per project and per watcher |
| Resolver authorization | Control which resolvers can write to the registry |
| Energy type registry | On-chain registry of valid energy source types |
| Replacement tracking | Track correction chains between attestations |
EnergyAttestationResolver
The resolver is a stateless validation layer. It implements EAS's resolver interface and is called automatically by EAS on every attestation and revocation attempt.
Responsibilities
| Function | Description |
|---|---|
| Data decoding | Decode the ABI-encoded attestation data (7 fields) |
| Structural validation | Check readingCount, interval, readings array length, method |
| Permission checks | Verify attester is whitelisted for the project or watcher |
| Derived computation | Calculate toTimestamp and total energyWh from readings |
| Replacement validation | Verify replacement attestations match the original's project and period |
| Registry delegation | Call recordAttestation() or recordReplacement() on registry |
| Revocation blocking | Reject direct revocations to preserve audit trail |
How They Interact
The resolver reads from the registry (to check project status, attester authorization, etc.) and writes to it (to record attestations and replacements). The registry only accepts writes from authorized resolvers.
Registry.authorizeResolver(resolverAddress)
→ Resolver can now call registry.recordAttestation()
→ Resolver can now call registry.recordReplacement()
Registry.deauthorizeResolver(resolverAddress)
→ Resolver can no longer write to registryMultiple resolvers can be authorized simultaneously. This enables zero-downtime migrations where old and new resolvers run side by side during a transition period.