From e97583befdf8e3e03263cc7d05e14d75aa9ea948 Mon Sep 17 00:00:00 2001 From: Eric Mastro Date: Tue, 25 Oct 2022 13:00:24 +1100 Subject: [PATCH 01/10] [marketplace] alias bytes32 types `RequestId`, `SlotId`, `LockId`, `ProofId`, `EndId` types were created to avoid confusion and enforce compiler restrictions. --- contracts/Marketplace.sol | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/contracts/Marketplace.sol b/contracts/Marketplace.sol index ce27027..95adb59 100644 --- a/contracts/Marketplace.sol +++ b/contracts/Marketplace.sol @@ -345,6 +345,15 @@ contract Marketplace is Collateral, Proofs { return RequestId.unwrap(a) != bytes32(b); } + function _toProofId(SlotId slotId) internal pure returns (ProofId) { + return ProofId.wrap(SlotId.unwrap(slotId)); + } + + function _notEqual(RequestId a, uint256 b) internal pure returns (bool) { + return RequestId.unwrap(a) != bytes32(b); + } + + struct Request { address client; Ask ask; From b2f9e07c564b27b059e1e6b14fb0ebc0a19e5053 Mon Sep 17 00:00:00 2001 From: Eric Mastro Date: Tue, 25 Oct 2022 13:00:48 +1100 Subject: [PATCH 02/10] [marketplace] add list of active requests --- contracts/Marketplace.sol | 5 +++++ test/Marketplace.test.js | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/contracts/Marketplace.sol b/contracts/Marketplace.sol index 95adb59..ec6a907 100644 --- a/contracts/Marketplace.sol +++ b/contracts/Marketplace.sol @@ -15,6 +15,7 @@ contract Marketplace is Collateral, Proofs { mapping(RequestId => Request) private requests; mapping(RequestId => RequestContext) private requestContexts; mapping(SlotId => Slot) private slots; + mapping(address => RequestId[]) private activeRequests; constructor( IERC20 _token, @@ -30,6 +31,10 @@ contract Marketplace is Collateral, Proofs { collateral = _collateral; } + function myRequests() public view returns (RequestId[] memory) { + return activeRequests[msg.sender]; + } + function requestStorage(Request calldata request) public marketplaceInvariant diff --git a/test/Marketplace.test.js b/test/Marketplace.test.js index 37d323c..e42a5ee 100644 --- a/test/Marketplace.test.js +++ b/test/Marketplace.test.js @@ -84,6 +84,12 @@ describe("Marketplace", function () { .withArgs(requestId(request), askToArray(request.ask)) }) + it("adds request to list of active requests", async function () { + await token.approve(marketplace.address, price(request)) + await marketplace.requestStorage(request) + expect(await marketplace.myRequests()).to.deep.equal([requestId(request)]) + }) + it("rejects request with invalid client address", async function () { let invalid = { ...request, client: host.address } await token.approve(marketplace.address, price(invalid)) From 29dcfb52b41dc2486f85367748c0bc7b647b77db Mon Sep 17 00:00:00 2001 From: Eric Mastro Date: Tue, 25 Oct 2022 13:04:16 +1100 Subject: [PATCH 03/10] [marketplace] formatting reformatting using prettier --- contracts/Marketplace.sol | 50 ++++++++++++++++++--------------------- test/Marketplace.test.js | 2 +- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/contracts/Marketplace.sol b/contracts/Marketplace.sol index ec6a907..efe0fd5 100644 --- a/contracts/Marketplace.sol +++ b/contracts/Marketplace.sol @@ -97,9 +97,11 @@ contract Marketplace is Collateral, Proofs { } } - function _freeSlot( - SlotId slotId - ) internal slotMustAcceptProofs(slotId) marketplaceInvariant { + function _freeSlot(SlotId slotId) + internal + slotMustAcceptProofs(slotId) + marketplaceInvariant + { Slot storage slot = _slot(slotId); RequestId requestId = slot.requestId; RequestContext storage context = requestContexts[requestId]; @@ -131,6 +133,7 @@ contract Marketplace is Collateral, Proofs { // TODO: send client remaining funds } } + function payoutSlot(RequestId requestId, uint256 slotIndex) public marketplaceInvariant @@ -180,10 +183,8 @@ contract Marketplace is Collateral, Proofs { RequestContext storage context = _context(requestId); return context.state == RequestState.Cancelled || - ( - context.state == RequestState.New && - block.timestamp > _request(requestId).expiry - ); + (context.state == RequestState.New && + block.timestamp > _request(requestId).expiry); } /// @notice Return true if the request state is RequestState.Finished or if the request duration has elapsed and the request was started. @@ -194,10 +195,8 @@ contract Marketplace is Collateral, Proofs { RequestContext memory context = _context(requestId); return context.state == RequestState.Finished || - ( - context.state == RequestState.Started && - block.timestamp > context.endsAt - ); + (context.state == RequestState.Started && + block.timestamp > context.endsAt); } /// @notice Return id of request that slot belongs to @@ -272,8 +271,8 @@ contract Marketplace is Collateral, Proofs { function _price( uint64 numSlots, uint256 duration, - uint256 reward) internal pure returns (uint256) { - + uint256 reward + ) internal pure returns (uint256) { return numSlots * duration * reward; } @@ -311,7 +310,11 @@ contract Marketplace is Collateral, Proofs { /// @notice returns true when the request is accepting proof submissions from hosts occupying slots. /// @dev Request state must be new or started, and must not be cancelled, finished, or failed. /// @param requestId id of the request for which to obtain state info - function _requestAcceptsProofs(RequestId requestId) internal view returns (bool) { + function _requestAcceptsProofs(RequestId requestId) + internal + view + returns (bool) + { RequestState s = state(requestId); return s == RequestState.New || s == RequestState.Started; } @@ -324,9 +327,7 @@ contract Marketplace is Collateral, Proofs { return RequestId.wrap(keccak256(abi.encode(request))); } - function _toSlotId( - RequestId requestId, - uint256 slotIndex) + function _toSlotId(RequestId requestId, uint256 slotIndex) internal pure returns (SlotId) @@ -354,11 +355,6 @@ contract Marketplace is Collateral, Proofs { return ProofId.wrap(SlotId.unwrap(slotId)); } - function _notEqual(RequestId a, uint256 b) internal pure returns (bool) { - return RequestId.unwrap(a) != bytes32(b); - } - - struct Request { address client; Ask ask; @@ -393,11 +389,11 @@ contract Marketplace is Collateral, Proofs { } enum RequestState { - New, // [default] waiting to fill slots - Started, // all slots filled, accepting regular proofs - Cancelled, // not enough slots filled before expiry - Finished, // successfully completed - Failed // too many nodes have failed to provide proofs, data lost + New, // [default] waiting to fill slots + Started, // all slots filled, accepting regular proofs + Cancelled, // not enough slots filled before expiry + Finished, // successfully completed + Failed // too many nodes have failed to provide proofs, data lost } struct RequestContext { diff --git a/test/Marketplace.test.js b/test/Marketplace.test.js index e42a5ee..fa139e0 100644 --- a/test/Marketplace.test.js +++ b/test/Marketplace.test.js @@ -9,7 +9,7 @@ const { waitUntilStarted, waitUntilFinished, waitUntilFailed, - RequestState + RequestState, } = require("./marketplace") const { price, pricePerSlot } = require("./price") const { From 51a02c09ba72ebda79a58a59999b00bff911400d Mon Sep 17 00:00:00 2001 From: Eric Mastro Date: Tue, 25 Oct 2022 13:06:52 +1100 Subject: [PATCH 04/10] [marketplace] remove request from list of active requests --- contracts/Marketplace.sol | 23 +++++++++++++++++-- test/Marketplace.test.js | 47 ++++++++++++++++++++++++++++++++++----- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/contracts/Marketplace.sol b/contracts/Marketplace.sol index efe0fd5..1feba96 100644 --- a/contracts/Marketplace.sol +++ b/contracts/Marketplace.sol @@ -3,10 +3,13 @@ pragma solidity ^0.8.8; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/utils/math/Math.sol"; +import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "./Collateral.sol"; import "./Proofs.sol"; contract Marketplace is Collateral, Proofs { + using EnumerableSet for EnumerableSet.Bytes32Set; + type RequestId is bytes32; type SlotId is bytes32; @@ -15,7 +18,7 @@ contract Marketplace is Collateral, Proofs { mapping(RequestId => Request) private requests; mapping(RequestId => RequestContext) private requestContexts; mapping(SlotId => Slot) private slots; - mapping(address => RequestId[]) private activeRequests; + mapping(address => EnumerableSet.Bytes32Set) private activeRequests; constructor( IERC20 _token, @@ -32,7 +35,7 @@ contract Marketplace is Collateral, Proofs { } function myRequests() public view returns (RequestId[] memory) { - return activeRequests[msg.sender]; + return _toRequestIds(activeRequests[msg.sender].values()); } function requestStorage(Request calldata request) @@ -50,6 +53,7 @@ contract Marketplace is Collateral, Proofs { context.endsAt = block.timestamp + request.ask.duration; _setProofEnd(_toEndId(id), context.endsAt); + activeRequests[request.client].add(RequestId.unwrap(id)); _createLock(_toLockId(id), request.expiry); @@ -126,6 +130,7 @@ contract Marketplace is Collateral, Proofs { context.state = RequestState.Failed; _setProofEnd(_toEndId(requestId), block.timestamp - 1); context.endsAt = block.timestamp - 1; + activeRequests[request.client].remove(RequestId.unwrap(requestId)); emit RequestFailed(requestId); // TODO: burn all remaining slot collateral (note: slot collateral not @@ -140,7 +145,9 @@ contract Marketplace is Collateral, Proofs { { require(_isFinished(requestId), "Contract not ended"); RequestContext storage context = _context(requestId); + Request storage request = _request(requestId); context.state = RequestState.Finished; + activeRequests[request.client].remove(RequestId.unwrap(requestId)); SlotId slotId = _toSlotId(requestId, slotIndex); Slot storage slot = _slot(slotId); require(!slot.hostPaid, "Already paid"); @@ -164,6 +171,7 @@ contract Marketplace is Collateral, Proofs { // Update request state to Cancelled. Handle in the withdraw transaction // as there needs to be someone to pay for the gas to update the state context.state = RequestState.Cancelled; + activeRequests[request.client].remove(RequestId.unwrap(requestId)); emit RequestCancelled(requestId); // TODO: To be changed once we start paying out hosts for the time they @@ -327,6 +335,17 @@ contract Marketplace is Collateral, Proofs { return RequestId.wrap(keccak256(abi.encode(request))); } + function _toRequestIds(bytes32[] memory array) + private + pure + returns (RequestId[] memory result) + { + // solhint-disable-next-line no-inline-assembly + assembly { + result := array + } + } + function _toSlotId(RequestId requestId, uint256 slotIndex) internal pure diff --git a/test/Marketplace.test.js b/test/Marketplace.test.js index fa139e0..e265942 100644 --- a/test/Marketplace.test.js +++ b/test/Marketplace.test.js @@ -84,12 +84,6 @@ describe("Marketplace", function () { .withArgs(requestId(request), askToArray(request.ask)) }) - it("adds request to list of active requests", async function () { - await token.approve(marketplace.address, price(request)) - await marketplace.requestStorage(request) - expect(await marketplace.myRequests()).to.deep.equal([requestId(request)]) - }) - it("rejects request with invalid client address", async function () { let invalid = { ...request, client: host.address } await token.approve(marketplace.address, price(invalid)) @@ -640,4 +634,45 @@ describe("Marketplace", function () { }) }) }) + + describe("list of active requests", function () { + beforeEach(async function () { + switchAccount(host) + await token.approve(marketplace.address, collateral) + await marketplace.deposit(collateral) + switchAccount(client) + await token.approve(marketplace.address, price(request)) + }) + + it("adds request to list when requesting storage", async function () { + await marketplace.requestStorage(request) + expect(await marketplace.myRequests()).to.deep.equal([requestId(request)]) + }) + + it("removes request from list when funds are withdrawn", async function () { + await marketplace.requestStorage(request) + await waitUntilCancelled(request) + await marketplace.withdrawFunds(requestId(request)) + expect(await marketplace.myRequests()).to.deep.equal([]) + }) + + it("removes request from list when request fails", async function () { + await marketplace.requestStorage(request) + switchAccount(host) + await waitUntilStarted(marketplace, request, slot, proof) + await waitUntilFailed(marketplace, request, slot) + switchAccount(client) + expect(await marketplace.myRequests()).to.deep.equal([]) + }) + + it("removes request from list when request finishes", async function () { + await marketplace.requestStorage(request) + switchAccount(host) + const lastSlot = await waitUntilStarted(marketplace, request, slot, proof) + await waitUntilFinished(marketplace, lastSlot) + await marketplace.payoutSlot(slot.request, slot.index) + switchAccount(client) + expect(await marketplace.myRequests()).to.deep.equal([]) + }) + }) }) From 2ac6c0b2deecd8060ae326301bf625d64115cc09 Mon Sep 17 00:00:00 2001 From: Eric Mastro Date: Tue, 25 Oct 2022 13:13:31 +1100 Subject: [PATCH 05/10] remove duplicate _toProofId function --- contracts/Marketplace.sol | 4 ---- 1 file changed, 4 deletions(-) diff --git a/contracts/Marketplace.sol b/contracts/Marketplace.sol index 1feba96..883ec12 100644 --- a/contracts/Marketplace.sol +++ b/contracts/Marketplace.sol @@ -370,10 +370,6 @@ contract Marketplace is Collateral, Proofs { return RequestId.unwrap(a) != bytes32(b); } - function _toProofId(SlotId slotId) internal pure returns (ProofId) { - return ProofId.wrap(SlotId.unwrap(slotId)); - } - struct Request { address client; Ask ask; From 9a6a321d5b9b20e953a6759fd91bd595bc4f6d46 Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Tue, 25 Oct 2022 14:49:37 +0200 Subject: [PATCH 06/10] [marketplace] Add method to get request end time --- contracts/Marketplace.sol | 6 +++++- test/Marketplace.test.js | 20 ++++++++++---------- test/Storage.test.js | 2 +- test/marketplace.js | 5 ++--- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/contracts/Marketplace.sol b/contracts/Marketplace.sol index 883ec12..54d68d5 100644 --- a/contracts/Marketplace.sol +++ b/contracts/Marketplace.sol @@ -268,7 +268,7 @@ contract Marketplace is Collateral, Proofs { function proofEnd(SlotId slotId) public view returns (uint256) { Slot memory slot = _slot(slotId); - uint256 end = _end(_toEndId(slot.requestId)); + uint256 end = requestEnd(slot.requestId); if (_slotAcceptsProofs(slotId)) { return end; } else { @@ -276,6 +276,10 @@ contract Marketplace is Collateral, Proofs { } } + function requestEnd(RequestId requestId) public view returns (uint256) { + return _end(_toEndId(requestId)); + } + function _price( uint64 numSlots, uint256 duration, diff --git a/test/Marketplace.test.js b/test/Marketplace.test.js index e265942..ce352bf 100644 --- a/test/Marketplace.test.js +++ b/test/Marketplace.test.js @@ -179,7 +179,7 @@ describe("Marketplace", function () { it("is rejected when request is finished", async function () { const lastSlot = await waitUntilStarted(marketplace, request, slot, proof) - await waitUntilFinished(marketplace, lastSlot) + await waitUntilFinished(marketplace, requestId(request)) await expect( marketplace.fillSlot(slot.request, slot.index, proof) ).to.be.revertedWith("Request not accepting proofs") @@ -262,7 +262,7 @@ describe("Marketplace", function () { it("checks that proof end time is in the past once finished", async function () { const lastSlot = await waitUntilStarted(marketplace, request, slot, proof) - await waitUntilFinished(marketplace, lastSlot) + await waitUntilFinished(marketplace, requestId(request)) const now = await currentTime() // in the process of calling currentTime and proofEnd, // block.timestamp has advanced by 1, so the expected proof end time will @@ -303,7 +303,7 @@ describe("Marketplace", function () { it("fails to free slot when finished", async function () { const lastSlot = await waitUntilStarted(marketplace, request, slot, proof) - await waitUntilFinished(marketplace, lastSlot) + await waitUntilFinished(marketplace, requestId(request)) await expect(marketplace.freeSlot(slotId(slot))).to.be.revertedWith( "Slot not accepting proofs" ) @@ -340,7 +340,7 @@ describe("Marketplace", function () { it("pays the host", async function () { const lastSlot = await waitUntilStarted(marketplace, request, slot, proof) - await waitUntilFinished(marketplace, lastSlot) + await waitUntilFinished(marketplace, requestId(request)) const startBalance = await token.balanceOf(host.address) await marketplace.payoutSlot(slot.request, slot.index) const endBalance = await token.balanceOf(host.address) @@ -356,7 +356,7 @@ describe("Marketplace", function () { it("can only be done once", async function () { const lastSlot = await waitUntilStarted(marketplace, request, slot, proof) - await waitUntilFinished(marketplace, lastSlot) + await waitUntilFinished(marketplace, requestId(request)) await marketplace.payoutSlot(slot.request, slot.index) await expect( marketplace.payoutSlot(slot.request, slot.index) @@ -365,7 +365,7 @@ describe("Marketplace", function () { it("cannot be filled again", async function () { const lastSlot = await waitUntilStarted(marketplace, request, slot, proof) - await waitUntilFinished(marketplace, lastSlot) + await waitUntilFinished(marketplace, requestId(request)) await marketplace.payoutSlot(slot.request, slot.index) await expect(marketplace.fillSlot(slot.request, slot.index, proof)).to.be .reverted @@ -508,7 +508,7 @@ describe("Marketplace", function () { it("state is Finished once slot is paid out", async function () { const lastSlot = await waitUntilStarted(marketplace, request, slot, proof) - await waitUntilFinished(marketplace, lastSlot) + await waitUntilFinished(marketplace, requestId(request)) await marketplace.payoutSlot(slot.request, slot.index) await expect(await marketplace.state(slot.request)).to.equal( RequestState.Finished @@ -601,7 +601,7 @@ describe("Marketplace", function () { slot, proof ) - await waitUntilFinished(marketplace, lastSlot) + await waitUntilFinished(marketplace, requestId(request)) await expect( marketplace.testAcceptsProofs(slotId(slot)) ).to.be.revertedWith("Slot not accepting proofs") @@ -614,7 +614,7 @@ describe("Marketplace", function () { slot, proof ) - await waitUntilFinished(marketplace, lastSlot) + await waitUntilFinished(marketplace, requestId(request)) await marketplace.payoutSlot(slot.request, slot.index) await expect( marketplace.testAcceptsProofs(slotId(slot)) @@ -669,7 +669,7 @@ describe("Marketplace", function () { await marketplace.requestStorage(request) switchAccount(host) const lastSlot = await waitUntilStarted(marketplace, request, slot, proof) - await waitUntilFinished(marketplace, lastSlot) + await waitUntilFinished(marketplace, requestId(request)) await marketplace.payoutSlot(slot.request, slot.index) switchAccount(client) expect(await marketplace.myRequests()).to.deep.equal([]) diff --git a/test/Storage.test.js b/test/Storage.test.js index 4d2c39e..01746cb 100644 --- a/test/Storage.test.js +++ b/test/Storage.test.js @@ -76,7 +76,7 @@ describe("Storage", function () { describe("ending the contract", function () { it("unlocks the host collateral", async function () { await storage.fillSlot(slot.request, slot.index, proof) - await waitUntilFinished(storage, slot) + await waitUntilFinished(storage, slot.request) await expect(storage.withdraw()).not.to.be.reverted }) }) diff --git a/test/marketplace.js b/test/marketplace.js index 94317bb..bbcaa72 100644 --- a/test/marketplace.js +++ b/test/marketplace.js @@ -13,9 +13,8 @@ async function waitUntilStarted(contract, request, slot, proof) { return { ...slot, index: lastSlotIdx } } -async function waitUntilFinished(contract, lastSlot) { - const lastSlotId = slotId(lastSlot) - const end = (await contract.proofEnd(lastSlotId)).toNumber() +async function waitUntilFinished(contract, requestId) { + const end = (await contract.requestEnd(requestId)).toNumber() await advanceTimeTo(end + 1) } From 4a470c7dc738824b84f5aca9617dbf1c4322714e Mon Sep 17 00:00:00 2001 From: Eric Mastro Date: Wed, 26 Oct 2022 13:15:42 +1100 Subject: [PATCH 07/10] [marketplace] improve requestEnd to check all states MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There may be cases where the the request end is not accurate as the state of the request hasn’t yet been updated. For example, when a request is cancelled, the request end would not have been updated to be in the past, and would still be set for the end of the request (which could be in the future). --- contracts/Marketplace.sol | 9 ++++-- test/Marketplace.test.js | 66 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/contracts/Marketplace.sol b/contracts/Marketplace.sol index 54d68d5..0b54d34 100644 --- a/contracts/Marketplace.sol +++ b/contracts/Marketplace.sol @@ -268,7 +268,7 @@ contract Marketplace is Collateral, Proofs { function proofEnd(SlotId slotId) public view returns (uint256) { Slot memory slot = _slot(slotId); - uint256 end = requestEnd(slot.requestId); + uint256 end = _end(_toEndId(slot.requestId)); if (_slotAcceptsProofs(slotId)) { return end; } else { @@ -277,7 +277,12 @@ contract Marketplace is Collateral, Proofs { } function requestEnd(RequestId requestId) public view returns (uint256) { - return _end(_toEndId(requestId)); + uint256 end = _end(_toEndId(requestId)); + if(_requestAcceptsProofs(requestId)) { + return end; + } else { + return Math.min(end, block.timestamp - 1); + } } function _price( diff --git a/test/Marketplace.test.js b/test/Marketplace.test.js index ce352bf..674429d 100644 --- a/test/Marketplace.test.js +++ b/test/Marketplace.test.js @@ -271,6 +271,72 @@ describe("Marketplace", function () { }) }) + describe("request end", function () { + var requestTime + beforeEach(async function () { + switchAccount(client) + await token.approve(marketplace.address, price(request)) + await marketplace.requestStorage(request) + requestTime = await currentTime() + switchAccount(host) + await token.approve(marketplace.address, collateral) + await marketplace.deposit(collateral) + }) + + it("shares request end time for all slots in request", async function () { + const lastSlot = request.ask.slots - 1 + for (let i = 0; i < lastSlot; i++) { + await marketplace.fillSlot(slot.request, i, proof) + } + advanceTime(minutes(10)) + await marketplace.fillSlot(slot.request, lastSlot, proof) + let slot0 = { ...slot, index: 0 } + let end = await marketplace.requestEnd(requestId(request)) + for (let i = 1; i <= lastSlot; i++) { + let sloti = { ...slot, index: i } + await expect((await marketplace.proofEnd(slotId(sloti))) === end) + } + }) + + it("sets the request end time to now + duration", async function () { + await marketplace.fillSlot(slot.request, slot.index, proof) + await expect( + (await marketplace.requestEnd(requestId(request))).toNumber() + ).to.be.closeTo(requestTime + request.ask.duration, 1) + }) + + it("sets request end time to the past once failed", async function () { + await waitUntilStarted(marketplace, request, slot, proof) + await waitUntilFailed(marketplace, request, slot) + let slot0 = { ...slot, index: request.ask.maxSlotLoss + 1 } + const now = await currentTime() + await expect(await marketplace.requestEnd(requestId(request))).to.be.eq( + now - 1 + ) + }) + + it("sets request end time to the past once cancelled", async function () { + await marketplace.fillSlot(slot.request, slot.index, proof) + await waitUntilCancelled(request) + const now = await currentTime() + await expect(await marketplace.requestEnd(requestId(request))).to.be.eq( + now - 1 + ) + }) + + it("checks that request end time is in the past once finished", async function () { + await waitUntilStarted(marketplace, request, slot, proof) + await waitUntilFinished(marketplace, requestId(request)) + const now = await currentTime() + // in the process of calling currentTime and proofEnd, + // block.timestamp has advanced by 1, so the expected proof end time will + // be block.timestamp - 1. + await expect(await marketplace.requestEnd(requestId(request))).to.be.eq( + now - 1 + ) + }) + }) + describe("freeing a slot", function () { var id beforeEach(async function () { From 61b8f5fc352838866b0fe27b936323de45bf269c Mon Sep 17 00:00:00 2001 From: Eric Mastro Date: Wed, 26 Oct 2022 13:37:30 +1100 Subject: [PATCH 08/10] [test] Remove lastSlot return from waitUntilStarted This is a remnant from a staggered ending of slots. All slots will end at the request end time now, and thus this is no longer needed. --- test/Marketplace.test.js | 30 ++++++++++-------------------- test/marketplace.js | 4 +--- 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/test/Marketplace.test.js b/test/Marketplace.test.js index 674429d..ff3bfa8 100644 --- a/test/Marketplace.test.js +++ b/test/Marketplace.test.js @@ -178,7 +178,7 @@ describe("Marketplace", function () { }) it("is rejected when request is finished", async function () { - const lastSlot = await waitUntilStarted(marketplace, request, slot, proof) + await waitUntilStarted(marketplace, request, slot, proof) await waitUntilFinished(marketplace, requestId(request)) await expect( marketplace.fillSlot(slot.request, slot.index, proof) @@ -261,7 +261,7 @@ describe("Marketplace", function () { }) it("checks that proof end time is in the past once finished", async function () { - const lastSlot = await waitUntilStarted(marketplace, request, slot, proof) + await waitUntilStarted(marketplace, request, slot, proof) await waitUntilFinished(marketplace, requestId(request)) const now = await currentTime() // in the process of calling currentTime and proofEnd, @@ -368,7 +368,7 @@ describe("Marketplace", function () { }) it("fails to free slot when finished", async function () { - const lastSlot = await waitUntilStarted(marketplace, request, slot, proof) + await waitUntilStarted(marketplace, request, slot, proof) await waitUntilFinished(marketplace, requestId(request)) await expect(marketplace.freeSlot(slotId(slot))).to.be.revertedWith( "Slot not accepting proofs" @@ -405,7 +405,7 @@ describe("Marketplace", function () { }) it("pays the host", async function () { - const lastSlot = await waitUntilStarted(marketplace, request, slot, proof) + await waitUntilStarted(marketplace, request, slot, proof) await waitUntilFinished(marketplace, requestId(request)) const startBalance = await token.balanceOf(host.address) await marketplace.payoutSlot(slot.request, slot.index) @@ -421,7 +421,7 @@ describe("Marketplace", function () { }) it("can only be done once", async function () { - const lastSlot = await waitUntilStarted(marketplace, request, slot, proof) + await waitUntilStarted(marketplace, request, slot, proof) await waitUntilFinished(marketplace, requestId(request)) await marketplace.payoutSlot(slot.request, slot.index) await expect( @@ -430,7 +430,7 @@ describe("Marketplace", function () { }) it("cannot be filled again", async function () { - const lastSlot = await waitUntilStarted(marketplace, request, slot, proof) + await waitUntilStarted(marketplace, request, slot, proof) await waitUntilFinished(marketplace, requestId(request)) await marketplace.payoutSlot(slot.request, slot.index) await expect(marketplace.fillSlot(slot.request, slot.index, proof)).to.be @@ -573,7 +573,7 @@ describe("Marketplace", function () { }) it("state is Finished once slot is paid out", async function () { - const lastSlot = await waitUntilStarted(marketplace, request, slot, proof) + await waitUntilStarted(marketplace, request, slot, proof) await waitUntilFinished(marketplace, requestId(request)) await marketplace.payoutSlot(slot.request, slot.index) await expect(await marketplace.state(slot.request)).to.equal( @@ -661,12 +661,7 @@ describe("Marketplace", function () { }) it("fails when request Finished (isFinished is true)", async function () { - const lastSlot = await waitUntilStarted( - marketplace, - request, - slot, - proof - ) + await waitUntilStarted(marketplace, request, slot, proof) await waitUntilFinished(marketplace, requestId(request)) await expect( marketplace.testAcceptsProofs(slotId(slot)) @@ -674,12 +669,7 @@ describe("Marketplace", function () { }) it("fails when request Finished (state set to Finished)", async function () { - const lastSlot = await waitUntilStarted( - marketplace, - request, - slot, - proof - ) + await waitUntilStarted(marketplace, request, slot, proof) await waitUntilFinished(marketplace, requestId(request)) await marketplace.payoutSlot(slot.request, slot.index) await expect( @@ -734,7 +724,7 @@ describe("Marketplace", function () { it("removes request from list when request finishes", async function () { await marketplace.requestStorage(request) switchAccount(host) - const lastSlot = await waitUntilStarted(marketplace, request, slot, proof) + await waitUntilStarted(marketplace, request, slot, proof) await waitUntilFinished(marketplace, requestId(request)) await marketplace.payoutSlot(slot.request, slot.index) switchAccount(client) diff --git a/test/marketplace.js b/test/marketplace.js index bbcaa72..bbb9801 100644 --- a/test/marketplace.js +++ b/test/marketplace.js @@ -6,11 +6,9 @@ async function waitUntilCancelled(request) { } async function waitUntilStarted(contract, request, slot, proof) { - const lastSlotIdx = request.ask.slots - 1 - for (let i = 0; i <= lastSlotIdx; i++) { + for (let i = 0; i < request.ask.slots; i++) { await contract.fillSlot(slot.request, i, proof) } - return { ...slot, index: lastSlotIdx } } async function waitUntilFinished(contract, requestId) { From c29fb75a487852e192d3d6bf5e21cd5b945efeee Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Wed, 26 Oct 2022 10:48:09 +0200 Subject: [PATCH 09/10] [marketplace] Remove duplication --- contracts/Marketplace.sol | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/contracts/Marketplace.sol b/contracts/Marketplace.sol index 0b54d34..449e654 100644 --- a/contracts/Marketplace.sol +++ b/contracts/Marketplace.sol @@ -267,13 +267,7 @@ contract Marketplace is Collateral, Proofs { } function proofEnd(SlotId slotId) public view returns (uint256) { - Slot memory slot = _slot(slotId); - uint256 end = _end(_toEndId(slot.requestId)); - if (_slotAcceptsProofs(slotId)) { - return end; - } else { - return Math.min(end, block.timestamp - 1); - } + return requestEnd(_slot(slotId).requestId); } function requestEnd(RequestId requestId) public view returns (uint256) { From fb471764509b90f302ab4adead9030839b39a52a Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Wed, 26 Oct 2022 10:58:14 +0200 Subject: [PATCH 10/10] [marketplace] formatting reformatting using prettier --- contracts/Marketplace.sol | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/contracts/Marketplace.sol b/contracts/Marketplace.sol index 449e654..12eeda4 100644 --- a/contracts/Marketplace.sol +++ b/contracts/Marketplace.sol @@ -82,10 +82,7 @@ contract Marketplace is Collateral, Proofs { _lock(msg.sender, lockId); ProofId proofId = _toProofId(slotId); - _expectProofs( - proofId, - _toEndId(requestId), - request.ask.proofProbability); + _expectProofs(proofId, _toEndId(requestId), request.ask.proofProbability); _submitProof(proofId, proof); slot.host = msg.sender; @@ -124,9 +121,10 @@ contract Marketplace is Collateral, Proofs { Request storage request = _request(requestId); uint256 slotsLost = request.ask.slots - context.slotsFilled; - if (slotsLost > request.ask.maxSlotLoss && - context.state == RequestState.Started) { - + if ( + slotsLost > request.ask.maxSlotLoss && + context.state == RequestState.Started + ) { context.state = RequestState.Failed; _setProofEnd(_toEndId(requestId), block.timestamp - 1); context.endsAt = block.timestamp - 1; @@ -272,7 +270,7 @@ contract Marketplace is Collateral, Proofs { function requestEnd(RequestId requestId) public view returns (uint256) { uint256 end = _end(_toEndId(requestId)); - if(_requestAcceptsProofs(requestId)) { + if (_requestAcceptsProofs(requestId)) { return end; } else { return Math.min(end, block.timestamp - 1);