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.
142 lines
5.7 KiB
JavaScript
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);
|
|
});
|
|
});
|