mirror of
https://github.com/logos-storage/logos-storage-contracts-eth.git
synced 2026-01-07 07:43:08 +00:00
marketplace: use vault in marketplace
This commit is contained in:
parent
8b40f63693
commit
8df557801c
@ -13,6 +13,7 @@ import "./SlotReservations.sol";
|
|||||||
import "./StateRetrieval.sol";
|
import "./StateRetrieval.sol";
|
||||||
import "./Endian.sol";
|
import "./Endian.sol";
|
||||||
import "./Groth16.sol";
|
import "./Groth16.sol";
|
||||||
|
import "./marketplace/VaultHelpers.sol";
|
||||||
|
|
||||||
contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian {
|
contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian {
|
||||||
error Marketplace_RepairRewardPercentageTooHigh();
|
error Marketplace_RepairRewardPercentageTooHigh();
|
||||||
@ -46,6 +47,9 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian {
|
|||||||
using EnumerableSet for EnumerableSet.AddressSet;
|
using EnumerableSet for EnumerableSet.AddressSet;
|
||||||
using Requests for Request;
|
using Requests for Request;
|
||||||
using AskHelpers for Ask;
|
using AskHelpers for Ask;
|
||||||
|
using VaultHelpers for Vault;
|
||||||
|
using VaultHelpers for RequestId;
|
||||||
|
using VaultHelpers for Request;
|
||||||
|
|
||||||
Vault private immutable _vault;
|
Vault private immutable _vault;
|
||||||
MarketplaceConfig private _config;
|
MarketplaceConfig private _config;
|
||||||
@ -173,10 +177,18 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian {
|
|||||||
|
|
||||||
_addToMyRequests(request.client, id);
|
_addToMyRequests(request.client, id);
|
||||||
|
|
||||||
uint256 amount = request.maxPrice();
|
uint128 amount = uint128(request.maxPrice());
|
||||||
_requestContexts[id].fundsToReturnToClient = amount;
|
_requestContexts[id].fundsToReturnToClient = amount;
|
||||||
_marketplaceTotals.received += amount;
|
_marketplaceTotals.received += amount;
|
||||||
token().safeTransferFrom(msg.sender, address(this), amount);
|
|
||||||
|
FundId fund = id.asFundId();
|
||||||
|
AccountId account = _vault.clientAccount(request.client);
|
||||||
|
_vault.lock(
|
||||||
|
fund,
|
||||||
|
Timestamp.wrap(uint40(_requestContexts[id].expiresAt)),
|
||||||
|
Timestamp.wrap(uint40(_requestContexts[id].endsAt))
|
||||||
|
);
|
||||||
|
_transferToVault(request.client, fund, account, amount);
|
||||||
|
|
||||||
emit StorageRequested(id, request.ask, _requestContexts[id].expiresAt);
|
emit StorageRequested(id, request.ask, _requestContexts[id].expiresAt);
|
||||||
}
|
}
|
||||||
@ -236,7 +248,14 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian {
|
|||||||
} else {
|
} else {
|
||||||
collateralAmount = collateralPerSlot;
|
collateralAmount = collateralPerSlot;
|
||||||
}
|
}
|
||||||
token().safeTransferFrom(msg.sender, address(this), collateralAmount);
|
|
||||||
|
FundId fund = requestId.asFundId();
|
||||||
|
AccountId clientAccount = _vault.clientAccount(request.client);
|
||||||
|
AccountId hostAccount = _vault.hostAccount(slot.host, slotIndex);
|
||||||
|
|
||||||
|
_transferToVault(slot.host, fund, hostAccount, uint128(collateralAmount));
|
||||||
|
_vault.flow(fund, clientAccount, hostAccount, request.slotPrice());
|
||||||
|
|
||||||
_marketplaceTotals.received += collateralAmount;
|
_marketplaceTotals.received += collateralAmount;
|
||||||
slot.currentCollateral = collateralPerSlot; // Even if he has collateral discounted, he is operating with full collateral
|
slot.currentCollateral = collateralPerSlot; // Even if he has collateral discounted, he is operating with full collateral
|
||||||
|
|
||||||
@ -251,10 +270,22 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian {
|
|||||||
) {
|
) {
|
||||||
context.state = RequestState.Started;
|
context.state = RequestState.Started;
|
||||||
context.startedAt = uint64(block.timestamp);
|
context.startedAt = uint64(block.timestamp);
|
||||||
|
_vault.extendLock(fund, Timestamp.wrap(uint40(context.endsAt)));
|
||||||
emit RequestFulfilled(requestId);
|
emit RequestFulfilled(requestId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _transferToVault(
|
||||||
|
address from,
|
||||||
|
FundId fund,
|
||||||
|
AccountId account,
|
||||||
|
uint128 amount
|
||||||
|
) private {
|
||||||
|
_vault.getToken().safeTransferFrom(from, address(this), amount);
|
||||||
|
_vault.getToken().approve(address(_vault), amount);
|
||||||
|
_vault.deposit(fund, account, amount);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notice Frees a slot, paying out rewards and returning collateral for
|
* @notice Frees a slot, paying out rewards and returning collateral for
|
||||||
finished or cancelled requests to the host that has filled the slot.
|
finished or cancelled requests to the host that has filled the slot.
|
||||||
@ -328,7 +359,19 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian {
|
|||||||
uint256 validatorRewardAmount = (slashedAmount *
|
uint256 validatorRewardAmount = (slashedAmount *
|
||||||
_config.collateral.validatorRewardPercentage) / 100;
|
_config.collateral.validatorRewardPercentage) / 100;
|
||||||
_marketplaceTotals.sent += validatorRewardAmount;
|
_marketplaceTotals.sent += validatorRewardAmount;
|
||||||
token().safeTransfer(msg.sender, validatorRewardAmount);
|
|
||||||
|
FundId fund = slot.requestId.asFundId();
|
||||||
|
AccountId hostAccount = _vault.hostAccount(
|
||||||
|
slot.host,
|
||||||
|
slot.slotIndex
|
||||||
|
);
|
||||||
|
AccountId validatorAccount = _vault.validatorAccount(msg.sender);
|
||||||
|
_vault.transfer(
|
||||||
|
fund,
|
||||||
|
hostAccount,
|
||||||
|
validatorAccount,
|
||||||
|
uint128(validatorRewardAmount)
|
||||||
|
);
|
||||||
|
|
||||||
slot.currentCollateral -= slashedAmount;
|
slot.currentCollateral -= slashedAmount;
|
||||||
if (missingProofs(slotId) >= _config.collateral.maxNumberOfSlashes) {
|
if (missingProofs(slotId) >= _config.collateral.maxNumberOfSlashes) {
|
||||||
@ -354,6 +397,17 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian {
|
|||||||
// we keep correctly the track of the funds that needs to be returned at the end.
|
// we keep correctly the track of the funds that needs to be returned at the end.
|
||||||
context.fundsToReturnToClient += _slotPayout(requestId, slot.filledAt);
|
context.fundsToReturnToClient += _slotPayout(requestId, slot.filledAt);
|
||||||
|
|
||||||
|
Request storage request = _requests[requestId];
|
||||||
|
|
||||||
|
FundId fund = requestId.asFundId();
|
||||||
|
AccountId hostAccount = _vault.hostAccount(
|
||||||
|
slot.host,
|
||||||
|
slot.slotIndex
|
||||||
|
);
|
||||||
|
AccountId clientAccount = _vault.clientAccount(request.client);
|
||||||
|
_vault.flow(fund, hostAccount, clientAccount, request.slotPrice());
|
||||||
|
_vault.burnAccount(fund, hostAccount);
|
||||||
|
|
||||||
_removeFromMySlots(slot.host, slotId);
|
_removeFromMySlots(slot.host, slotId);
|
||||||
delete _reservations[slotId]; // We purge all the reservations for the slot
|
delete _reservations[slotId]; // We purge all the reservations for the slot
|
||||||
slot.state = SlotState.Repair;
|
slot.state = SlotState.Repair;
|
||||||
@ -364,14 +418,14 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian {
|
|||||||
emit SlotFreed(requestId, slot.slotIndex);
|
emit SlotFreed(requestId, slot.slotIndex);
|
||||||
_resetMissingProofs(slotId);
|
_resetMissingProofs(slotId);
|
||||||
|
|
||||||
Request storage request = _requests[requestId];
|
|
||||||
uint256 slotsLost = request.ask.slots - context.slotsFilled;
|
uint256 slotsLost = request.ask.slots - context.slotsFilled;
|
||||||
if (
|
if (
|
||||||
slotsLost > request.ask.maxSlotLoss &&
|
slotsLost > request.ask.maxSlotLoss &&
|
||||||
context.state == RequestState.Started
|
context.state == RequestState.Started
|
||||||
) {
|
) {
|
||||||
context.state = RequestState.Failed;
|
context.state = RequestState.Failed;
|
||||||
context.endsAt = uint64(block.timestamp) - 1;
|
_vault.freezeFund(fund);
|
||||||
|
|
||||||
emit RequestFailed(requestId);
|
emit RequestFailed(requestId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -392,7 +446,9 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian {
|
|||||||
uint256 collateralAmount = slot.currentCollateral;
|
uint256 collateralAmount = slot.currentCollateral;
|
||||||
_marketplaceTotals.sent += (payoutAmount + collateralAmount);
|
_marketplaceTotals.sent += (payoutAmount + collateralAmount);
|
||||||
slot.state = SlotState.Paid;
|
slot.state = SlotState.Paid;
|
||||||
token().safeTransfer(slot.host, payoutAmount + collateralAmount);
|
FundId fund = requestId.asFundId();
|
||||||
|
AccountId account = _vault.hostAccount(slot.host, slot.slotIndex);
|
||||||
|
_vault.withdraw(fund, account);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -417,7 +473,9 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian {
|
|||||||
uint256 collateralAmount = slot.currentCollateral;
|
uint256 collateralAmount = slot.currentCollateral;
|
||||||
_marketplaceTotals.sent += (payoutAmount + collateralAmount);
|
_marketplaceTotals.sent += (payoutAmount + collateralAmount);
|
||||||
slot.state = SlotState.Paid;
|
slot.state = SlotState.Paid;
|
||||||
token().safeTransfer(slot.host, payoutAmount + collateralAmount);
|
FundId fund = requestId.asFundId();
|
||||||
|
AccountId account = _vault.hostAccount(slot.host, slot.slotIndex);
|
||||||
|
_vault.withdraw(fund, account);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -470,12 +528,20 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian {
|
|||||||
uint256 amount = context.fundsToReturnToClient;
|
uint256 amount = context.fundsToReturnToClient;
|
||||||
_marketplaceTotals.sent += amount;
|
_marketplaceTotals.sent += amount;
|
||||||
|
|
||||||
token().safeTransfer(request.client, amount);
|
FundId fund = requestId.asFundId();
|
||||||
|
AccountId account = _vault.clientAccount(request.client);
|
||||||
|
_vault.withdraw(fund, account);
|
||||||
|
|
||||||
// We zero out the funds tracking in order to prevent double-spends
|
// We zero out the funds tracking in order to prevent double-spends
|
||||||
context.fundsToReturnToClient = 0;
|
context.fundsToReturnToClient = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function withdrawByValidator(RequestId requestId) public {
|
||||||
|
FundId fund = requestId.asFundId();
|
||||||
|
AccountId account = _vault.validatorAccount(msg.sender);
|
||||||
|
_vault.withdraw(fund, account);
|
||||||
|
}
|
||||||
|
|
||||||
function getActiveSlot(
|
function getActiveSlot(
|
||||||
SlotId slotId
|
SlotId slotId
|
||||||
) public view slotIsNotFree(slotId) returns (ActiveSlot memory) {
|
) public view slotIsNotFree(slotId) returns (ActiveSlot memory) {
|
||||||
@ -510,7 +576,11 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian {
|
|||||||
|
|
||||||
function requestEnd(RequestId requestId) public view returns (uint64) {
|
function requestEnd(RequestId requestId) public view returns (uint64) {
|
||||||
RequestState state = requestState(requestId);
|
RequestState state = requestState(requestId);
|
||||||
if (state == RequestState.New || state == RequestState.Started) {
|
if (
|
||||||
|
state == RequestState.New ||
|
||||||
|
state == RequestState.Started ||
|
||||||
|
state == RequestState.Failed
|
||||||
|
) {
|
||||||
return _requestContexts[requestId].endsAt;
|
return _requestContexts[requestId].endsAt;
|
||||||
}
|
}
|
||||||
if (state == RequestState.Cancelled) {
|
if (state == RequestState.Cancelled) {
|
||||||
|
|||||||
53
contracts/marketplace/VaultHelpers.sol
Normal file
53
contracts/marketplace/VaultHelpers.sol
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity 0.8.28;
|
||||||
|
|
||||||
|
import "../Requests.sol";
|
||||||
|
import "../Vault.sol";
|
||||||
|
|
||||||
|
import "hardhat/console.sol";
|
||||||
|
|
||||||
|
library VaultHelpers {
|
||||||
|
enum VaultRole {
|
||||||
|
client,
|
||||||
|
host,
|
||||||
|
validator
|
||||||
|
}
|
||||||
|
|
||||||
|
function clientAccount(
|
||||||
|
Vault vault,
|
||||||
|
address client
|
||||||
|
) internal pure returns (AccountId) {
|
||||||
|
bytes12 discriminator = bytes12(bytes1(uint8(VaultRole.client)));
|
||||||
|
return vault.encodeAccountId(client, discriminator);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hostAccount(
|
||||||
|
Vault vault,
|
||||||
|
address host,
|
||||||
|
uint64 slotIndex
|
||||||
|
) internal pure returns (AccountId) {
|
||||||
|
bytes12 role = bytes12(bytes1(uint8(VaultRole.host)));
|
||||||
|
bytes12 index = bytes12(uint96(slotIndex));
|
||||||
|
bytes12 discriminator = role | index;
|
||||||
|
return vault.encodeAccountId(host, discriminator);
|
||||||
|
}
|
||||||
|
|
||||||
|
function validatorAccount(
|
||||||
|
Vault vault,
|
||||||
|
address validator
|
||||||
|
) internal pure returns (AccountId) {
|
||||||
|
bytes12 discriminator = bytes12(bytes1(uint8(VaultRole.validator)));
|
||||||
|
return vault.encodeAccountId(validator, discriminator);
|
||||||
|
}
|
||||||
|
|
||||||
|
function asFundId(RequestId requestId) internal pure returns (FundId) {
|
||||||
|
return FundId.wrap(RequestId.unwrap(requestId));
|
||||||
|
}
|
||||||
|
|
||||||
|
function slotPrice(
|
||||||
|
Request memory request
|
||||||
|
) internal pure returns (TokensPerSecond) {
|
||||||
|
uint256 price = request.ask.pricePerBytePerSecond * request.ask.slotSize;
|
||||||
|
return TokensPerSecond.wrap(uint96(price));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,6 +6,9 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|||||||
import "./Accounts.sol";
|
import "./Accounts.sol";
|
||||||
import "./Funds.sol";
|
import "./Funds.sol";
|
||||||
|
|
||||||
|
/// Unique identifier for a fund, chosen by the controller
|
||||||
|
type FundId is bytes32;
|
||||||
|
|
||||||
/// Records account balances and token flows. Accounts are separated into funds.
|
/// Records account balances and token flows. Accounts are separated into funds.
|
||||||
/// Funds are kept separate between controllers.
|
/// Funds are kept separate between controllers.
|
||||||
///
|
///
|
||||||
@ -46,8 +49,6 @@ abstract contract VaultBase {
|
|||||||
|
|
||||||
/// Represents a smart contract that can redistribute and burn tokens in funds
|
/// Represents a smart contract that can redistribute and burn tokens in funds
|
||||||
type Controller is address;
|
type Controller is address;
|
||||||
/// Unique identifier for a fund, chosen by the controller
|
|
||||||
type FundId is bytes32;
|
|
||||||
|
|
||||||
/// Each controller has its own set of funds
|
/// Each controller has its own set of funds
|
||||||
mapping(Controller => mapping(FundId => Fund)) private _funds;
|
mapping(Controller => mapping(FundId => Fund)) private _funds;
|
||||||
|
|||||||
@ -23,7 +23,11 @@ const {
|
|||||||
waitUntilSlotFailed,
|
waitUntilSlotFailed,
|
||||||
patchOverloads,
|
patchOverloads,
|
||||||
} = require("./marketplace")
|
} = require("./marketplace")
|
||||||
const { maxPrice, pricePerSlotPerSecond } = require("./price")
|
const {
|
||||||
|
maxPrice,
|
||||||
|
pricePerSlotPerSecond,
|
||||||
|
payoutForDuration,
|
||||||
|
} = require("./price")
|
||||||
const { collateralPerSlot } = require("./collateral")
|
const { collateralPerSlot } = require("./collateral")
|
||||||
const {
|
const {
|
||||||
snapshot,
|
snapshot,
|
||||||
@ -500,15 +504,6 @@ describe("Marketplace", function () {
|
|||||||
).to.equal(requestTime + request.ask.duration)
|
).to.equal(requestTime + request.ask.duration)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("sets request end time to the past once failed", async function () {
|
|
||||||
await waitUntilStarted(marketplace, request, proof, token)
|
|
||||||
await waitUntilFailed(marketplace, request)
|
|
||||||
const now = await currentTime()
|
|
||||||
await expect(await marketplace.requestEnd(requestId(request))).to.be.eq(
|
|
||||||
now - 1
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("sets request end time to the past once cancelled", async function () {
|
it("sets request end time to the past once cancelled", async function () {
|
||||||
await marketplace.reserveSlot(slot.request, slot.index)
|
await marketplace.reserveSlot(slot.request, slot.index)
|
||||||
await marketplace.fillSlot(slot.request, slot.index, proof)
|
await marketplace.fillSlot(slot.request, slot.index, proof)
|
||||||
@ -583,7 +578,7 @@ describe("Marketplace", function () {
|
|||||||
await token.approve(marketplace.address, collateral)
|
await token.approve(marketplace.address, collateral)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("finished request pays out reward based on time hosted", async function () {
|
it("pays out finished request based on time hosted", async function () {
|
||||||
// We are advancing the time because most of the slots will be filled somewhere
|
// We are advancing the time because most of the slots will be filled somewhere
|
||||||
// in the "expiry window" and not at its beginning. This is more "real" setup
|
// in the "expiry window" and not at its beginning. This is more "real" setup
|
||||||
// and demonstrates the partial payout feature better.
|
// and demonstrates the partial payout feature better.
|
||||||
@ -601,7 +596,6 @@ describe("Marketplace", function () {
|
|||||||
await marketplace.freeSlot(slotId(slot))
|
await marketplace.freeSlot(slotId(slot))
|
||||||
const endBalanceHost = await token.balanceOf(host.address)
|
const endBalanceHost = await token.balanceOf(host.address)
|
||||||
|
|
||||||
expect(expectedPayouts[slot.index]).to.be.lt(maxPrice(request))
|
|
||||||
const collateral = collateralPerSlot(request)
|
const collateral = collateralPerSlot(request)
|
||||||
expect(endBalanceHost - startBalanceHost).to.equal(
|
expect(endBalanceHost - startBalanceHost).to.equal(
|
||||||
expectedPayouts[slot.index] + collateral
|
expectedPayouts[slot.index] + collateral
|
||||||
@ -805,18 +799,24 @@ describe("Marketplace", function () {
|
|||||||
expect(endBalance - startBalance).to.equal(maxPrice(request))
|
expect(endBalance - startBalance).to.equal(maxPrice(request))
|
||||||
})
|
})
|
||||||
|
|
||||||
it("withdraws full price for failed requests to the client", async function () {
|
it("refunds the client for the remaining time when request fails", async function () {
|
||||||
await waitUntilStarted(marketplace, request, proof, token)
|
await waitUntilStarted(marketplace, request, proof, token)
|
||||||
await waitUntilFailed(marketplace, request)
|
await waitUntilFailed(marketplace, request)
|
||||||
|
const failedAt = await currentTime()
|
||||||
|
await waitUntilFinished(marketplace, requestId(request))
|
||||||
|
const finishedAt = await currentTime()
|
||||||
|
|
||||||
switchAccount(client)
|
switchAccount(client)
|
||||||
|
|
||||||
const startBalance = await token.balanceOf(client.address)
|
const startBalance = await token.balanceOf(client.address)
|
||||||
await marketplace.withdrawFunds(slot.request)
|
await marketplace.withdrawFunds(slot.request)
|
||||||
|
|
||||||
const endBalance = await token.balanceOf(client.address)
|
const endBalance = await token.balanceOf(client.address)
|
||||||
|
|
||||||
expect(endBalance - startBalance).to.equal(maxPrice(request))
|
const expectedRefund =
|
||||||
|
(finishedAt - failedAt) *
|
||||||
|
request.ask.slots *
|
||||||
|
pricePerSlotPerSecond(request)
|
||||||
|
expect(endBalance - startBalance).to.be.gte(expectedRefund)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("withdraws to the client for cancelled requests lowered by hosts payout", async function () {
|
it("withdraws to the client for cancelled requests lowered by hosts payout", async function () {
|
||||||
@ -844,21 +844,21 @@ describe("Marketplace", function () {
|
|||||||
|
|
||||||
it("refunds the client when slot is freed and not repaired", async function () {
|
it("refunds the client when slot is freed and not repaired", async function () {
|
||||||
const payouts = await waitUntilStarted(marketplace, request, proof, token)
|
const payouts = await waitUntilStarted(marketplace, request, proof, token)
|
||||||
|
await advanceTime(10)
|
||||||
await expect(marketplace.freeSlot(slotId(slot))).to.emit(
|
await marketplace.freeSlot(slotId(slot))
|
||||||
marketplace,
|
const freedAt = await currentTime()
|
||||||
"SlotFreed"
|
const requestEnd = await marketplace.requestEnd(requestId(request))
|
||||||
)
|
|
||||||
await waitUntilFinished(marketplace, requestId(request))
|
await waitUntilFinished(marketplace, requestId(request))
|
||||||
|
|
||||||
switchAccount(client)
|
switchAccount(client)
|
||||||
const startBalance = await token.balanceOf(client.address)
|
const startBalance = await token.balanceOf(client.address)
|
||||||
await marketplace.withdrawFunds(slot.request)
|
await marketplace.withdrawFunds(slot.request)
|
||||||
const endBalance = await token.balanceOf(client.address)
|
const endBalance = await token.balanceOf(client.address)
|
||||||
|
|
||||||
|
const hostPayouts = payouts.reduce((a, b) => a + b, 0)
|
||||||
|
const refund = payoutForDuration(request, freedAt, requestEnd)
|
||||||
expect(endBalance - startBalance).to.equal(
|
expect(endBalance - startBalance).to.equal(
|
||||||
maxPrice(request) -
|
maxPrice(request) - hostPayouts + refund
|
||||||
payouts.reduce((a, b) => a + b, 0) + // This is the amount that user gets refunded for filling period in expiry window
|
|
||||||
payouts[slot.index] // This is the refunded amount for the freed slot
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -1195,13 +1195,14 @@ describe("Marketplace", function () {
|
|||||||
|
|
||||||
switchAccount(validator)
|
switchAccount(validator)
|
||||||
|
|
||||||
const startBalance = await token.balanceOf(validator.address)
|
|
||||||
|
|
||||||
await waitUntilProofIsRequired(id)
|
await waitUntilProofIsRequired(id)
|
||||||
let missedPeriod = periodOf(await currentTime())
|
let missedPeriod = periodOf(await currentTime())
|
||||||
await advanceTime(period + 1)
|
await advanceTime(period + 1)
|
||||||
await marketplace.markProofAsMissing(id, missedPeriod)
|
await marketplace.markProofAsMissing(id, missedPeriod)
|
||||||
|
|
||||||
|
const startBalance = await token.balanceOf(validator.address)
|
||||||
|
await waitUntilFinished(marketplace, slot.request)
|
||||||
|
await marketplace.withdrawByValidator(slot.request)
|
||||||
const endBalance = await token.balanceOf(validator.address)
|
const endBalance = await token.balanceOf(validator.address)
|
||||||
|
|
||||||
const collateral = collateralPerSlot(request)
|
const collateral = collateralPerSlot(request)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user