mirror of
https://github.com/status-im/dagger-contracts.git
synced 2025-03-03 07:40:57 +00:00
[marketplace] alias bytes32 types
`RequestId`, `SlotId`, `LockId`, `ProofId`, `EndId` types were created to avoid confusion and enforce compiler restrictions.
This commit is contained in:
parent
bac2675bb2
commit
cfb70897f8
@ -1,5 +1,5 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.8;
|
||||||
|
|
||||||
/// Implements account locking. The main goal of this design is to allow
|
/// Implements account locking. The main goal of this design is to allow
|
||||||
/// unlocking of multiple accounts in O(1). To achieve this we keep a list of
|
/// unlocking of multiple accounts in O(1). To achieve this we keep a list of
|
||||||
@ -8,14 +8,16 @@ pragma solidity ^0.8.0;
|
|||||||
/// this operation does not become too expensive in gas costs, a maximum amount
|
/// this operation does not become too expensive in gas costs, a maximum amount
|
||||||
/// of active locks per account is enforced.
|
/// of active locks per account is enforced.
|
||||||
contract AccountLocks {
|
contract AccountLocks {
|
||||||
|
type LockId is bytes32;
|
||||||
|
|
||||||
uint256 public constant MAX_LOCKS_PER_ACCOUNT = 128;
|
uint256 public constant MAX_LOCKS_PER_ACCOUNT = 128;
|
||||||
|
|
||||||
mapping(bytes32 => Lock) private locks;
|
mapping(LockId => Lock) private locks;
|
||||||
mapping(address => Account) private accounts;
|
mapping(address => Account) private accounts;
|
||||||
|
|
||||||
/// Creates a lock that can be used to lock accounts. The id needs to be
|
/// Creates a lock that can be used to lock accounts. The id needs to be
|
||||||
/// unique and collision resistant. The expiry time is given in unix time.
|
/// unique and collision resistant. The expiry time is given in unix time.
|
||||||
function _createLock(bytes32 id, uint256 expiry) internal {
|
function _createLock(LockId id, uint256 expiry) internal {
|
||||||
require(locks[id].owner == address(0), "Lock already exists");
|
require(locks[id].owner == address(0), "Lock already exists");
|
||||||
locks[id] = Lock(msg.sender, expiry, false);
|
locks[id] = Lock(msg.sender, expiry, false);
|
||||||
}
|
}
|
||||||
@ -24,9 +26,9 @@ contract AccountLocks {
|
|||||||
/// can the account be unlocked again.
|
/// can the account be unlocked again.
|
||||||
/// Calling this function triggers a cleanup of inactive locks, making this
|
/// Calling this function triggers a cleanup of inactive locks, making this
|
||||||
/// an O(N) operation, where N = MAX_LOCKS_PER_ACCOUNT.
|
/// an O(N) operation, where N = MAX_LOCKS_PER_ACCOUNT.
|
||||||
function _lock(address account, bytes32 lockId) internal {
|
function _lock(address account, LockId lockId) internal {
|
||||||
require(locks[lockId].owner != address(0), "Lock does not exist");
|
require(locks[lockId].owner != address(0), "Lock does not exist");
|
||||||
bytes32[] storage accountLocks = accounts[account].locks;
|
LockId[] storage accountLocks = accounts[account].locks;
|
||||||
removeInactiveLocks(accountLocks);
|
removeInactiveLocks(accountLocks);
|
||||||
require(accountLocks.length < MAX_LOCKS_PER_ACCOUNT, "Max locks reached");
|
require(accountLocks.length < MAX_LOCKS_PER_ACCOUNT, "Max locks reached");
|
||||||
accountLocks.push(lockId);
|
accountLocks.push(lockId);
|
||||||
@ -35,7 +37,7 @@ contract AccountLocks {
|
|||||||
/// Unlocks a lock, thereby freeing any accounts that are attached to this
|
/// Unlocks a lock, thereby freeing any accounts that are attached to this
|
||||||
/// lock. This is an O(1) operation. Only the party that created the lock is
|
/// lock. This is an O(1) operation. Only the party that created the lock is
|
||||||
/// allowed to unlock it.
|
/// allowed to unlock it.
|
||||||
function _unlock(bytes32 lockId) internal {
|
function _unlock(LockId lockId) internal {
|
||||||
Lock storage lock = locks[lockId];
|
Lock storage lock = locks[lockId];
|
||||||
require(lock.owner != address(0), "Lock does not exist");
|
require(lock.owner != address(0), "Lock does not exist");
|
||||||
require(lock.owner == msg.sender, "Only lock creator can unlock");
|
require(lock.owner == msg.sender, "Only lock creator can unlock");
|
||||||
@ -46,7 +48,7 @@ contract AccountLocks {
|
|||||||
/// NOTE: We do not need to check that msg.sender is the lock.owner because
|
/// NOTE: We do not need to check that msg.sender is the lock.owner because
|
||||||
/// this function is internal, and is only called after all checks have been
|
/// this function is internal, and is only called after all checks have been
|
||||||
/// performed in Marketplace.fillSlot.
|
/// performed in Marketplace.fillSlot.
|
||||||
function _extendLockExpiryTo(bytes32 lockId, uint256 expiry) internal {
|
function _extendLockExpiryTo(LockId lockId, uint256 expiry) internal {
|
||||||
Lock storage lock = locks[lockId];
|
Lock storage lock = locks[lockId];
|
||||||
require(lock.owner != address(0), "Lock does not exist");
|
require(lock.owner != address(0), "Lock does not exist");
|
||||||
require(lock.expiry >= block.timestamp, "Lock already expired");
|
require(lock.expiry >= block.timestamp, "Lock already expired");
|
||||||
@ -58,12 +60,12 @@ contract AccountLocks {
|
|||||||
/// Calling this function triggers a cleanup of inactive locks, making this
|
/// Calling this function triggers a cleanup of inactive locks, making this
|
||||||
/// an O(N) operation, where N = MAX_LOCKS_PER_ACCOUNT.
|
/// an O(N) operation, where N = MAX_LOCKS_PER_ACCOUNT.
|
||||||
function _unlockAccount() internal {
|
function _unlockAccount() internal {
|
||||||
bytes32[] storage accountLocks = accounts[msg.sender].locks;
|
LockId[] storage accountLocks = accounts[msg.sender].locks;
|
||||||
removeInactiveLocks(accountLocks);
|
removeInactiveLocks(accountLocks);
|
||||||
require(accountLocks.length == 0, "Account locked");
|
require(accountLocks.length == 0, "Account locked");
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeInactiveLocks(bytes32[] storage lockIds) private {
|
function removeInactiveLocks(LockId[] storage lockIds) private {
|
||||||
uint256 index = 0;
|
uint256 index = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (index >= lockIds.length) {
|
if (index >= lockIds.length) {
|
||||||
@ -89,6 +91,6 @@ contract AccountLocks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct Account {
|
struct Account {
|
||||||
bytes32[] locks;
|
LockId[] locks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.8;
|
||||||
|
|
||||||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||||
import "@openzeppelin/contracts/utils/math/Math.sol";
|
import "@openzeppelin/contracts/utils/math/Math.sol";
|
||||||
@ -7,11 +7,14 @@ import "./Collateral.sol";
|
|||||||
import "./Proofs.sol";
|
import "./Proofs.sol";
|
||||||
|
|
||||||
contract Marketplace is Collateral, Proofs {
|
contract Marketplace is Collateral, Proofs {
|
||||||
|
type RequestId is bytes32;
|
||||||
|
type SlotId is bytes32;
|
||||||
|
|
||||||
uint256 public immutable collateral;
|
uint256 public immutable collateral;
|
||||||
MarketplaceFunds private funds;
|
MarketplaceFunds private funds;
|
||||||
mapping(bytes32 => Request) private requests;
|
mapping(RequestId => Request) private requests;
|
||||||
mapping(bytes32 => RequestContext) private requestContexts;
|
mapping(RequestId => RequestContext) private requestContexts;
|
||||||
mapping(bytes32 => Slot) private slots;
|
mapping(SlotId => Slot) private slots;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
IERC20 _token,
|
IERC20 _token,
|
||||||
@ -33,17 +36,17 @@ contract Marketplace is Collateral, Proofs {
|
|||||||
{
|
{
|
||||||
require(request.client == msg.sender, "Invalid client address");
|
require(request.client == msg.sender, "Invalid client address");
|
||||||
|
|
||||||
bytes32 id = keccak256(abi.encode(request));
|
RequestId id = _toRequestId(request);
|
||||||
require(requests[id].client == address(0), "Request already exists");
|
require(requests[id].client == address(0), "Request already exists");
|
||||||
|
|
||||||
requests[id] = request;
|
requests[id] = request;
|
||||||
RequestContext storage context = _context(id);
|
RequestContext storage context = _context(id);
|
||||||
// set contract end time to `duration` from now (time request was created)
|
// set contract end time to `duration` from now (time request was created)
|
||||||
context.endsAt = block.timestamp + request.ask.duration;
|
context.endsAt = block.timestamp + request.ask.duration;
|
||||||
_setProofEnd(id, context.endsAt);
|
_setProofEnd(_toEndId(id), context.endsAt);
|
||||||
|
|
||||||
|
|
||||||
_createLock(id, request.expiry);
|
_createLock(_toLockId(id), request.expiry);
|
||||||
|
|
||||||
uint256 amount = price(request);
|
uint256 amount = price(request);
|
||||||
funds.received += amount;
|
funds.received += amount;
|
||||||
@ -54,22 +57,27 @@ contract Marketplace is Collateral, Proofs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fillSlot(
|
function fillSlot(
|
||||||
bytes32 requestId,
|
RequestId requestId,
|
||||||
uint256 slotIndex,
|
uint256 slotIndex,
|
||||||
bytes calldata proof
|
bytes calldata proof
|
||||||
) public requestMustAcceptProofs(requestId) marketplaceInvariant {
|
) public requestMustAcceptProofs(requestId) marketplaceInvariant {
|
||||||
Request storage request = _request(requestId);
|
Request storage request = _request(requestId);
|
||||||
require(slotIndex < request.ask.slots, "Invalid slot");
|
require(slotIndex < request.ask.slots, "Invalid slot");
|
||||||
|
|
||||||
bytes32 slotId = keccak256(abi.encode(requestId, slotIndex));
|
SlotId slotId = _toSlotId(requestId, slotIndex);
|
||||||
Slot storage slot = slots[slotId];
|
Slot storage slot = slots[slotId];
|
||||||
require(slot.host == address(0), "Slot already filled");
|
require(slot.host == address(0), "Slot already filled");
|
||||||
|
|
||||||
require(balanceOf(msg.sender) >= collateral, "Insufficient collateral");
|
require(balanceOf(msg.sender) >= collateral, "Insufficient collateral");
|
||||||
_lock(msg.sender, requestId);
|
LockId lockId = _toLockId(requestId);
|
||||||
|
_lock(msg.sender, lockId);
|
||||||
|
|
||||||
_expectProofs(slotId, requestId, request.ask.proofProbability);
|
ProofId proofId = _toProofId(slotId);
|
||||||
_submitProof(slotId, proof);
|
_expectProofs(
|
||||||
|
proofId,
|
||||||
|
requestId,
|
||||||
|
request.ask.proofProbability);
|
||||||
|
_submitProof(proofId, proof);
|
||||||
|
|
||||||
slot.host = msg.sender;
|
slot.host = msg.sender;
|
||||||
slot.requestId = requestId;
|
slot.requestId = requestId;
|
||||||
@ -79,16 +87,16 @@ contract Marketplace is Collateral, Proofs {
|
|||||||
if (context.slotsFilled == request.ask.slots) {
|
if (context.slotsFilled == request.ask.slots) {
|
||||||
context.state = RequestState.Started;
|
context.state = RequestState.Started;
|
||||||
context.startedAt = block.timestamp;
|
context.startedAt = block.timestamp;
|
||||||
_extendLockExpiryTo(requestId, context.endsAt);
|
_extendLockExpiryTo(lockId, context.endsAt);
|
||||||
emit RequestFulfilled(requestId);
|
emit RequestFulfilled(requestId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _freeSlot(
|
function _freeSlot(
|
||||||
bytes32 slotId
|
SlotId slotId
|
||||||
) internal slotMustAcceptProofs(slotId) marketplaceInvariant {
|
) internal slotMustAcceptProofs(slotId) marketplaceInvariant {
|
||||||
Slot storage slot = _slot(slotId);
|
Slot storage slot = _slot(slotId);
|
||||||
bytes32 requestId = slot.requestId;
|
RequestId requestId = slot.requestId;
|
||||||
RequestContext storage context = requestContexts[requestId];
|
RequestContext storage context = requestContexts[requestId];
|
||||||
|
|
||||||
// TODO: burn host's slot collateral except for repair costs + mark proof
|
// TODO: burn host's slot collateral except for repair costs + mark proof
|
||||||
@ -96,10 +104,10 @@ contract Marketplace is Collateral, Proofs {
|
|||||||
// Slot collateral is not yet implemented as the design decision was
|
// Slot collateral is not yet implemented as the design decision was
|
||||||
// not finalised.
|
// not finalised.
|
||||||
|
|
||||||
_unexpectProofs(slotId);
|
_unexpectProofs(_toProofId(slotId));
|
||||||
|
|
||||||
slot.host = address(0);
|
slot.host = address(0);
|
||||||
slot.requestId = 0;
|
slot.requestId = RequestId.wrap(0);
|
||||||
context.slotsFilled -= 1;
|
context.slotsFilled -= 1;
|
||||||
emit SlotFreed(requestId, slotId);
|
emit SlotFreed(requestId, slotId);
|
||||||
|
|
||||||
@ -118,16 +126,14 @@ contract Marketplace is Collateral, Proofs {
|
|||||||
// TODO: send client remaining funds
|
// TODO: send client remaining funds
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function payoutSlot(RequestId requestId, uint256 slotIndex)
|
||||||
function payoutSlot(bytes32 requestId, uint256 slotIndex)
|
|
||||||
public
|
public
|
||||||
marketplaceInvariant
|
marketplaceInvariant
|
||||||
{
|
{
|
||||||
require(_isFinished(requestId), "Contract not ended");
|
require(_isFinished(requestId), "Contract not ended");
|
||||||
RequestContext storage context = _context(requestId);
|
RequestContext storage context = _context(requestId);
|
||||||
context.state = RequestState.Finished;
|
context.state = RequestState.Finished;
|
||||||
|
SlotId slotId = _toSlotId(requestId, slotIndex);
|
||||||
bytes32 slotId = keccak256(abi.encode(requestId, slotIndex));
|
|
||||||
Slot storage slot = _slot(slotId);
|
Slot storage slot = _slot(slotId);
|
||||||
require(!slot.hostPaid, "Already paid");
|
require(!slot.hostPaid, "Already paid");
|
||||||
uint256 amount = pricePerSlot(requests[requestId]);
|
uint256 amount = pricePerSlot(requests[requestId]);
|
||||||
@ -140,7 +146,7 @@ contract Marketplace is Collateral, Proofs {
|
|||||||
/// @notice Withdraws storage request funds back to the client that deposited them.
|
/// @notice Withdraws storage request funds back to the client that deposited them.
|
||||||
/// @dev Request must be expired, must be in RequestState.New, and the transaction must originate from the depositer address.
|
/// @dev Request must be expired, must be in RequestState.New, and the transaction must originate from the depositer address.
|
||||||
/// @param requestId the id of the request
|
/// @param requestId the id of the request
|
||||||
function withdrawFunds(bytes32 requestId) public marketplaceInvariant {
|
function withdrawFunds(RequestId requestId) public marketplaceInvariant {
|
||||||
Request storage request = requests[requestId];
|
Request storage request = requests[requestId];
|
||||||
require(block.timestamp > request.expiry, "Request not yet timed out");
|
require(block.timestamp > request.expiry, "Request not yet timed out");
|
||||||
require(request.client == msg.sender, "Invalid client address");
|
require(request.client == msg.sender, "Invalid client address");
|
||||||
@ -165,7 +171,7 @@ contract Marketplace is Collateral, Proofs {
|
|||||||
/// @dev Handles the case when a request may have been cancelled, but the client has not withdrawn its funds yet, and therefore the state has not yet been updated.
|
/// @dev Handles the case when a request may have been cancelled, but the client has not withdrawn its funds yet, and therefore the state has not yet been updated.
|
||||||
/// @param requestId the id of the request
|
/// @param requestId the id of the request
|
||||||
/// @return true if request is cancelled
|
/// @return true if request is cancelled
|
||||||
function _isCancelled(bytes32 requestId) internal view returns (bool) {
|
function _isCancelled(RequestId requestId) internal view returns (bool) {
|
||||||
RequestContext storage context = _context(requestId);
|
RequestContext storage context = _context(requestId);
|
||||||
return
|
return
|
||||||
context.state == RequestState.Cancelled ||
|
context.state == RequestState.Cancelled ||
|
||||||
@ -179,7 +185,7 @@ contract Marketplace is Collateral, Proofs {
|
|||||||
/// @dev Handles the case when a request may have been finished, but the state has not yet been updated by a transaction.
|
/// @dev Handles the case when a request may have been finished, but the state has not yet been updated by a transaction.
|
||||||
/// @param requestId the id of the request
|
/// @param requestId the id of the request
|
||||||
/// @return true if request is finished
|
/// @return true if request is finished
|
||||||
function _isFinished(bytes32 requestId) internal view returns (bool) {
|
function _isFinished(RequestId requestId) internal view returns (bool) {
|
||||||
RequestContext memory context = _context(requestId);
|
RequestContext memory context = _context(requestId);
|
||||||
return
|
return
|
||||||
context.state == RequestState.Finished ||
|
context.state == RequestState.Finished ||
|
||||||
@ -193,9 +199,13 @@ contract Marketplace is Collateral, Proofs {
|
|||||||
/// @dev Returns requestId that is mapped to the slotId
|
/// @dev Returns requestId that is mapped to the slotId
|
||||||
/// @param slotId id of the slot
|
/// @param slotId id of the slot
|
||||||
/// @return if of the request the slot belongs to
|
/// @return if of the request the slot belongs to
|
||||||
function _getRequestIdForSlot(bytes32 slotId) internal view returns (bytes32) {
|
function _getRequestIdForSlot(SlotId slotId)
|
||||||
|
internal
|
||||||
|
view
|
||||||
|
returns (RequestId)
|
||||||
|
{
|
||||||
Slot memory slot = _slot(slotId);
|
Slot memory slot = _slot(slotId);
|
||||||
require(slot.requestId != 0, "Missing request id");
|
require(_notEqual(slot.requestId, 0), "Missing request id");
|
||||||
return slot.requestId;
|
return slot.requestId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,28 +213,36 @@ contract Marketplace is Collateral, Proofs {
|
|||||||
/// @dev Handles the case when a request may have been cancelled, but the client has not withdrawn its funds yet, and therefore the state has not yet been updated.
|
/// @dev Handles the case when a request may have been cancelled, but the client has not withdrawn its funds yet, and therefore the state has not yet been updated.
|
||||||
/// @param slotId the id of the slot
|
/// @param slotId the id of the slot
|
||||||
/// @return true if request is cancelled
|
/// @return true if request is cancelled
|
||||||
function _isSlotCancelled(bytes32 slotId) internal view returns (bool) {
|
function _isSlotCancelled(SlotId slotId) internal view returns (bool) {
|
||||||
bytes32 requestId = _getRequestIdForSlot(slotId);
|
RequestId requestId = _getRequestIdForSlot(slotId);
|
||||||
return _isCancelled(requestId);
|
return _isCancelled(requestId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _host(bytes32 slotId) internal view returns (address) {
|
function _host(SlotId slotId) internal view returns (address) {
|
||||||
return slots[slotId].host;
|
return slots[slotId].host;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _request(bytes32 requestId) internal view returns (Request storage) {
|
function _request(RequestId requestId)
|
||||||
|
internal
|
||||||
|
view
|
||||||
|
returns (Request storage)
|
||||||
|
{
|
||||||
Request storage request = requests[requestId];
|
Request storage request = requests[requestId];
|
||||||
require(request.client != address(0), "Unknown request");
|
require(request.client != address(0), "Unknown request");
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _slot(bytes32 slotId) internal view returns (Slot storage) {
|
function _slot(SlotId slotId) internal view returns (Slot storage) {
|
||||||
Slot storage slot = slots[slotId];
|
Slot storage slot = slots[slotId];
|
||||||
require(slot.host != address(0), "Slot empty");
|
require(slot.host != address(0), "Slot empty");
|
||||||
return slot;
|
return slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _context(bytes32 requestId) internal view returns (RequestContext storage) {
|
function _context(RequestId requestId)
|
||||||
|
internal
|
||||||
|
view
|
||||||
|
returns (RequestContext storage)
|
||||||
|
{
|
||||||
return requestContexts[requestId];
|
return requestContexts[requestId];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,7 +256,7 @@ contract Marketplace is Collateral, Proofs {
|
|||||||
|
|
||||||
function proofEnd(bytes32 slotId) public view returns (uint256) {
|
function proofEnd(bytes32 slotId) public view returns (uint256) {
|
||||||
Slot memory slot = _slot(slotId);
|
Slot memory slot = _slot(slotId);
|
||||||
uint256 end = _end(slot.requestId);
|
uint256 end = _end(_toEndId(slot.requestId));
|
||||||
if (_slotAcceptsProofs(slotId)) {
|
if (_slotAcceptsProofs(slotId)) {
|
||||||
return end;
|
return end;
|
||||||
} else {
|
} else {
|
||||||
@ -266,7 +284,7 @@ contract Marketplace is Collateral, Proofs {
|
|||||||
return request.ask.duration * request.ask.reward;
|
return request.ask.duration * request.ask.reward;
|
||||||
}
|
}
|
||||||
|
|
||||||
function state(bytes32 requestId) public view returns (RequestState) {
|
function state(RequestId requestId) public view returns (RequestState) {
|
||||||
if (_isCancelled(requestId)) {
|
if (_isCancelled(requestId)) {
|
||||||
return RequestState.Cancelled;
|
return RequestState.Cancelled;
|
||||||
} else if (_isFinished(requestId)) {
|
} else if (_isFinished(requestId)) {
|
||||||
@ -279,20 +297,52 @@ contract Marketplace is Collateral, Proofs {
|
|||||||
|
|
||||||
/// @notice returns true when the request is accepting proof submissions from hosts occupying slots.
|
/// @notice returns true when the request is accepting proof submissions from hosts occupying slots.
|
||||||
/// @dev Request state must be new or started, and must not be cancelled, finished, or failed.
|
/// @dev Request state must be new or started, and must not be cancelled, finished, or failed.
|
||||||
/// @param requestId id of the request for which to obtain state info
|
/// @param slotId id of the slot, that is mapped to a request, for which to obtain state info
|
||||||
function _requestAcceptsProofs(bytes32 requestId) internal view returns (bool) {
|
function _slotAcceptsProofs(SlotId slotId) internal view returns (bool) {
|
||||||
RequestState s = state(requestId);
|
RequestId requestId = _getRequestIdForSlot(slotId);
|
||||||
return s == RequestState.New || s == RequestState.Started;
|
return _requestAcceptsProofs(requestId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice returns true when the request is accepting proof submissions from hosts occupying slots.
|
/// @notice returns true when the request is accepting proof submissions from hosts occupying slots.
|
||||||
/// @dev Request state must be new or started, and must not be cancelled, finished, or failed.
|
/// @dev Request state must be new or started, and must not be cancelled, finished, or failed.
|
||||||
/// @param slotId id of the slot, that is mapped to a request, for which to obtain state info
|
/// @param requestId id of the request for which to obtain state info
|
||||||
function _slotAcceptsProofs(bytes32 slotId) internal view returns (bool) {
|
function _requestAcceptsProofs(RequestId requestId) internal view returns (bool) {
|
||||||
bytes32 requestId = _getRequestIdForSlot(slotId);
|
RequestState s = state(requestId);
|
||||||
return _requestAcceptsProofs(requestId);
|
return s == RequestState.New || s == RequestState.Started;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _toRequestId(Request memory request)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (RequestId)
|
||||||
|
{
|
||||||
|
return RequestId.wrap(keccak256(abi.encode(request)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function _toSlotId(
|
||||||
|
RequestId requestId,
|
||||||
|
uint256 slotIndex)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (SlotId)
|
||||||
|
{
|
||||||
|
return SlotId.wrap(keccak256(abi.encode(requestId, slotIndex)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function _toLockId(RequestId requestId) internal pure returns (LockId) {
|
||||||
|
return LockId.wrap(RequestId.unwrap(requestId));
|
||||||
|
}
|
||||||
|
|
||||||
|
function _toProofId(SlotId slotId) internal pure returns (ProofId) {
|
||||||
|
return ProofId.wrap(SlotId.unwrap(slotId));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function _notEqual(RequestId a, uint256 b) internal pure returns (bool) {
|
||||||
|
return RequestId.unwrap(a) != bytes32(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct Request {
|
struct Request {
|
||||||
address client;
|
address client;
|
||||||
Ask ask;
|
Ask ask;
|
||||||
@ -344,19 +394,19 @@ contract Marketplace is Collateral, Proofs {
|
|||||||
struct Slot {
|
struct Slot {
|
||||||
address host;
|
address host;
|
||||||
bool hostPaid;
|
bool hostPaid;
|
||||||
bytes32 requestId;
|
RequestId requestId;
|
||||||
}
|
}
|
||||||
|
|
||||||
event StorageRequested(bytes32 requestId, Ask ask);
|
event StorageRequested(RequestId requestId, Ask ask);
|
||||||
event RequestFulfilled(bytes32 indexed requestId);
|
event RequestFulfilled(RequestId indexed requestId);
|
||||||
event RequestFailed(bytes32 indexed requestId);
|
event RequestFailed(RequestId indexed requestId);
|
||||||
event SlotFilled(
|
event SlotFilled(
|
||||||
bytes32 indexed requestId,
|
RequestId indexed requestId,
|
||||||
uint256 indexed slotIndex,
|
uint256 indexed slotIndex,
|
||||||
bytes32 slotId
|
SlotId slotId
|
||||||
);
|
);
|
||||||
event SlotFreed(bytes32 indexed requestId, bytes32 slotId);
|
event SlotFreed(RequestId indexed requestId, SlotId slotId);
|
||||||
event RequestCancelled(bytes32 indexed requestId);
|
event RequestCancelled(RequestId indexed requestId);
|
||||||
|
|
||||||
modifier marketplaceInvariant() {
|
modifier marketplaceInvariant() {
|
||||||
MarketplaceFunds memory oldFunds = funds;
|
MarketplaceFunds memory oldFunds = funds;
|
||||||
@ -369,8 +419,8 @@ contract Marketplace is Collateral, Proofs {
|
|||||||
/// @notice Modifier that requires the request state to be that which is accepting proof submissions from hosts occupying slots.
|
/// @notice Modifier that requires the request state to be that which is accepting proof submissions from hosts occupying slots.
|
||||||
/// @dev Request state must be new or started, and must not be cancelled, finished, or failed.
|
/// @dev Request state must be new or started, and must not be cancelled, finished, or failed.
|
||||||
/// @param slotId id of the slot, that is mapped to a request, for which to obtain state info
|
/// @param slotId id of the slot, that is mapped to a request, for which to obtain state info
|
||||||
modifier slotMustAcceptProofs(bytes32 slotId) {
|
modifier slotMustAcceptProofs(SlotId slotId) {
|
||||||
bytes32 requestId = _getRequestIdForSlot(slotId);
|
RequestId requestId = _getRequestIdForSlot(slotId);
|
||||||
require(_requestAcceptsProofs(requestId), "Slot not accepting proofs");
|
require(_requestAcceptsProofs(requestId), "Slot not accepting proofs");
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
@ -378,7 +428,7 @@ contract Marketplace is Collateral, Proofs {
|
|||||||
/// @notice Modifier that requires the request state to be that which is accepting proof submissions from hosts occupying slots.
|
/// @notice Modifier that requires the request state to be that which is accepting proof submissions from hosts occupying slots.
|
||||||
/// @dev Request state must be new or started, and must not be cancelled, finished, or failed.
|
/// @dev Request state must be new or started, and must not be cancelled, finished, or failed.
|
||||||
/// @param requestId id of the request, for which to obtain state info
|
/// @param requestId id of the request, for which to obtain state info
|
||||||
modifier requestMustAcceptProofs(bytes32 requestId) {
|
modifier requestMustAcceptProofs(RequestId requestId) {
|
||||||
require(_requestAcceptsProofs(requestId), "Request not accepting proofs");
|
require(_requestAcceptsProofs(requestId), "Request not accepting proofs");
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.8;
|
||||||
|
|
||||||
contract Proofs {
|
contract Proofs {
|
||||||
|
type ProofId is bytes32;
|
||||||
|
|
||||||
uint256 private immutable period;
|
uint256 private immutable period;
|
||||||
uint256 private immutable timeout;
|
uint256 private immutable timeout;
|
||||||
uint8 private immutable downtime;
|
uint8 private immutable downtime;
|
||||||
@ -17,15 +19,15 @@ contract Proofs {
|
|||||||
downtime = __downtime;
|
downtime = __downtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
mapping(bytes32 => bool) private ids;
|
mapping(ProofId => bool) private ids;
|
||||||
mapping(bytes32 => uint256) private starts;
|
mapping(ProofId => uint256) private starts;
|
||||||
mapping(bytes32 => uint256) private ends;
|
mapping(EndId => uint256) private ends;
|
||||||
mapping(bytes32 => bytes32) private idEnds;
|
mapping(ProofId => EndId) private idEnds;
|
||||||
mapping(bytes32 => uint256) private probabilities;
|
mapping(ProofId => uint256) private probabilities;
|
||||||
mapping(bytes32 => uint256) private markers;
|
mapping(ProofId => uint256) private markers;
|
||||||
mapping(bytes32 => uint256) private missed;
|
mapping(ProofId => uint256) private missed;
|
||||||
mapping(bytes32 => mapping(uint256 => bool)) private received;
|
mapping(ProofId => mapping(uint256 => bool)) private received;
|
||||||
mapping(bytes32 => mapping(uint256 => bool)) private missing;
|
mapping(ProofId => mapping(uint256 => bool)) private missing;
|
||||||
|
|
||||||
function _period() internal view returns (uint256) {
|
function _period() internal view returns (uint256) {
|
||||||
return period;
|
return period;
|
||||||
@ -35,24 +37,24 @@ contract Proofs {
|
|||||||
return timeout;
|
return timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _end(bytes32 endId) internal view returns (uint256) {
|
function _end(ProofId id) internal view returns (uint256) {
|
||||||
uint256 end = ends[endId];
|
uint256 end = ends[endId];
|
||||||
require(end > 0, "Proof ending doesn't exist");
|
require(end > 0, "Proof ending doesn't exist");
|
||||||
return ends[endId];
|
return ends[endId];
|
||||||
}
|
}
|
||||||
|
|
||||||
function _endId(bytes32 id) internal view returns (bytes32) {
|
function _endId(ProofId id) internal view returns (EndId) {
|
||||||
bytes32 endId = idEnds[id];
|
EndId endId = idEnds[id];
|
||||||
require(endId > 0, "endId for given id doesn't exist");
|
require(endId > 0, "endId for given id doesn't exist");
|
||||||
return endId;
|
return endId;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _endFromId(bytes32 id) internal view returns (uint256) {
|
function _endFromId(ProofId id) internal view returns (uint256) {
|
||||||
bytes32 endId = _endId(id);
|
EndId endId = _endId(id);
|
||||||
return _end(endId);
|
return _end(endId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _missed(bytes32 id) internal view returns (uint256) {
|
function _missed(ProofId id) internal view returns (uint256) {
|
||||||
return missed[id];
|
return missed[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,8 +72,8 @@ contract Proofs {
|
|||||||
/// @param endId Identifies the id of the proof expectation ending. Typically a request id. Different from id because the proof ending is shared amongst many ids.
|
/// @param endId Identifies the id of the proof expectation ending. Typically a request id. Different from id because the proof ending is shared amongst many ids.
|
||||||
/// @param probability The probability that a proof should be expected
|
/// @param probability The probability that a proof should be expected
|
||||||
function _expectProofs(
|
function _expectProofs(
|
||||||
bytes32 id, // typically slot id
|
ProofId id, // typically slot id
|
||||||
bytes32 endId, // typically request id, used so that the ending is global for all slots
|
EndId endId, // typically request id, used so that the ending is global for all slots
|
||||||
uint256 probability
|
uint256 probability
|
||||||
) internal {
|
) internal {
|
||||||
require(!ids[id], "Proof id already in use");
|
require(!ids[id], "Proof id already in use");
|
||||||
@ -83,25 +85,25 @@ contract Proofs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _unexpectProofs(
|
function _unexpectProofs(
|
||||||
bytes32 id
|
ProofId id
|
||||||
) internal {
|
) internal {
|
||||||
require(ids[id], "Proof id not in use");
|
require(ids[id], "Proof id not in use");
|
||||||
ids[id] = false;
|
ids[id] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _getPointer(bytes32 id, uint256 proofPeriod)
|
function _getPointer(ProofId id, uint256 proofPeriod)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (uint8)
|
returns (uint8)
|
||||||
{
|
{
|
||||||
uint256 blockNumber = block.number % 256;
|
uint256 blockNumber = block.number % 256;
|
||||||
uint256 periodNumber = proofPeriod % 256;
|
uint256 periodNumber = proofPeriod % 256;
|
||||||
uint256 idOffset = uint256(id) % 256;
|
uint256 idOffset = uint256(ProofId.unwrap(id)) % 256;
|
||||||
uint256 pointer = (blockNumber + periodNumber + idOffset) % 256;
|
uint256 pointer = (blockNumber + periodNumber + idOffset) % 256;
|
||||||
return uint8(pointer);
|
return uint8(pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _getPointer(bytes32 id) internal view returns (uint8) {
|
function _getPointer(ProofId id) internal view returns (uint8) {
|
||||||
return _getPointer(id, currentPeriod());
|
return _getPointer(id, currentPeriod());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +113,7 @@ contract Proofs {
|
|||||||
return keccak256(abi.encode(hash));
|
return keccak256(abi.encode(hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
function _getChallenge(bytes32 id, uint256 proofPeriod)
|
function _getChallenge(ProofId id, uint256 proofPeriod)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (bytes32)
|
returns (bytes32)
|
||||||
@ -119,11 +121,11 @@ contract Proofs {
|
|||||||
return _getChallenge(_getPointer(id, proofPeriod));
|
return _getChallenge(_getPointer(id, proofPeriod));
|
||||||
}
|
}
|
||||||
|
|
||||||
function _getChallenge(bytes32 id) internal view returns (bytes32) {
|
function _getChallenge(ProofId id) internal view returns (bytes32) {
|
||||||
return _getChallenge(id, currentPeriod());
|
return _getChallenge(id, currentPeriod());
|
||||||
}
|
}
|
||||||
|
|
||||||
function _getProofRequirement(bytes32 id, uint256 proofPeriod)
|
function _getProofRequirement(ProofId id, uint256 proofPeriod)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (bool isRequired, uint8 pointer)
|
returns (bool isRequired, uint8 pointer)
|
||||||
@ -141,7 +143,7 @@ contract Proofs {
|
|||||||
isRequired = ids[id] && uint256(challenge) % probability == 0;
|
isRequired = ids[id] && uint256(challenge) % probability == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _isProofRequired(bytes32 id, uint256 proofPeriod)
|
function _isProofRequired(ProofId id, uint256 proofPeriod)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (bool)
|
returns (bool)
|
||||||
@ -152,25 +154,25 @@ contract Proofs {
|
|||||||
return isRequired && pointer >= downtime;
|
return isRequired && pointer >= downtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _isProofRequired(bytes32 id) internal view returns (bool) {
|
function _isProofRequired(ProofId id) internal view returns (bool) {
|
||||||
return _isProofRequired(id, currentPeriod());
|
return _isProofRequired(id, currentPeriod());
|
||||||
}
|
}
|
||||||
|
|
||||||
function _willProofBeRequired(bytes32 id) internal view returns (bool) {
|
function _willProofBeRequired(ProofId id) internal view returns (bool) {
|
||||||
bool isRequired;
|
bool isRequired;
|
||||||
uint8 pointer;
|
uint8 pointer;
|
||||||
(isRequired, pointer) = _getProofRequirement(id, currentPeriod());
|
(isRequired, pointer) = _getProofRequirement(id, currentPeriod());
|
||||||
return isRequired && pointer < downtime;
|
return isRequired && pointer < downtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _submitProof(bytes32 id, bytes calldata proof) internal {
|
function _submitProof(ProofId id, bytes calldata proof) internal {
|
||||||
require(proof.length > 0, "Invalid proof"); // TODO: replace by actual check
|
require(proof.length > 0, "Invalid proof"); // TODO: replace by actual check
|
||||||
require(!received[id][currentPeriod()], "Proof already submitted");
|
require(!received[id][currentPeriod()], "Proof already submitted");
|
||||||
received[id][currentPeriod()] = true;
|
received[id][currentPeriod()] = true;
|
||||||
emit ProofSubmitted(id, proof);
|
emit ProofSubmitted(id, proof);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _markProofAsMissing(bytes32 id, uint256 missedPeriod) internal {
|
function _markProofAsMissing(ProofId id, uint256 missedPeriod) internal {
|
||||||
uint256 periodEnd = (missedPeriod + 1) * period;
|
uint256 periodEnd = (missedPeriod + 1) * period;
|
||||||
require(periodEnd < block.timestamp, "Period has not ended yet");
|
require(periodEnd < block.timestamp, "Period has not ended yet");
|
||||||
require(block.timestamp < periodEnd + timeout, "Validation timed out");
|
require(block.timestamp < periodEnd + timeout, "Validation timed out");
|
||||||
@ -192,5 +194,5 @@ contract Proofs {
|
|||||||
ends[endId] = ending;
|
ends[endId] = ending;
|
||||||
}
|
}
|
||||||
|
|
||||||
event ProofSubmitted(bytes32 id, bytes proof);
|
event ProofSubmitted(ProofId id, bytes proof);
|
||||||
}
|
}
|
||||||
|
@ -35,58 +35,59 @@ contract Storage is Collateral, Marketplace {
|
|||||||
minCollateralThreshold = _minCollateralThreshold;
|
minCollateralThreshold = _minCollateralThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRequest(bytes32 requestId) public view returns (Request memory) {
|
function getRequest(RequestId requestId) public view returns (Request memory) {
|
||||||
return _request(requestId);
|
return _request(requestId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSlot(bytes32 slotId) public view returns (Slot memory) {
|
function getSlot(SlotId slotId) public view returns (Slot memory) {
|
||||||
return _slot(slotId);
|
return _slot(slotId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getHost(bytes32 slotId) public view returns (address) {
|
function getHost(SlotId slotId) public view returns (address) {
|
||||||
return _host(slotId);
|
return _host(slotId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function missingProofs(bytes32 slotId) public view returns (uint256) {
|
function missingProofs(SlotId slotId) public view returns (uint256) {
|
||||||
return _missed(slotId);
|
return _missed(_toProofId(slotId));
|
||||||
}
|
}
|
||||||
|
|
||||||
function isProofRequired(bytes32 slotId) public view returns (bool) {
|
function isProofRequired(SlotId slotId) public view returns (bool) {
|
||||||
if(!_slotAcceptsProofs(slotId)) {
|
if(!_slotAcceptsProofs(slotId)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return _isProofRequired(slotId);
|
return _isProofRequired(_toProofId(slotId));
|
||||||
}
|
}
|
||||||
|
|
||||||
function willProofBeRequired(bytes32 slotId) public view returns (bool) {
|
function willProofBeRequired(SlotId slotId) public view returns (bool) {
|
||||||
if(!_slotAcceptsProofs(slotId)) {
|
if(!_slotAcceptsProofs(slotId)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return _willProofBeRequired(slotId);
|
return _willProofBeRequired(_toProofId(slotId));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getChallenge(bytes32 slotId) public view returns (bytes32) {
|
function getChallenge(SlotId slotId) public view returns (bytes32) {
|
||||||
if(!_slotAcceptsProofs(slotId)) {
|
if(!_slotAcceptsProofs(slotId)) {
|
||||||
return bytes32(0);
|
return bytes32(0);
|
||||||
}
|
}
|
||||||
return _getChallenge(slotId);
|
return _getChallenge(_toProofId(slotId));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPointer(bytes32 slotId) public view returns (uint8) {
|
function getPointer(SlotId slotId) public view returns (uint8) {
|
||||||
return _getPointer(slotId);
|
return _getPointer(_toProofId(slotId));
|
||||||
}
|
}
|
||||||
|
|
||||||
function submitProof(bytes32 slotId, bytes calldata proof) public {
|
function submitProof(SlotId slotId, bytes calldata proof) public {
|
||||||
_submitProof(slotId, proof);
|
_submitProof(_toProofId(slotId), proof);
|
||||||
}
|
}
|
||||||
|
|
||||||
function markProofAsMissing(bytes32 slotId, uint256 period)
|
function markProofAsMissing(SlotId slotId, uint256 period)
|
||||||
public
|
public
|
||||||
slotMustAcceptProofs(slotId)
|
slotMustAcceptProofs(slotId)
|
||||||
{
|
{
|
||||||
_markProofAsMissing(slotId, period);
|
ProofId proofId = _toProofId(slotId);
|
||||||
|
_markProofAsMissing(proofId, period);
|
||||||
address host = _host(slotId);
|
address host = _host(slotId);
|
||||||
if (_missed(slotId) % slashMisses == 0) {
|
if (_missed(_toProofId(slotId)) % slashMisses == 0) {
|
||||||
_slash(host, slashPercentage);
|
_slash(host, slashPercentage);
|
||||||
|
|
||||||
if (balanceOf(host) < minCollateralThreshold) {
|
if (balanceOf(host) < minCollateralThreshold) {
|
||||||
|
@ -5,15 +5,15 @@ import "./AccountLocks.sol";
|
|||||||
|
|
||||||
// exposes internal functions for testing
|
// exposes internal functions for testing
|
||||||
contract TestAccountLocks is AccountLocks {
|
contract TestAccountLocks is AccountLocks {
|
||||||
function createLock(bytes32 id, uint256 expiry) public {
|
function createLock(LockId id, uint256 expiry) public {
|
||||||
_createLock(id, expiry);
|
_createLock(id, expiry);
|
||||||
}
|
}
|
||||||
|
|
||||||
function lock(address account, bytes32 id) public {
|
function lock(address account, LockId id) public {
|
||||||
_lock(account, id);
|
_lock(account, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function unlock(bytes32 id) public {
|
function unlock(LockId id) public {
|
||||||
_unlock(id);
|
_unlock(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ contract TestAccountLocks is AccountLocks {
|
|||||||
_unlockAccount();
|
_unlockAccount();
|
||||||
}
|
}
|
||||||
|
|
||||||
function extendLockExpiryTo(bytes32 lockId, uint256 expiry) public {
|
function extendLockExpiryTo(LockId lockId, uint256 expiry) public {
|
||||||
_extendLockExpiryTo(lockId, expiry);
|
_extendLockExpiryTo(lockId, expiry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,15 +12,15 @@ contract TestCollateral is Collateral {
|
|||||||
_slash(account, percentage);
|
_slash(account, percentage);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createLock(bytes32 id, uint256 expiry) public {
|
function createLock(LockId id, uint256 expiry) public {
|
||||||
_createLock(id, expiry);
|
_createLock(id, expiry);
|
||||||
}
|
}
|
||||||
|
|
||||||
function lock(address account, bytes32 id) public {
|
function lock(address account, LockId id) public {
|
||||||
_lock(account, id);
|
_lock(account, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function unlock(bytes32 id) public {
|
function unlock(LockId id) public {
|
||||||
_unlock(id);
|
_unlock(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,23 +18,23 @@ contract TestMarketplace is Marketplace {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function isCancelled(bytes32 requestId) public view returns (bool) {
|
function isCancelled(RequestId requestId) public view returns (bool) {
|
||||||
return _isCancelled(requestId);
|
return _isCancelled(requestId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSlotCancelled(bytes32 slotId) public view returns (bool) {
|
function isSlotCancelled(SlotId slotId) public view returns (bool) {
|
||||||
return _isSlotCancelled(slotId);
|
return _isSlotCancelled(slotId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function freeSlot(bytes32 slotId) public {
|
function freeSlot(SlotId slotId) public {
|
||||||
_freeSlot(slotId);
|
_freeSlot(slotId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function slot(bytes32 slotId) public view returns (Slot memory) {
|
function slot(SlotId slotId) public view returns (Slot memory) {
|
||||||
return _slot(slotId);
|
return _slot(slotId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAcceptsProofs(bytes32 slotId)
|
function testAcceptsProofs(SlotId slotId)
|
||||||
public
|
public
|
||||||
view
|
view
|
||||||
slotMustAcceptProofs(slotId)
|
slotMustAcceptProofs(slotId)
|
||||||
|
@ -24,47 +24,47 @@ contract TestProofs is Proofs {
|
|||||||
return _timeout();
|
return _timeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
function end(bytes32 id) public view returns (uint256) {
|
function end(ProofId id) public view returns (uint256) {
|
||||||
return _end(id);
|
return _end(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function missed(bytes32 id) public view returns (uint256) {
|
function missed(ProofId id) public view returns (uint256) {
|
||||||
return _missed(id);
|
return _missed(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function expectProofs(
|
function expectProofs(
|
||||||
bytes32 id,
|
ProofId id,
|
||||||
bytes32 endId,
|
EndId endId,
|
||||||
uint256 _probability
|
uint256 _probability
|
||||||
) public {
|
) public {
|
||||||
_expectProofs(id, endId, _probability);
|
_expectProofs(id, endId, _probability);
|
||||||
}
|
}
|
||||||
|
|
||||||
function unexpectProofs(bytes32 id) public {
|
function unexpectProofs(ProofId id) public {
|
||||||
_unexpectProofs(id);
|
_unexpectProofs(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isProofRequired(bytes32 id) public view returns (bool) {
|
function isProofRequired(ProofId id) public view returns (bool) {
|
||||||
return _isProofRequired(id);
|
return _isProofRequired(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function willProofBeRequired(bytes32 id) public view returns (bool) {
|
function willProofBeRequired(ProofId id) public view returns (bool) {
|
||||||
return _willProofBeRequired(id);
|
return _willProofBeRequired(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getChallenge(bytes32 id) public view returns (bytes32) {
|
function getChallenge(ProofId id) public view returns (bytes32) {
|
||||||
return _getChallenge(id);
|
return _getChallenge(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPointer(bytes32 id) public view returns (uint8) {
|
function getPointer(ProofId id) public view returns (uint8) {
|
||||||
return _getPointer(id);
|
return _getPointer(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function submitProof(bytes32 id, bytes calldata proof) public {
|
function submitProof(ProofId id, bytes calldata proof) public {
|
||||||
_submitProof(id, proof);
|
_submitProof(id, proof);
|
||||||
}
|
}
|
||||||
|
|
||||||
function markProofAsMissing(bytes32 id, uint256 _period) public {
|
function markProofAsMissing(ProofId id, uint256 _period) public {
|
||||||
_markProofAsMissing(id, _period);
|
_markProofAsMissing(id, _period);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ require("hardhat-deploy-ethers")
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
solidity: {
|
solidity: {
|
||||||
version: "0.8.4",
|
version: "0.8.8",
|
||||||
settings: {
|
settings: {
|
||||||
optimizer: {
|
optimizer: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user