[marketplace] Reward is paid out per second per slot

This commit is contained in:
Mark Spanbroek 2022-07-20 11:07:20 +02:00 committed by markspanbroek
parent 1d951ef8f8
commit 3e9fffb526
4 changed files with 38 additions and 18 deletions

View File

@ -39,9 +39,10 @@ contract Marketplace is Collateral, Proofs {
_createLock(id, request.expiry); _createLock(id, request.expiry);
funds.received += request.ask.reward; uint256 amount = price(request);
funds.balance += request.ask.reward; funds.received += amount;
transferFrom(msg.sender, request.ask.reward); funds.balance += amount;
transferFrom(msg.sender, amount);
emit StorageRequested(id, request.ask); emit StorageRequested(id, request.ask);
} }
@ -84,7 +85,7 @@ contract Marketplace is Collateral, Proofs {
Slot storage slot = slots[slotId]; Slot storage slot = slots[slotId];
require(slot.host != address(0), "Slot empty"); require(slot.host != address(0), "Slot empty");
require(!slot.hostPaid, "Already paid"); require(!slot.hostPaid, "Already paid");
uint256 amount = requests[requestId].ask.reward; uint256 amount = pricePerSlot(requests[requestId]);
funds.sent += amount; funds.sent += amount;
funds.balance -= amount; funds.balance -= amount;
slot.hostPaid = true; slot.hostPaid = true;
@ -111,6 +112,14 @@ contract Marketplace is Collateral, Proofs {
return _end(contractId); 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 { struct Request {
address client; address client;
Ask ask; Ask ask;
@ -123,7 +132,7 @@ contract Marketplace is Collateral, Proofs {
uint256 size; // size of requested storage in number of bytes uint256 size; // size of requested storage in number of bytes
uint256 duration; // how long content should be stored (in seconds) uint256 duration; // how long content should be stored (in seconds)
uint256 proofProbability; // how often storage proofs are required 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 uint64 slots; // the total number of hosts that store the data set
} }

View File

@ -4,6 +4,7 @@ const { expect } = require("chai")
const { exampleRequest } = require("./examples") const { exampleRequest } = require("./examples")
const { now, hours } = require("./time") const { now, hours } = require("./time")
const { requestId, slotId, askToArray } = require("./ids") const { requestId, slotId, askToArray } = require("./ids")
const { price, pricePerSlot } = require("./price")
const { const {
snapshot, snapshot,
revert, revert,
@ -33,7 +34,7 @@ describe("Marketplace", function () {
const TestToken = await ethers.getContractFactory("TestToken") const TestToken = await ethers.getContractFactory("TestToken")
token = await TestToken.deploy() token = await TestToken.deploy()
for (account of [client, host1, host2, host3]) { 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") const Marketplace = await ethers.getContractFactory("Marketplace")
@ -69,7 +70,7 @@ describe("Marketplace", function () {
}) })
it("emits event when storage is requested", async 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)) await expect(marketplace.requestStorage(request))
.to.emit(marketplace, "StorageRequested") .to.emit(marketplace, "StorageRequested")
.withArgs(requestId(request), askToArray(request.ask)) .withArgs(requestId(request), askToArray(request.ask))
@ -77,14 +78,14 @@ describe("Marketplace", function () {
it("rejects request with invalid client address", async function () { it("rejects request with invalid client address", async function () {
let invalid = { ...request, client: host.address } 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( await expect(marketplace.requestStorage(invalid)).to.be.revertedWith(
"Invalid client address" "Invalid client address"
) )
}) })
it("rejects request with insufficient payment", async function () { 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 token.approve(marketplace.address, insufficient)
await expect(marketplace.requestStorage(request)).to.be.revertedWith( await expect(marketplace.requestStorage(request)).to.be.revertedWith(
"ERC20: insufficient allowance" "ERC20: insufficient allowance"
@ -92,7 +93,7 @@ describe("Marketplace", function () {
}) })
it("rejects resubmission of request", async 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 marketplace.requestStorage(request)
await expect(marketplace.requestStorage(request)).to.be.revertedWith( await expect(marketplace.requestStorage(request)).to.be.revertedWith(
"Request already exists" "Request already exists"
@ -103,7 +104,7 @@ describe("Marketplace", function () {
describe("filling a slot", function () { describe("filling a slot", function () {
beforeEach(async function () { beforeEach(async function () {
switchAccount(client) switchAccount(client)
await token.approve(marketplace.address, request.ask.reward) await token.approve(marketplace.address, price(request))
await marketplace.requestStorage(request) await marketplace.requestStorage(request)
switchAccount(host) switchAccount(host)
await token.approve(marketplace.address, collateral) await token.approve(marketplace.address, collateral)
@ -160,7 +161,7 @@ describe("Marketplace", function () {
it("is rejected when request is expired", async function () { it("is rejected when request is expired", async function () {
switchAccount(client) switchAccount(client)
let expired = { ...request, expiry: now() - hours(1) } 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) await marketplace.requestStorage(expired)
switchAccount(host) switchAccount(host)
await expect( await expect(
@ -179,7 +180,7 @@ describe("Marketplace", function () {
describe("paying out a slot", function () { describe("paying out a slot", function () {
beforeEach(async function () { beforeEach(async function () {
switchAccount(client) switchAccount(client)
await token.approve(marketplace.address, request.ask.reward) await token.approve(marketplace.address, price(request))
await marketplace.requestStorage(request) await marketplace.requestStorage(request)
switchAccount(host) switchAccount(host)
await token.approve(marketplace.address, collateral) await token.approve(marketplace.address, collateral)
@ -197,7 +198,7 @@ describe("Marketplace", function () {
const startBalance = await token.balanceOf(host.address) const startBalance = await token.balanceOf(host.address)
await marketplace.payoutSlot(slot.request, slot.index) await marketplace.payoutSlot(slot.request, slot.index)
const endBalance = await token.balanceOf(host.address) 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 () { it("is only allowed when the slot is filled", async function () {
@ -234,7 +235,7 @@ describe("Marketplace", function () {
describe("fulfilling a request", function () { describe("fulfilling a request", function () {
beforeEach(async function () { beforeEach(async function () {
switchAccount(client) switchAccount(client)
await token.approve(marketplace.address, request.ask.reward) await token.approve(marketplace.address, price(request))
await marketplace.requestStorage(request) await marketplace.requestStorage(request)
switchAccount(host) switchAccount(host)
await token.approve(marketplace.address, collateral) await token.approve(marketplace.address, collateral)

View File

@ -6,6 +6,7 @@ const { exampleRequest } = require("./examples")
const { advanceTime, advanceTimeTo, currentTime } = require("./evm") const { advanceTime, advanceTimeTo, currentTime } = require("./evm")
const { requestId, slotId } = require("./ids") const { requestId, slotId } = require("./ids")
const { periodic } = require("./time") const { periodic } = require("./time")
const { price } = require("./price")
describe("Storage", function () { describe("Storage", function () {
const proof = hexlify(randomBytes(42)) const proof = hexlify(randomBytes(42))
@ -29,8 +30,8 @@ describe("Storage", function () {
token = await ethers.getContract("TestToken") token = await ethers.getContract("TestToken")
storage = await ethers.getContract("Storage") storage = await ethers.getContract("Storage")
await token.mint(client.address, 1000) await token.mint(client.address, 1_000_000_000)
await token.mint(host.address, 1000) await token.mint(host.address, 1_000_000_000)
collateralAmount = await storage.collateralAmount() collateralAmount = await storage.collateralAmount()
slashMisses = await storage.slashMisses() slashMisses = await storage.slashMisses()
@ -44,7 +45,7 @@ describe("Storage", function () {
} }
switchAccount(client) switchAccount(client)
await token.approve(storage.address, request.ask.reward) await token.approve(storage.address, price(request))
await storage.requestStorage(request) await storage.requestStorage(request)
switchAccount(host) switchAccount(host)
await token.approve(storage.address, collateralAmount) await token.approve(storage.address, collateralAmount)

9
test/price.js Normal file
View File

@ -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 }