const { expect } = require("chai") const { ethers } = require("hardhat") const { hashRequest, hashBid, sign } = require("./marketplace") describe("Storage Contract", function () { const duration = 31 * 24 * 60 * 60 // 31 days const size = 1 * 1024 * 1024 * 1024 // 1 Gigabyte const contentHash = ethers.utils.sha256("0xdeadbeef") // hash of content const proofPeriod = 8 // 8 blocks ≈ 2 minutes const proofTimeout = 4 // 4 blocks ≈ 1 minute const price = 42 var StorageContract var client, host var bidExpiry var requestHash, bidHash var contract beforeEach(async function () { [client, host] = await ethers.getSigners() StorageContract = await ethers.getContractFactory("StorageContract") requestHash = hashRequest( duration, size, contentHash, proofPeriod, proofTimeout ) bidExpiry = Math.round(Date.now() / 1000) + 60 * 60 // 1 hour from now bidHash = hashBid(requestHash, bidExpiry, price) }) describe("when properly instantiated", function () { beforeEach(async function () { contract = await StorageContract.deploy( duration, size, contentHash, price, proofPeriod, proofTimeout, bidExpiry, await host.getAddress(), await sign(client, requestHash), await sign(host, bidHash) ) }) it("has a duration", async function () { expect(await contract.duration()).to.equal(duration) }) it("contains the size of the data that is to be stored", async function () { expect(await contract.size()).to.equal(size) }) it("contains the hash of the data that is to be stored", async function () { expect(await contract.contentHash()).to.equal(contentHash) }) it("has a price", async function () { expect(await contract.price()).to.equal(price) }) it("knows the host that provides the storage", async function () { expect(await contract.host()).to.equal(await host.getAddress()) }) it("has an average time between proofs (in blocks)", async function (){ expect(await contract.proofPeriod()).to.equal(proofPeriod) }) it("has a proof timeout (in blocks)", async function (){ expect(await contract.proofTimeout()).to.equal(proofTimeout) }) }) it("cannot be created when client signature is invalid", async function () { let invalidHash = hashRequest( duration + 1, size, contentHash, proofPeriod, proofTimeout ) let invalidSignature = await sign(client, invalidHash) await expect(StorageContract.deploy( duration, size, contentHash, price, proofPeriod, proofTimeout, bidExpiry, await host.getAddress(), invalidSignature, await sign(host, bidHash) )).to.be.revertedWith("Invalid signature") }) it("cannot be created when host signature is invalid", async function () { let invalidBid = hashBid(requestHash, bidExpiry, price - 1) let invalidSignature = await sign(host, invalidBid) await expect(StorageContract.deploy( duration, size, contentHash, price, proofPeriod, proofTimeout, bidExpiry, await host.getAddress(), await sign(client, requestHash), invalidSignature )).to.be.revertedWith("Invalid signature") }) it("cannot be created when proof timeout is too large", async function () { let invalidTimeout = 129 // max proof timeout is 128 blocks requestHash = hashRequest( duration, size, contentHash, proofPeriod, invalidTimeout ) bidHash = hashBid(requestHash, bidExpiry, price) await expect(StorageContract.deploy( duration, size, contentHash, price, proofPeriod, invalidTimeout, bidExpiry, await host.getAddress(), await sign(client, requestHash), await sign(host, bidHash), )).to.be.revertedWith("Invalid proof timeout") }) it("cannot be created when bid has expired", async function () { let expired = Math.round(Date.now() / 1000) - 60 // 1 minute ago let bidHash = hashBid(requestHash, expired, price) await expect(StorageContract.deploy( duration, size, contentHash, price, proofPeriod, proofTimeout, expired, await host.getAddress(), await sign(client, requestHash), await sign(host, bidHash), )).to.be.revertedWith("Bid expired") }) describe("proofs", function () { async function mineBlock() { await ethers.provider.send("evm_mine") } async function minedBlockNumber() { return await ethers.provider.getBlockNumber() - 1 } async function mineUntilProofIsRequired() { while (!await contract.isProofRequired(await minedBlockNumber())) { mineBlock() } } beforeEach(async function () { contract = await StorageContract.deploy( duration, size, contentHash, price, proofPeriod, proofTimeout, bidExpiry, await host.getAddress(), await sign(client, requestHash), await sign(host, bidHash) ) }) it("requires on average a proof every period", async function () { let blocks = 400 let proofs = 0 for (i=0; i