Submitting Attestations
Attestations are the core of EnergyAS — on-chain energy readings that are permanent, verifiable, and auditable by anyone.
Prepare Your Data
Each attestation contains interval readings in watt-hours (Wh). For example, 24 hourly readings from a solar farm:
JSON
{
"project_id": 1,
"reading_count": 24,
"reading_interval": 60,
"readings": [0, 0, 0, 0, 0, 15000, 45000, 120000,
280000, 410000, 520000, 580000, 590000,
560000, 480000, 350000, 200000, 80000,
20000, 0, 0, 0, 0, 0],
"from_timestamp": "1700000000",
"method": "iot",
"energy_type": 1,
"metadata_uri": "ipfs://QmReportHash"
}Submit via Script
Terminal
npx hardhat run scripts/attest.ts --network <network>The script can load from a JSON file or prompt interactively. It encodes the data, submits to EAS, and the resolver validates and records the attestation.
Submit via Code
JavaScript
import { AbiCoder, ZeroAddress, ZeroHash } from 'ethers';
const data = AbiCoder.defaultAbiCoder().encode(
["uint64", "uint32", "uint32", "uint256[]", "uint64",
"string", "uint8", "string"],
[projectId, readingCount, intervalMinutes, readings,
fromTimestamp, "iot", energyType, metadataURI]
);
const tx = await eas.attest({
schema: schemaUID,
data: {
recipient: ZeroAddress,
expirationTime: 0,
revocable: true,
refUID: ZeroHash,
data,
value: 0n
}
});
const receipt = await tx.wait();Batch Attestations
Use EAS multiAttest() to submit multiple readings in a single transaction:
JavaScript
const items = reports.map(report => ({
schema: schemaUID,
data: [{
recipient: ZeroAddress,
expirationTime: 0,
revocable: true,
refUID: ZeroHash,
data: encodeReport(report),
value: 0n
}]
}));
await eas.multiAttest(items);Corrections
To correct a reading, first revoke the original attestation, then re-submit:
JavaScript
// 1. Revoke the incorrect attestation
await eas.revoke({
schema: schemaUID,
data: { uid: originalAttestationUID, value: 0n }
});
// 2. Re-submit with corrected data
await eas.attest({ ... });Note
Revocation clears the period lock, allowing the same time window to be re-attested. Revocations always work, even when the resolver is paused.