Security
Security considerations for deploying and operating EnergyAS in production.
Key Management
- Use a multisig (Gnosis Safe) as the contract owner — not an EOA
- Use a multisig as the watcher owner for production watchers
- Rotate watcher ownership via transferWatcherOwnership if keys are compromised
- The Energy Type Admin is a separate role — delegate it to reduce owner key exposure
Attester Isolation
Per-project attester whitelisting ensures that a compromised IoT device can only affect a single project. This is the recommended pattern for device-level access:
| Pattern | Scope | Risk if Compromised |
|---|---|---|
| Per-project attester | One project only | Attacker can only submit false readings for that project |
| Watcher-wide attester | All projects under watcher | Attacker can submit false readings for any project |
Note
Warning: Use watcher-wide attesters sparingly. Reserve them for trusted manual operators, not IoT devices.
Data Integrity
- Duplicate period detection prevents double-counting — the same time window cannot be attested twice
- Strict start-time uniqueness prevents overlapping periods starting at the same timestamp
- Energy accumulators are updated atomically with each attestation and revocation
- Revocations decrement accumulators correctly, preventing inflated totals
- The registry is permanent — historical data cannot be altered or deleted
Contract Safety
- Both contracts disable renounceOwnership() to prevent accidental lockout
- Ownership transfer uses OpenZeppelin Ownable2Step (requires the new owner to accept)
- The resolver is pausable for emergency stops — revocations still work when paused
- The contract holds no ETH or tokens — attack surface is limited to data integrity
- 152 tests cover the full protocol including edge cases and boundary values
Upgrade Safety
The two-contract design ensures upgrades are safe:
- The registry is never replaced — all state is preserved across resolver upgrades
- Multiple resolvers can be authorized simultaneously for zero-downtime migration
- The old resolver can be paused and deauthorized after migration
- No proxy pattern is used — the registry is a plain contract, not upgradeable