From 51a02c09ba72ebda79a58a59999b00bff911400d Mon Sep 17 00:00:00 2001 From: Eric Mastro Date: Tue, 25 Oct 2022 13:06:52 +1100 Subject: [PATCH] [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([]) + }) + }) })