From ff82c26b3669b52a09280c634141dace7f04659a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Uhl=C3=AD=C5=99?= Date: Tue, 18 Feb 2025 15:27:47 +0100 Subject: [PATCH] feat: request duration limit (#206) * feat: request duration limit * Merge master and use custom error * Remove slashCriterion --------- Co-authored-by: Arnaud --- configuration/configuration.js | 1 + configuration/networks/hardhat/configuration.js | 1 + contracts/Configuration.sol | 1 + contracts/FuzzMarketplace.sol | 3 ++- contracts/Marketplace.sol | 7 ++++++- test/Marketplace.test.js | 11 +++++++++-- test/examples.js | 1 + 7 files changed, 21 insertions(+), 4 deletions(-) diff --git a/configuration/configuration.js b/configuration/configuration.js index 938cf63..61c3c6e 100644 --- a/configuration/configuration.js +++ b/configuration/configuration.js @@ -19,6 +19,7 @@ const DEFAULT_CONFIGURATION = { reservations: { maxReservations: 3, }, + requestDurationLimit: 60*60*24*30 // 30 days } function loadConfiguration(name) { diff --git a/configuration/networks/hardhat/configuration.js b/configuration/networks/hardhat/configuration.js index 809840a..f7a1f29 100644 --- a/configuration/networks/hardhat/configuration.js +++ b/configuration/networks/hardhat/configuration.js @@ -16,4 +16,5 @@ module.exports = { reservations: { maxReservations: 3, }, + requestDurationLimit: 60*60*24*30 // 30 days } diff --git a/contracts/Configuration.sol b/contracts/Configuration.sol index ae75212..65cf862 100644 --- a/contracts/Configuration.sol +++ b/contracts/Configuration.sol @@ -7,6 +7,7 @@ struct MarketplaceConfig { CollateralConfig collateral; ProofConfig proofs; SlotReservationsConfig reservations; + uint256 requestDurationLimit; } struct CollateralConfig { diff --git a/contracts/FuzzMarketplace.sol b/contracts/FuzzMarketplace.sol index d86c391..f73cd66 100644 --- a/contracts/FuzzMarketplace.sol +++ b/contracts/FuzzMarketplace.sol @@ -11,7 +11,8 @@ contract FuzzMarketplace is Marketplace { MarketplaceConfig( CollateralConfig(10, 5, 10, 20), ProofConfig(10, 5, 64, "", 67), - SlotReservationsConfig(20) + SlotReservationsConfig(20), + 60 * 60 * 24 * 30 // 30 days ), new TestToken(), new TestVerifier() diff --git a/contracts/Marketplace.sol b/contracts/Marketplace.sol index 1a799fe..297eaa1 100644 --- a/contracts/Marketplace.sol +++ b/contracts/Marketplace.sol @@ -38,6 +38,7 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian { error Marketplace_SlotIsFree(); error Marketplace_ReservationRequired(); error Marketplace_NothingToWithdraw(); + error Marketplace_DurationExceedsLimit(); using EnumerableSet for EnumerableSet.Bytes32Set; using EnumerableSet for EnumerableSet.AddressSet; @@ -131,8 +132,9 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian { RequestId id = request.id(); if (request.client != msg.sender) revert Marketplace_InvalidClientAddress(); - if (_requests[id].client != address(0)) + if (_requests[id].client != address(0)) { revert Marketplace_RequestAlreadyExists(); + } if (request.expiry == 0 || request.expiry >= request.ask.duration) revert Marketplace_InvalidExpiry(); if (request.ask.slots == 0) revert Marketplace_InsufficientSlots(); @@ -153,6 +155,9 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian { if (bytes(request.content.cid).length == 0) { revert Marketplace_InvalidCid(); } + if (request.ask.duration > _config.requestDurationLimit) { + revert Marketplace_DurationExceedsLimit(); + } _requests[id] = request; _requestContexts[id].endsAt = block.timestamp + request.ask.duration; diff --git a/test/Marketplace.test.js b/test/Marketplace.test.js index c890300..2f996f5 100644 --- a/test/Marketplace.test.js +++ b/test/Marketplace.test.js @@ -203,6 +203,14 @@ describe("Marketplace", function () { ) }) + it("rejects request with duration exceeding limit", async function () { + request.ask.duration = config.requestDurationLimit + 1 + await token.approve(marketplace.address, collateralPerSlot(request)) + await expect(marketplace.requestStorage(request)).to.be.revertedWith( + "Marketplace_DurationExceedsLimit" + ) + }) + it("rejects request with insufficient payment", async function () { let insufficient = maxPrice(request) - 1 await token.approve(marketplace.address, insufficient) @@ -1390,8 +1398,7 @@ describe("Marketplace", function () { it("rewards validator when marking proof as missing", async function () { const id = slotId(slot) - const { slashCriterion, slashPercentage, validatorRewardPercentage } = - config.collateral + const { slashPercentage, validatorRewardPercentage } = config.collateral await marketplace.reserveSlot(slot.request, slot.index) await marketplace.fillSlot(slot.request, slot.index, proof) diff --git a/test/examples.js b/test/examples.js index ba84e9a..b03ef9a 100644 --- a/test/examples.js +++ b/test/examples.js @@ -19,6 +19,7 @@ const exampleConfiguration = () => ({ reservations: { maxReservations: 3, }, + requestDurationLimit: 60 * 60 * 24 * 30, // 30 days }) const exampleRequest = async () => {