aere-contracts/test/block-stm-registry.test.js
Aere Network a13a649b77
Some checks are pending
contracts-ci / Install (lockfile) → compile → full test suite (push) Waiting to run
contracts-ci / PQC known-answer tests (NIST vectors) (push) Waiting to run
contracts-ci / Coverage (scoped, with artifacts) (push) Waiting to run
Initial public release
Aere Network public source. Everything here can be checked against the live
chain (chain id 2800, https://rpc.aere.network).

Scope note, stated up front rather than buried: consensus on chain 2800 is
classical secp256k1 ECDSA QBFT. The post-quantum work in this repository is at
the signature, precompile, account and transport layers. Nothing here makes the
consensus post-quantum, and no document in it should be read as claiming so.
2026-07-20 01:02:37 +03:00

76 lines
3.1 KiB
JavaScript

const { expect } = require("chai");
const { ethers } = require("hardhat");
describe("AereBlockSTMRegistry", () => {
let alice, bob, target;
let reg;
const SELECTOR = "0x12345678";
const SLOT_A = ethers.keccak256(ethers.toUtf8Bytes("slot-a"));
const SLOT_B = ethers.keccak256(ethers.toUtf8Bytes("slot-b"));
beforeEach(async () => {
[alice, bob, target] = await ethers.getSigners();
const F = await ethers.getContractFactory("AereBlockSTMRegistry");
reg = await F.deploy();
await reg.waitForDeployment();
});
it("first publisher claims (target, selector); only they can update", async () => {
// AUDIT FIX (HIGH #27): first publisher must be target itself OR target's owner.
// We have `target` as an EOA so we use it as msg.sender (== target.address).
await reg.connect(target).publish(target.address, SELECTOR, [
{ slotPrefix: SLOT_A, mode: 0 /*READ*/ },
{ slotPrefix: SLOT_B, mode: 1 /*WRITE*/ },
]);
expect(await reg.publisherOf(target.address, SELECTOR)).to.equal(target.address);
// Random alice cannot squat someone else's (target, selector).
await expect(
reg.connect(alice).publish(target.address, SELECTOR, [{ slotPrefix: SLOT_A, mode: 0 }])
).to.be.revertedWithCustomError(reg, "NotPublisher");
// Bob can't either.
await expect(
reg.connect(bob).publish(target.address, SELECTOR, [{ slotPrefix: SLOT_A, mode: 0 }])
).to.be.revertedWithCustomError(reg, "NotPublisher");
});
it("hintsFor returns the latest set + count is correct", async () => {
await reg.connect(target).publish(target.address, SELECTOR, [
{ slotPrefix: SLOT_A, mode: 2 /*READWRITE*/ },
]);
const out = await reg.hintsFor(target.address, SELECTOR);
expect(out.publisher).to.equal(target.address);
expect(out.hints.length).to.equal(1);
expect(out.hints[0].slotPrefix).to.equal(SLOT_A);
expect(out.hints[0].mode).to.equal(2);
});
it("publish replaces previous hints (not append)", async () => {
await reg.connect(target).publish(target.address, SELECTOR, [
{ slotPrefix: SLOT_A, mode: 0 }, { slotPrefix: SLOT_B, mode: 0 },
]);
await reg.connect(target).publish(target.address, SELECTOR, [
{ slotPrefix: SLOT_A, mode: 1 },
]);
const out = await reg.hintsFor(target.address, SELECTOR);
expect(out.hints.length).to.equal(1);
expect(out.hints[0].mode).to.equal(1);
});
it("rejects > 64 hints", async () => {
const hints = [];
for (let i = 0; i < 65; i++) hints.push({ slotPrefix: SLOT_A, mode: 0 });
await expect(
reg.connect(target).publish(target.address, SELECTOR, hints)
).to.be.revertedWithCustomError(reg, "TooManyHints");
});
it("clear only by publisher; emits", async () => {
await reg.connect(target).publish(target.address, SELECTOR, [{ slotPrefix: SLOT_A, mode: 0 }]);
await expect(reg.connect(bob).clear(target.address, SELECTOR)).to.be.revertedWithCustomError(reg, "NotPublisher");
await expect(reg.connect(target).clear(target.address, SELECTOR)).to.emit(reg, "HintsCleared");
const out = await reg.hintsFor(target.address, SELECTOR);
expect(out.hints.length).to.equal(0);
});
});