Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(slot-reservations): ensure slot is free #196

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions contracts/Marketplace.sol
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,10 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian {
_;
}

function _slotIsFree(SlotId slotId) internal view override returns (bool) {
return _slots[slotId].state == SlotState.Free;
}

function requestEnd(RequestId requestId) public view returns (uint256) {
uint256 end = _requestContexts[requestId].endsAt;
RequestState state = requestState(requestId);
Expand Down
5 changes: 4 additions & 1 deletion contracts/SlotReservations.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "./Requests.sol";
import "./Configuration.sol";

contract SlotReservations {
abstract contract SlotReservations {
using EnumerableSet for EnumerableSet.AddressSet;

mapping(SlotId => EnumerableSet.AddressSet) internal _reservations;
Expand All @@ -15,6 +15,8 @@ contract SlotReservations {
_config = config;
}

function _slotIsFree(SlotId slotId) internal view virtual returns (bool);

function reserveSlot(RequestId requestId, uint256 slotIndex) public {
require(canReserveSlot(requestId, slotIndex), "Reservation not allowed");

Expand All @@ -34,6 +36,7 @@ contract SlotReservations {
SlotId slotId = Requests.slotId(requestId, slotIndex);
return
// TODO: add in check for address inside of expanding window
_slotIsFree(slotId) &&
(_reservations[slotId].length() < _config.maxReservations) &&
(!_reservations[slotId].contains(host));
}
Expand Down
10 changes: 10 additions & 0 deletions contracts/TestSlotReservations.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import "./SlotReservations.sol";
contract TestSlotReservations is SlotReservations {
using EnumerableSet for EnumerableSet.AddressSet;

mapping(SlotId => SlotState) private _states;

// solhint-disable-next-line no-empty-blocks
constructor(SlotReservationsConfig memory config) SlotReservations(config) {}

Expand All @@ -16,4 +18,12 @@ contract TestSlotReservations is SlotReservations {
function length(SlotId slotId) public view returns (uint256) {
return _reservations[slotId].length();
}

function _slotIsFree(SlotId slotId) internal view override returns (bool) {
return _states[slotId] == SlotState.Free;
}

function setSlotState(SlotId id, SlotState state) public {
_states[id] = state;
}
}
16 changes: 16 additions & 0 deletions test/SlotReservations.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const { expect } = require("chai")
const { ethers } = require("hardhat")
const { exampleRequest, exampleConfiguration } = require("./examples")
const { requestId, slotId } = require("./ids")
const { SlotState } = require("./requests")

describe("SlotReservations", function () {
let reservations
Expand All @@ -28,6 +29,8 @@ describe("SlotReservations", function () {
index: slotIndex,
}
id = slotId(slot)

await reservations.setSlotState(id, SlotState.Free)
})

function switchAccount(account) {
Expand Down Expand Up @@ -99,6 +102,19 @@ describe("SlotReservations", function () {
expect(await reservations.canReserveSlot(reqId, slotIndex)).to.be.false
})

it("cannot reserve a slot if not free", async function () {
await reservations.setSlotState(id, SlotState.Filled)
await expect(reservations.reserveSlot(reqId, slotIndex)).to.be.revertedWith(
"Reservation not allowed"
)
expect(await reservations.length(id)).to.equal(0)
})

it("reports a slot cannot be reserved if not free", async function () {
await reservations.setSlotState(id, SlotState.Filled)
expect(await reservations.canReserveSlot(reqId, slotIndex)).to.be.false
})

it("should emit an event when slot reservations are full", async function () {
await reservations.reserveSlot(reqId, slotIndex)
switchAccount(address1)
Expand Down