From 3e9fffb5264bf7ab7ac9718d69608c87afeaca9c Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Wed, 20 Jul 2022 11:07:20 +0200 Subject: [PATCH] [marketplace] Reward is paid out per second per slot --- contracts/Marketplace.sol | 19 ++++++++++++++----- test/Marketplace.test.js | 21 +++++++++++---------- test/Storage.test.js | 7 ++++--- test/price.js | 9 +++++++++ 4 files changed, 38 insertions(+), 18 deletions(-) create mode 100644 test/price.js diff --git a/contracts/Marketplace.sol b/contracts/Marketplace.sol index 7f5e072..c778581 100644 --- a/contracts/Marketplace.sol +++ b/contracts/Marketplace.sol @@ -39,9 +39,10 @@ contract Marketplace is Collateral, Proofs { _createLock(id, request.expiry); - funds.received += request.ask.reward; - funds.balance += request.ask.reward; - transferFrom(msg.sender, request.ask.reward); + uint256 amount = price(request); + funds.received += amount; + funds.balance += amount; + transferFrom(msg.sender, amount); emit StorageRequested(id, request.ask); } @@ -84,7 +85,7 @@ contract Marketplace is Collateral, Proofs { Slot storage slot = slots[slotId]; require(slot.host != address(0), "Slot empty"); require(!slot.hostPaid, "Already paid"); - uint256 amount = requests[requestId].ask.reward; + uint256 amount = pricePerSlot(requests[requestId]); funds.sent += amount; funds.balance -= amount; slot.hostPaid = true; @@ -111,6 +112,14 @@ contract Marketplace is Collateral, Proofs { return _end(contractId); } + function price(Request calldata request) private pure returns (uint256) { + return request.ask.slots * request.ask.duration * request.ask.reward; + } + + function pricePerSlot(Request memory request) private pure returns (uint256) { + return request.ask.duration * request.ask.reward; + } + struct Request { address client; Ask ask; @@ -123,7 +132,7 @@ contract Marketplace is Collateral, Proofs { uint256 size; // size of requested storage in number of bytes uint256 duration; // how long content should be stored (in seconds) uint256 proofProbability; // how often storage proofs are required - uint256 reward; // reward that the client will pay (in number of tokens) + uint256 reward; // amount of tokens paid per second per slot to hosts uint64 slots; // the total number of hosts that store the data set } diff --git a/test/Marketplace.test.js b/test/Marketplace.test.js index 8a66b17..823490b 100644 --- a/test/Marketplace.test.js +++ b/test/Marketplace.test.js @@ -4,6 +4,7 @@ const { expect } = require("chai") const { exampleRequest } = require("./examples") const { now, hours } = require("./time") const { requestId, slotId, askToArray } = require("./ids") +const { price, pricePerSlot } = require("./price") const { snapshot, revert, @@ -33,7 +34,7 @@ describe("Marketplace", function () { const TestToken = await ethers.getContractFactory("TestToken") token = await TestToken.deploy() for (account of [client, host1, host2, host3]) { - await token.mint(account.address, 1000) + await token.mint(account.address, 1_000_000_000) } const Marketplace = await ethers.getContractFactory("Marketplace") @@ -69,7 +70,7 @@ describe("Marketplace", function () { }) it("emits event when storage is requested", async function () { - await token.approve(marketplace.address, request.ask.reward) + await token.approve(marketplace.address, price(request)) await expect(marketplace.requestStorage(request)) .to.emit(marketplace, "StorageRequested") .withArgs(requestId(request), askToArray(request.ask)) @@ -77,14 +78,14 @@ describe("Marketplace", function () { it("rejects request with invalid client address", async function () { let invalid = { ...request, client: host.address } - await token.approve(marketplace.address, invalid.ask.reward) + await token.approve(marketplace.address, price(invalid)) await expect(marketplace.requestStorage(invalid)).to.be.revertedWith( "Invalid client address" ) }) it("rejects request with insufficient payment", async function () { - let insufficient = request.ask.reward - 1 + let insufficient = price(request) - 1 await token.approve(marketplace.address, insufficient) await expect(marketplace.requestStorage(request)).to.be.revertedWith( "ERC20: insufficient allowance" @@ -92,7 +93,7 @@ describe("Marketplace", function () { }) it("rejects resubmission of request", async function () { - await token.approve(marketplace.address, request.ask.reward * 2) + await token.approve(marketplace.address, price(request) * 2) await marketplace.requestStorage(request) await expect(marketplace.requestStorage(request)).to.be.revertedWith( "Request already exists" @@ -103,7 +104,7 @@ describe("Marketplace", function () { describe("filling a slot", function () { beforeEach(async function () { switchAccount(client) - await token.approve(marketplace.address, request.ask.reward) + await token.approve(marketplace.address, price(request)) await marketplace.requestStorage(request) switchAccount(host) await token.approve(marketplace.address, collateral) @@ -160,7 +161,7 @@ describe("Marketplace", function () { it("is rejected when request is expired", async function () { switchAccount(client) let expired = { ...request, expiry: now() - hours(1) } - await token.approve(marketplace.address, request.ask.reward) + await token.approve(marketplace.address, price(request)) await marketplace.requestStorage(expired) switchAccount(host) await expect( @@ -179,7 +180,7 @@ describe("Marketplace", function () { describe("paying out a slot", function () { beforeEach(async function () { switchAccount(client) - await token.approve(marketplace.address, request.ask.reward) + await token.approve(marketplace.address, price(request)) await marketplace.requestStorage(request) switchAccount(host) await token.approve(marketplace.address, collateral) @@ -197,7 +198,7 @@ describe("Marketplace", function () { const startBalance = await token.balanceOf(host.address) await marketplace.payoutSlot(slot.request, slot.index) const endBalance = await token.balanceOf(host.address) - expect(endBalance - startBalance).to.equal(request.ask.reward) + expect(endBalance - startBalance).to.equal(pricePerSlot(request)) }) it("is only allowed when the slot is filled", async function () { @@ -234,7 +235,7 @@ describe("Marketplace", function () { describe("fulfilling a request", function () { beforeEach(async function () { switchAccount(client) - await token.approve(marketplace.address, request.ask.reward) + await token.approve(marketplace.address, price(request)) await marketplace.requestStorage(request) switchAccount(host) await token.approve(marketplace.address, collateral) diff --git a/test/Storage.test.js b/test/Storage.test.js index 4479b6c..a3a76ba 100644 --- a/test/Storage.test.js +++ b/test/Storage.test.js @@ -6,6 +6,7 @@ const { exampleRequest } = require("./examples") const { advanceTime, advanceTimeTo, currentTime } = require("./evm") const { requestId, slotId } = require("./ids") const { periodic } = require("./time") +const { price } = require("./price") describe("Storage", function () { const proof = hexlify(randomBytes(42)) @@ -29,8 +30,8 @@ describe("Storage", function () { token = await ethers.getContract("TestToken") storage = await ethers.getContract("Storage") - await token.mint(client.address, 1000) - await token.mint(host.address, 1000) + await token.mint(client.address, 1_000_000_000) + await token.mint(host.address, 1_000_000_000) collateralAmount = await storage.collateralAmount() slashMisses = await storage.slashMisses() @@ -44,7 +45,7 @@ describe("Storage", function () { } switchAccount(client) - await token.approve(storage.address, request.ask.reward) + await token.approve(storage.address, price(request)) await storage.requestStorage(request) switchAccount(host) await token.approve(storage.address, collateralAmount) diff --git a/test/price.js b/test/price.js new file mode 100644 index 0000000..f3dca53 --- /dev/null +++ b/test/price.js @@ -0,0 +1,9 @@ +function price(request) { + return request.ask.slots * pricePerSlot(request) +} + +function pricePerSlot(request) { + return request.ask.duration * request.ask.reward +} + +module.exports = { price, pricePerSlot }