Skip to content

Commit

Permalink
fix(slot-reservations): ensure slot is free (#196)
Browse files Browse the repository at this point in the history
Ensure that the slot state is free before allowing reservations
  • Loading branch information
emizzle authored Oct 30, 2024
1 parent 7645df1 commit 1ce3d10
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 1 deletion.
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

0 comments on commit 1ce3d10

Please sign in to comment.