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.
79 lines
3.8 KiB
JavaScript
79 lines
3.8 KiB
JavaScript
const { expect } = require("chai");
|
|
const { ethers } = require("hardhat");
|
|
|
|
describe("AereComputeMarket (DePIN)", function () {
|
|
async function deploy() {
|
|
const [foundation, provider, requester, other] = await ethers.getSigners();
|
|
const M = await ethers.getContractFactory("AereComputeMarket");
|
|
const m = await M.deploy(foundation.address);
|
|
await m.waitForDeployment();
|
|
return { m, foundation, provider, requester, other };
|
|
}
|
|
const STAKE = ethers.parseEther("10");
|
|
const PAY = ethers.parseEther("1");
|
|
const spec = ethers.id("train-model-x");
|
|
|
|
it("full happy path: register → post → claim → submit → confirm → paid", async function () {
|
|
const { m, provider, requester } = await deploy();
|
|
await m.connect(provider).registerProvider(1000, "https://p.example", { value: STAKE });
|
|
await m.connect(requester).postJob(spec, { value: PAY });
|
|
await m.connect(provider).claimJob(0);
|
|
await m.connect(provider).submitResult(0, ethers.id("result"));
|
|
const before = await ethers.provider.getBalance(provider.address);
|
|
await m.connect(requester).confirmJob(0);
|
|
const after = await ethers.provider.getBalance(provider.address);
|
|
expect(after - before).to.be.closeTo(PAY, ethers.parseEther("0.001"));
|
|
expect((await m.jobs(0)).status).to.equal(4); // Paid
|
|
});
|
|
|
|
it("rejects under-stake provider + non-provider claim", async function () {
|
|
const { m, provider, requester, other } = await deploy();
|
|
await expect(m.connect(provider).registerProvider(1, "x", { value: ethers.parseEther("9") }))
|
|
.to.be.revertedWithCustomError(m, "BadStake");
|
|
await m.connect(requester).postJob(spec, { value: PAY });
|
|
await expect(m.connect(other).claimJob(0)).to.be.revertedWithCustomError(m, "NotProvider");
|
|
});
|
|
|
|
it("cancel unclaimed job refunds requester", async function () {
|
|
const { m, requester } = await deploy();
|
|
await m.connect(requester).postJob(spec, { value: PAY });
|
|
await m.connect(requester).cancelJob(0);
|
|
expect((await m.jobs(0)).status).to.equal(5); // Refunded
|
|
});
|
|
|
|
it("autoConfirm after window pays provider; not before", async function () {
|
|
const { m, provider, requester } = await deploy();
|
|
await m.connect(provider).registerProvider(1, "x", { value: STAKE });
|
|
await m.connect(requester).postJob(spec, { value: PAY });
|
|
await m.connect(provider).claimJob(0);
|
|
await m.connect(provider).submitResult(0, ethers.id("r"));
|
|
await expect(m.autoConfirm(0)).to.be.revertedWithCustomError(m, "WindowOpen");
|
|
await ethers.provider.send("evm_increaseTime", [3 * 24 * 3600 + 1]);
|
|
await ethers.provider.send("evm_mine", []);
|
|
await m.autoConfirm(0);
|
|
expect((await m.jobs(0)).status).to.equal(4); // Paid
|
|
});
|
|
|
|
it("dispute → Foundation slashes provider, refunds requester", async function () {
|
|
const { m, foundation, provider, requester } = await deploy();
|
|
await m.connect(provider).registerProvider(1, "x", { value: STAKE });
|
|
await m.connect(requester).postJob(spec, { value: PAY });
|
|
await m.connect(provider).claimJob(0);
|
|
await m.connect(provider).submitResult(0, ethers.id("bad"));
|
|
await m.connect(requester).disputeJob(0);
|
|
await m.connect(foundation).resolveDispute(0, false); // provider loses
|
|
expect((await m.jobs(0)).status).to.equal(6); // Slashed
|
|
const p = await m.providers(provider.address);
|
|
expect(p.stake).to.equal(ethers.parseEther("5")); // 50% slashed
|
|
expect(await m.slashPool()).to.equal(ethers.parseEther("5"));
|
|
});
|
|
|
|
it("provider cannot deregister with active jobs", async function () {
|
|
const { m, provider, requester } = await deploy();
|
|
await m.connect(provider).registerProvider(1, "x", { value: STAKE });
|
|
await m.connect(requester).postJob(spec, { value: PAY });
|
|
await m.connect(provider).claimJob(0);
|
|
await expect(m.connect(provider).deregisterProvider()).to.be.revertedWithCustomError(m, "HasActiveJobs");
|
|
});
|
|
});
|