aere-contracts/test/cancun-canary.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

142 lines
5.7 KiB
JavaScript

// cancun-canary.test.js
//
// Proves the Cancun EVM feature set behind AereCancunCanary.sol, compiled
// with solc 0.8.24 evmVersion=cancun via the per-file hardhat override
// (the repo global stays 0.8.23). The local hardhat network runs with
// hardfork: "cancun" (see hardhat.config.js), so these tests exercise the
// real opcodes:
// - TSTORE/TLOAD same-tx round-trip (EIP-1153)
// - transient auto-reset between two SEPARATE transactions
// - transient reentrancy lock (inner self-call must revert)
// - MCOPY round-trip keccak equality (EIP-5656), multiple sizes
// - BLOBHASH(0) == 0 and BLOBBASEFEE executes (EIP-4844 / EIP-7516)
// - PUSH0 (EIP-3855) present at genuine opcode positions in the runtime
// bytecode (opcode-walk, not a naive substring scan)
const { expect } = require("chai");
const { ethers } = require("hardhat");
/**
* Walk EVM bytecode from offset 0, skipping PUSH1..PUSH32 immediates, and
* count 0x5f (PUSH0) at genuine opcode positions. Stops at the first
* INVALID (0xfe) since solc places non-code data (metadata) after it.
*/
function countPush0(bytecodeHex) {
const code = Buffer.from(bytecodeHex.replace(/^0x/, ""), "hex");
let i = 0;
let push0 = 0;
while (i < code.length) {
const op = code[i];
if (op === 0xfe) break; // INVALID: data section follows
if (op === 0x5f) push0++;
if (op >= 0x60 && op <= 0x7f) {
i += op - 0x60 + 1; // skip PUSHn immediate bytes
}
i += 1;
}
return push0;
}
describe("AereCancunCanary (solc 0.8.24, evmVersion=cancun)", () => {
let canary, deployer;
before(async () => {
[deployer] = await ethers.getSigners();
const F = await ethers.getContractFactory("AereCancunCanary");
canary = await F.deploy();
await canary.waitForDeployment();
});
it("constructor self-test passed (TSTORE/TLOAD + MCOPY + blob opcodes)", async () => {
expect(await canary.deploySelfTest()).to.equal(true);
// constructor also emitted BlobProbed(0x0, fee)
const rc = await canary.deploymentTransaction().wait();
const parsed = rc.logs
.map((l) => { try { return canary.interface.parseLog(l); } catch { return null; } })
.filter(Boolean);
const blob = parsed.find((e) => e.name === "BlobProbed");
expect(blob, "constructor BlobProbed event").to.not.equal(undefined);
expect(blob.args.blobHash0).to.equal(ethers.ZeroHash);
});
it("TSTORE/TLOAD: same-tx write + read-back round-trip", async () => {
const value = 0xa3e3n;
await expect(canary.transientWriteAndRead(value))
.to.emit(canary, "TransientWithinTx")
.withArgs(value, value);
});
it("transient storage auto-resets between two separate transactions", async () => {
// tx 1: write a non-zero value into the transient slot
const tx1 = await canary.transientWriteAndRead(999999n);
const rc1 = await tx1.wait();
// tx 2 (a LATER, separate transaction): the slot must read 0
const tx2 = await canary.transientReadOnly();
const rc2 = await tx2.wait();
expect(rc2.blockNumber).to.be.greaterThanOrEqual(rc1.blockNumber);
expect(tx2.hash).to.not.equal(tx1.hash);
const parsed = rc2.logs
.map((l) => { try { return canary.interface.parseLog(l); } catch { return null; } })
.filter(Boolean);
const ev = parsed.find((e) => e.name === "TransientCrossTx");
expect(ev.args.observed).to.equal(0n);
// and via eth_call as well
expect(await canary.transientPeek()).to.equal(0n);
});
it("transient reentrancy lock: inner self-call reverts, outer succeeds", async () => {
await expect(canary.guardedEnter(true))
.to.emit(canary, "ReentrancyLockProbe")
.withArgs(true, true); // reentry attempted, inner call reverted
// lock is released after the tx (both by the modifier and by the
// EVM transient reset)
expect(await canary.lockPeek()).to.equal(0n);
// a subsequent non-reentrant call goes straight through
await expect(canary.guardedEnter(false))
.to.emit(canary, "ReentrancyLockProbe")
.withArgs(false, false);
});
it("MCOPY: round-trip keccak equality across sizes 0..1024", async () => {
for (const n of [0, 1, 31, 32, 33, 256, 1024]) {
const data = n === 0 ? "0x" : ethers.hexlify(ethers.randomBytes(n));
const [inputHash, copyHash] = await canary.mcopyHash(data);
expect(copyHash, `mcopy size ${n}`).to.equal(inputHash);
expect(inputHash).to.equal(ethers.keccak256(data));
}
// transaction variant emits ok=true
const data = ethers.hexlify(ethers.randomBytes(777));
await expect(canary.mcopyCheck(data))
.to.emit(canary, "McopyChecked")
.withArgs(777n, ethers.keccak256(data), ethers.keccak256(data), true);
});
it("BLOBHASH(0) == 0 in a non-blob tx; BLOBBASEFEE executes", async () => {
const [h0, bbf] = await canary.blobView();
expect(h0).to.equal(ethers.ZeroHash);
expect(bbf).to.be.a("bigint"); // recorded, not asserted (min is 1 wei)
const tx = await canary.blobProbe();
const rc = await tx.wait();
const parsed = rc.logs
.map((l) => { try { return canary.interface.parseLog(l); } catch { return null; } })
.filter(Boolean);
const ev = parsed.find((e) => e.name === "BlobProbed");
expect(ev.args.blobHash0).to.equal(ethers.ZeroHash);
});
it("PUSH0: deployed runtime bytecode contains genuine 0x5f opcodes", async () => {
const code = await ethers.provider.getCode(await canary.getAddress());
expect(code.length).to.be.greaterThan(2);
const n = countPush0(code);
expect(n, "PUSH0 count at opcode positions").to.be.greaterThan(0);
// canonical solc cancun/shanghai revert stub PUSH0 DUP1 REVERT
expect(code.includes("5f80fd"), "5f80fd revert stub").to.equal(true);
});
});