mirror of
https://github.com/status-im/dagger-contracts.git
synced 2025-02-13 15:18:48 +00:00
[marketplace] Add slots
This commit is contained in:
parent
97ef1bcd9f
commit
141abce186
@ -10,6 +10,7 @@ contract Marketplace is Collateral, Proofs {
|
||||
MarketplaceFunds private funds;
|
||||
mapping(bytes32 => Request) private requests;
|
||||
mapping(bytes32 => RequestState) private requestState;
|
||||
mapping(bytes32 => Slot) private slots;
|
||||
|
||||
constructor(
|
||||
IERC20 _token,
|
||||
@ -45,6 +46,30 @@ contract Marketplace is Collateral, Proofs {
|
||||
emit StorageRequested(id, request.ask);
|
||||
}
|
||||
|
||||
function fillSlot(
|
||||
bytes32 requestId,
|
||||
uint256 slotIndex,
|
||||
bytes calldata proof
|
||||
) public marketplaceInvariant {
|
||||
Request storage request = requests[requestId];
|
||||
require(request.client != address(0), "Unknown request");
|
||||
require(request.expiry > block.timestamp, "Request expired");
|
||||
require(slotIndex < request.content.erasure.totalNodes, "Invalid slot");
|
||||
|
||||
bytes32 slotId = keccak256(abi.encode(requestId, slotIndex));
|
||||
Slot storage slot = slots[slotId];
|
||||
require(slot.host == address(0), "Slot already filled");
|
||||
|
||||
require(balanceOf(msg.sender) >= collateral, "Insufficient collateral");
|
||||
_lock(msg.sender, requestId);
|
||||
|
||||
_expectProofs(slotId, request.ask.proofProbability, request.ask.duration);
|
||||
_submitProof(slotId, proof);
|
||||
|
||||
slot.host = msg.sender;
|
||||
emit SlotFilled(requestId, slotIndex, slotId);
|
||||
}
|
||||
|
||||
function fulfillRequest(bytes32 requestId, bytes calldata proof)
|
||||
public
|
||||
marketplaceInvariant
|
||||
@ -127,8 +152,17 @@ contract Marketplace is Collateral, Proofs {
|
||||
address host;
|
||||
}
|
||||
|
||||
struct Slot {
|
||||
address host;
|
||||
}
|
||||
|
||||
event StorageRequested(bytes32 requestId, Ask ask);
|
||||
event RequestFulfilled(bytes32 indexed requestId);
|
||||
event SlotFilled(
|
||||
bytes32 indexed requestId,
|
||||
uint256 indexed slotIndex,
|
||||
bytes32 indexed slotId
|
||||
);
|
||||
|
||||
modifier marketplaceInvariant() {
|
||||
MarketplaceFunds memory oldFunds = funds;
|
||||
|
@ -4,7 +4,7 @@ const { expect } = require("chai")
|
||||
const { exampleRequest } = require("./examples")
|
||||
const { snapshot, revert, ensureMinimumBlockHeight } = require("./evm")
|
||||
const { now, hours } = require("./time")
|
||||
const { requestId, askToArray } = require("./ids")
|
||||
const { requestId, slotId, askToArray } = require("./ids")
|
||||
|
||||
describe("Marketplace", function () {
|
||||
const collateral = 100
|
||||
@ -88,6 +88,89 @@ describe("Marketplace", function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe("filling a slot", function () {
|
||||
const proof = hexlify(randomBytes(42))
|
||||
let slot
|
||||
|
||||
beforeEach(async function () {
|
||||
switchAccount(client)
|
||||
await token.approve(marketplace.address, request.ask.reward)
|
||||
await marketplace.requestStorage(request)
|
||||
switchAccount(host)
|
||||
await token.approve(marketplace.address, collateral)
|
||||
await marketplace.deposit(collateral)
|
||||
slot = {
|
||||
request: requestId(request),
|
||||
index: request.content.erasure.totalNodes / 2,
|
||||
}
|
||||
})
|
||||
|
||||
it("emits event when slot is filled", async function () {
|
||||
await expect(marketplace.fillSlot(slot.request, slot.index, proof))
|
||||
.to.emit(marketplace, "SlotFilled")
|
||||
.withArgs(slot.request, slot.index, slotId(slot))
|
||||
})
|
||||
|
||||
it("locks collateral of host", async function () {
|
||||
await marketplace.fillSlot(slot.request, slot.index, proof)
|
||||
await expect(marketplace.withdraw()).to.be.revertedWith("Account locked")
|
||||
})
|
||||
|
||||
it("starts requiring storage proofs", async function () {
|
||||
await marketplace.fillSlot(slot.request, slot.index, proof)
|
||||
expect(await marketplace.proofEnd(slotId(slot))).to.be.gt(0)
|
||||
})
|
||||
|
||||
it("is rejected when proof is incorrect", async function () {
|
||||
let invalid = hexlify([])
|
||||
await expect(
|
||||
marketplace.fillSlot(slot.request, slot.index, invalid)
|
||||
).to.be.revertedWith("Invalid proof")
|
||||
})
|
||||
|
||||
it("is rejected when collateral is insufficient", async function () {
|
||||
let insufficient = collateral - 1
|
||||
await marketplace.withdraw()
|
||||
await token.approve(marketplace.address, insufficient)
|
||||
await marketplace.deposit(insufficient)
|
||||
await expect(
|
||||
marketplace.fillSlot(slot.request, slot.index, proof)
|
||||
).to.be.revertedWith("Insufficient collateral")
|
||||
})
|
||||
|
||||
it("is rejected when slot already filled", async function () {
|
||||
await marketplace.fillSlot(slot.request, slot.index, proof)
|
||||
await expect(
|
||||
marketplace.fillSlot(slot.request, slot.index, proof)
|
||||
).to.be.revertedWith("Slot already filled")
|
||||
})
|
||||
|
||||
it("is rejected when request is unknown", async function () {
|
||||
let unknown = exampleRequest()
|
||||
await expect(
|
||||
marketplace.fillSlot(requestId(unknown), 0, proof)
|
||||
).to.be.revertedWith("Unknown request")
|
||||
})
|
||||
|
||||
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 marketplace.requestStorage(expired)
|
||||
switchAccount(host)
|
||||
await expect(
|
||||
marketplace.fillSlot(requestId(expired), slot.index, proof)
|
||||
).to.be.revertedWith("Request expired")
|
||||
})
|
||||
|
||||
it("is rejected when slot index not in range", async function () {
|
||||
const invalid = request.content.erasure.totalNodes
|
||||
await expect(
|
||||
marketplace.fillSlot(slot.request, invalid, proof)
|
||||
).to.be.revertedWith("Invalid slot")
|
||||
})
|
||||
})
|
||||
|
||||
describe("fulfilling request", function () {
|
||||
const proof = hexlify(randomBytes(42))
|
||||
|
||||
|
@ -39,8 +39,16 @@ function requestToArray(request) {
|
||||
]
|
||||
}
|
||||
|
||||
function slotId(slot) {
|
||||
const types = "tuple(bytes32, uint256)"
|
||||
const values = [slot.request, slot.index]
|
||||
const encoding = defaultAbiCoder.encode([types], [values])
|
||||
return keccak256(encoding)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
requestId,
|
||||
slotId,
|
||||
requestToArray,
|
||||
askToArray,
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user