feat: request duration limit (#206)

* feat: request duration limit

* Merge master and use custom error

* Remove slashCriterion

---------

Co-authored-by: Arnaud <arnaud@status.im>
This commit is contained in:
Adam Uhlíř 2025-02-18 15:27:47 +01:00 committed by GitHub
parent 0f2012b144
commit ff82c26b36
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 21 additions and 4 deletions

View File

@ -19,6 +19,7 @@ const DEFAULT_CONFIGURATION = {
reservations: {
maxReservations: 3,
},
requestDurationLimit: 60*60*24*30 // 30 days
}
function loadConfiguration(name) {

View File

@ -16,4 +16,5 @@ module.exports = {
reservations: {
maxReservations: 3,
},
requestDurationLimit: 60*60*24*30 // 30 days
}

View File

@ -7,6 +7,7 @@ struct MarketplaceConfig {
CollateralConfig collateral;
ProofConfig proofs;
SlotReservationsConfig reservations;
uint256 requestDurationLimit;
}
struct CollateralConfig {

View File

@ -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()

View File

@ -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;

View File

@ -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)

View File

@ -19,6 +19,7 @@ const exampleConfiguration = () => ({
reservations: {
maxReservations: 3,
},
requestDurationLimit: 60 * 60 * 24 * 30, // 30 days
})
const exampleRequest = async () => {