[marketplace] formatting

This commit is contained in:
Mark Spanbroek 2023-05-30 14:42:59 +02:00 committed by markspanbroek
parent 42d4778dcc
commit 03e5546121
3 changed files with 96 additions and 42 deletions

View File

@ -33,7 +33,6 @@ contract Marketplace is Proofs, StateRetrieval {
SlotState state; SlotState state;
RequestId requestId; RequestId requestId;
uint256 slotIndex; uint256 slotIndex;
/// @notice Tracks the current amount of host's collateral that is to be payed out at the end of Slot's lifespan. /// @notice Tracks the current amount of host's collateral that is to be payed out at the end of Slot's lifespan.
/// @dev When Slot is filled, the collateral is collected in amount of request.ask.collateral /// @dev When Slot is filled, the collateral is collected in amount of request.ask.collateral
/// @dev When Host is slashed for missing a proof the slashed amount is reflected in this variable /// @dev When Host is slashed for missing a proof the slashed amount is reflected in this variable
@ -52,9 +51,20 @@ contract Marketplace is Proofs, StateRetrieval {
) Proofs(configuration.proofs) { ) Proofs(configuration.proofs) {
token = token_; token = token_;
require(configuration.collateral.repairRewardPercentage <= 100, "Must be less than 100"); require(
require(configuration.collateral.slashPercentage <= 100, "Must be less than 100"); configuration.collateral.repairRewardPercentage <= 100,
require(configuration.collateral.maxNumberOfSlashes * configuration.collateral.slashPercentage <= 100, "Total slash percentage must be less then 100"); "Must be less than 100"
);
require(
configuration.collateral.slashPercentage <= 100,
"Must be less than 100"
);
require(
configuration.collateral.maxNumberOfSlashes *
configuration.collateral.slashPercentage <=
100,
"Maximum slashing exceeds 100%"
);
config = configuration; config = configuration;
} }
@ -137,9 +147,13 @@ contract Marketplace is Proofs, StateRetrieval {
Request storage request = _requests[slot.requestId]; Request storage request = _requests[slot.requestId];
if (missingProofs(slotId) % config.collateral.slashCriterion == 0) { if (missingProofs(slotId) % config.collateral.slashCriterion == 0) {
uint256 slashedAmount = (request.ask.collateral * config.collateral.slashPercentage) / 100; uint256 slashedAmount = (request.ask.collateral *
config.collateral.slashPercentage) / 100;
slot.currentCollateral -= slashedAmount; slot.currentCollateral -= slashedAmount;
if (missingProofs(slotId) / config.collateral.slashCriterion >= config.collateral.maxNumberOfSlashes) { if (
missingProofs(slotId) / config.collateral.slashCriterion >=
config.collateral.maxNumberOfSlashes
) {
// When the number of slashings is at or above the allowed amount, // When the number of slashings is at or above the allowed amount,
// free the slot. // free the slot.
_forciblyFreeSlot(slotId); _forciblyFreeSlot(slotId);
@ -157,7 +171,7 @@ contract Marketplace is Proofs, StateRetrieval {
delete _slots[slotId]; delete _slots[slotId];
context.slotsFilled -= 1; context.slotsFilled -= 1;
emit SlotFreed(requestId, slotId); emit SlotFreed(requestId, slotId);
resetMissingProofs(slotId); _resetMissingProofs(slotId);
Request storage request = _requests[requestId]; Request storage request = _requests[requestId];
uint256 slotsLost = request.ask.slots - context.slotsFilled; uint256 slotsLost = request.ask.slots - context.slotsFilled;
@ -185,7 +199,8 @@ contract Marketplace is Proofs, StateRetrieval {
_removeFromMySlots(slot.host, slotId); _removeFromMySlots(slot.host, slotId);
uint256 amount = _requests[requestId].pricePerSlot() + slot.currentCollateral; uint256 amount = _requests[requestId].pricePerSlot() +
slot.currentCollateral;
_marketplaceTotals.sent += amount; _marketplaceTotals.sent += amount;
slot.state = SlotState.Paid; slot.state = SlotState.Paid;
require(token.transfer(slot.host, amount), "Payment failed"); require(token.transfer(slot.host, amount), "Payment failed");
@ -216,12 +231,9 @@ contract Marketplace is Proofs, StateRetrieval {
require(token.transfer(msg.sender, amount), "Withdraw failed"); require(token.transfer(msg.sender, amount), "Withdraw failed");
} }
function getActiveSlot(SlotId slotId) function getActiveSlot(
public SlotId slotId
view ) public view slotIsNotFree(slotId) returns (ActiveSlot memory) {
slotIsNotFree(slotId)
returns (ActiveSlot memory)
{
Slot storage slot = _slots[slotId]; Slot storage slot = _slots[slotId];
ActiveSlot memory activeSlot; ActiveSlot memory activeSlot;
activeSlot.request = _requests[slot.requestId]; activeSlot.request = _requests[slot.requestId];

View File

@ -25,7 +25,7 @@ abstract contract Proofs is Periods {
return _missed[slotId]; return _missed[slotId];
} }
function resetMissingProofs(SlotId slotId) internal { function _resetMissingProofs(SlotId slotId) internal {
_missed[slotId] = 0; _missed[slotId] = 0;
} }

View File

@ -29,7 +29,7 @@ const {
currentTime, currentTime,
} = require("./evm") } = require("./evm")
describe('Marketplace constructor', function () { describe("Marketplace constructor", function () {
let Marketplace, token, config let Marketplace, token, config
beforeEach(async function () { beforeEach(async function () {
@ -51,21 +51,21 @@ describe('Marketplace constructor', function () {
it(`should reject for ${property} overflowing percentage values`, async () => { it(`should reject for ${property} overflowing percentage values`, async () => {
config.collateral[property] = 101 config.collateral[property] = 101
await expect(Marketplace.deploy(token.address, config)).to.be.revertedWith( await expect(
"Must be less than 100" Marketplace.deploy(token.address, config)
) ).to.be.revertedWith("Must be less than 100")
}) })
} }
testPercentageOverflow('repairRewardPercentage') testPercentageOverflow("repairRewardPercentage")
testPercentageOverflow('slashPercentage') testPercentageOverflow("slashPercentage")
it('should reject when total slash percentage exceeds 100%', async () => { it("should reject when total slash percentage exceeds 100%", async () => {
config.collateral.slashPercentage = 1 config.collateral.slashPercentage = 1
config.collateral.maxNumberOfSlashes = 101 config.collateral.maxNumberOfSlashes = 101
await expect(Marketplace.deploy(token.address, config)).to.be.revertedWith( await expect(Marketplace.deploy(token.address, config)).to.be.revertedWith(
"Total slash percentage must be less then 100" "Maximum slashing exceeds 100%"
) )
}) })
}) })
@ -250,7 +250,10 @@ describe("Marketplace", function () {
it("fails when all slots are already filled", async function () { it("fails when all slots are already filled", async function () {
const lastSlot = request.ask.slots - 1 const lastSlot = request.ask.slots - 1
await token.approve(marketplace.address, request.ask.collateral * lastSlot) await token.approve(
marketplace.address,
request.ask.collateral * lastSlot
)
await token.approve(marketplace.address, price(request) * lastSlot) await token.approve(marketplace.address, price(request) * lastSlot)
for (let i = 0; i <= lastSlot; i++) { for (let i = 0; i <= lastSlot; i++) {
await marketplace.fillSlot(slot.request, i, proof) await marketplace.fillSlot(slot.request, i, proof)
@ -278,11 +281,11 @@ describe("Marketplace", function () {
}) })
it("collects only requested collateral and not more", async function () { it("collects only requested collateral and not more", async function () {
await token.approve(marketplace.address, request.ask.collateral*2) await token.approve(marketplace.address, request.ask.collateral * 2)
const startBalanace = await token.balanceOf(host.address) const startBalanace = await token.balanceOf(host.address)
await marketplace.fillSlot(slot.request, slot.index, proof) await marketplace.fillSlot(slot.request, slot.index, proof)
const endBalance = await token.balanceOf(host.address) const endBalance = await token.balanceOf(host.address)
expect(startBalanace-endBalance).to.eq(request.ask.collateral) expect(startBalanace - endBalance).to.eq(request.ask.collateral)
}) })
}) })
@ -394,7 +397,9 @@ describe("Marketplace", function () {
const startBalance = await token.balanceOf(host.address) const startBalance = await token.balanceOf(host.address)
await marketplace.freeSlot(slotId(slot)) await marketplace.freeSlot(slotId(slot))
const endBalance = await token.balanceOf(host.address) const endBalance = await token.balanceOf(host.address)
expect(endBalance - startBalance).to.equal(pricePerSlot(request) + request.ask.collateral) expect(endBalance - startBalance).to.equal(
pricePerSlot(request) + request.ask.collateral
)
}) })
it("pays the host when contract was cancelled", async function () { it("pays the host when contract was cancelled", async function () {
@ -443,7 +448,10 @@ describe("Marketplace", function () {
it("emits event when all slots are filled", async function () { it("emits event when all slots are filled", async function () {
const lastSlot = request.ask.slots - 1 const lastSlot = request.ask.slots - 1
await token.approve(marketplace.address, request.ask.collateral * lastSlot) await token.approve(
marketplace.address,
request.ask.collateral * lastSlot
)
for (let i = 0; i < lastSlot; i++) { for (let i = 0; i < lastSlot; i++) {
await marketplace.fillSlot(slot.request, i, proof) await marketplace.fillSlot(slot.request, i, proof)
} }
@ -465,7 +473,10 @@ describe("Marketplace", function () {
}) })
it("fails when all slots are already filled", async function () { it("fails when all slots are already filled", async function () {
const lastSlot = request.ask.slots - 1 const lastSlot = request.ask.slots - 1
await token.approve(marketplace.address, request.ask.collateral * (lastSlot + 1)) await token.approve(
marketplace.address,
request.ask.collateral * (lastSlot + 1)
)
for (let i = 0; i <= lastSlot; i++) { for (let i = 0; i <= lastSlot; i++) {
await marketplace.fillSlot(slot.request, i, proof) await marketplace.fillSlot(slot.request, i, proof)
} }
@ -501,7 +512,10 @@ describe("Marketplace", function () {
it("rejects withdraw when in wrong state", async function () { it("rejects withdraw when in wrong state", async function () {
// fill all slots, should change state to RequestState.Started // fill all slots, should change state to RequestState.Started
const lastSlot = request.ask.slots - 1 const lastSlot = request.ask.slots - 1
await token.approve(marketplace.address, request.ask.collateral * (lastSlot + 1)) await token.approve(
marketplace.address,
request.ask.collateral * (lastSlot + 1)
)
for (let i = 0; i <= lastSlot; i++) { for (let i = 0; i <= lastSlot; i++) {
await marketplace.fillSlot(slot.request, i, proof) await marketplace.fillSlot(slot.request, i, proof)
} }
@ -569,7 +583,10 @@ describe("Marketplace", function () {
}) })
it("does not change to 'Failed' before it is started", async function () { it("does not change to 'Failed' before it is started", async function () {
await token.approve(marketplace.address, request.ask.collateral * (request.ask.maxSlotLoss + 1)) await token.approve(
marketplace.address,
request.ask.collateral * (request.ask.maxSlotLoss + 1)
)
for (let i = 0; i <= request.ask.maxSlotLoss; i++) { for (let i = 0; i <= request.ask.maxSlotLoss; i++) {
await marketplace.fillSlot(slot.request, i, proof) await marketplace.fillSlot(slot.request, i, proof)
} }
@ -701,7 +718,7 @@ describe("Marketplace", function () {
(await marketplace.isProofRequired(id)) && (await marketplace.isProofRequired(id)) &&
(await marketplace.getPointer(id)) < 250 (await marketplace.getPointer(id)) < 250
) )
) { ) {
await advanceTime(period) await advanceTime(period)
} }
} }
@ -774,7 +791,7 @@ describe("Marketplace", function () {
(await marketplace.isProofRequired(id)) && (await marketplace.isProofRequired(id)) &&
(await marketplace.getPointer(id)) < 250 (await marketplace.getPointer(id)) < 250
) )
) { ) {
await advanceTime(period) await advanceTime(period)
} }
} }
@ -799,42 +816,67 @@ describe("Marketplace", function () {
await advanceTime(period) await advanceTime(period)
await marketplace.markProofAsMissing(id, missedPeriod) await marketplace.markProofAsMissing(id, missedPeriod)
} }
const expectedBalance = (request.ask.collateral * (100 - slashPercentage)) / 100 const expectedBalance =
(request.ask.collateral * (100 - slashPercentage)) / 100
expect(BigNumber.from(expectedBalance).eq(await marketplace.getSlotCollateral(id))) expect(
BigNumber.from(expectedBalance).eq(
await marketplace.getSlotCollateral(id)
)
)
}) })
}) })
it("frees slot when collateral slashed below minimum threshold", async function () { it("frees slot when collateral slashed below minimum threshold", async function () {
const minimum = request.ask.collateral - (request.ask.collateral*config.collateral.maxNumberOfSlashes*config.collateral.slashPercentage)/100 const minimum =
request.ask.collateral -
(request.ask.collateral *
config.collateral.maxNumberOfSlashes *
config.collateral.slashPercentage) /
100
await waitUntilStarted(marketplace, request, proof, token) await waitUntilStarted(marketplace, request, proof, token)
while ((await marketplace.slotState(slotId(slot))) === SlotState.Filled) { while ((await marketplace.slotState(slotId(slot))) === SlotState.Filled) {
expect(await marketplace.getSlotCollateral(slotId(slot))).to.be.gt(minimum) expect(await marketplace.getSlotCollateral(slotId(slot))).to.be.gt(
minimum
)
await waitUntilProofIsRequired(slotId(slot)) await waitUntilProofIsRequired(slotId(slot))
const missedPeriod = periodOf(await currentTime()) const missedPeriod = periodOf(await currentTime())
await advanceTime(period) await advanceTime(period)
await marketplace.markProofAsMissing(slotId(slot), missedPeriod) await marketplace.markProofAsMissing(slotId(slot), missedPeriod)
} }
expect(await marketplace.slotState(slotId(slot))).to.equal(SlotState.Free) expect(await marketplace.slotState(slotId(slot))).to.equal(SlotState.Free)
expect(await marketplace.getSlotCollateral(slotId(slot))).to.be.lte(minimum) expect(await marketplace.getSlotCollateral(slotId(slot))).to.be.lte(
minimum
)
}) })
it("free slot when minimum reached and resets missed proof counter", async function () { it("free slot when minimum reached and resets missed proof counter", async function () {
const minimum = request.ask.collateral - (request.ask.collateral*config.collateral.maxNumberOfSlashes*config.collateral.slashPercentage)/100 const minimum =
request.ask.collateral -
(request.ask.collateral *
config.collateral.maxNumberOfSlashes *
config.collateral.slashPercentage) /
100
await waitUntilStarted(marketplace, request, proof, token) await waitUntilStarted(marketplace, request, proof, token)
let missedProofs = 0 let missedProofs = 0
while ((await marketplace.slotState(slotId(slot))) === SlotState.Filled) { while ((await marketplace.slotState(slotId(slot))) === SlotState.Filled) {
expect(await marketplace.getSlotCollateral(slotId(slot))).to.be.gt(minimum) expect(await marketplace.getSlotCollateral(slotId(slot))).to.be.gt(
minimum
)
await waitUntilProofIsRequired(slotId(slot)) await waitUntilProofIsRequired(slotId(slot))
const missedPeriod = periodOf(await currentTime()) const missedPeriod = periodOf(await currentTime())
await advanceTime(period) await advanceTime(period)
expect(await marketplace.missingProofs(slotId(slot))).to.equal(missedProofs) expect(await marketplace.missingProofs(slotId(slot))).to.equal(
missedProofs
)
await marketplace.markProofAsMissing(slotId(slot), missedPeriod) await marketplace.markProofAsMissing(slotId(slot), missedPeriod)
missedProofs += 1 missedProofs += 1
} }
expect(await marketplace.slotState(slotId(slot))).to.equal(SlotState.Free) expect(await marketplace.slotState(slotId(slot))).to.equal(SlotState.Free)
expect(await marketplace.missingProofs(slotId(slot))).to.equal(0) expect(await marketplace.missingProofs(slotId(slot))).to.equal(0)
expect(await marketplace.getSlotCollateral(slotId(slot))).to.be.lte(minimum) expect(await marketplace.getSlotCollateral(slotId(slot))).to.be.lte(
minimum
)
}) })
}) })