[style] enforce `_` prefix for private names
Co-authored-by: Eric Mastro <eric.mastro@gmail.com>
This commit is contained in:
parent
b81e6e6532
commit
be38c54622
|
@ -3,6 +3,7 @@
|
|||
"rules": {
|
||||
"compiler-version": ["warn", "^0.8.0"],
|
||||
"func-visibility": ["warn", {"ignoreConstructors": true}],
|
||||
"private-vars-leading-underscore": ["warn", { "strict": true }],
|
||||
"not-rely-on-time": "off"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,26 +5,26 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|||
|
||||
abstract contract Collateral {
|
||||
IERC20 public immutable token;
|
||||
CollateralFunds private funds;
|
||||
CollateralFunds private _funds;
|
||||
|
||||
mapping(address => uint256) private balances;
|
||||
mapping(address => uint256) private _balances;
|
||||
|
||||
constructor(IERC20 _token) collateralInvariant {
|
||||
token = _token;
|
||||
constructor(IERC20 token_) collateralInvariant {
|
||||
token = token_;
|
||||
}
|
||||
|
||||
function balanceOf(address account) public view returns (uint256) {
|
||||
return balances[account];
|
||||
return _balances[account];
|
||||
}
|
||||
|
||||
function _add(address account, uint256 amount) private {
|
||||
balances[account] += amount;
|
||||
funds.balance += amount;
|
||||
_balances[account] += amount;
|
||||
_funds.balance += amount;
|
||||
}
|
||||
|
||||
function _subtract(address account, uint256 amount) private {
|
||||
balances[account] -= amount;
|
||||
funds.balance -= amount;
|
||||
_balances[account] -= amount;
|
||||
_funds.balance -= amount;
|
||||
}
|
||||
|
||||
function _transferFrom(address sender, uint256 amount) internal {
|
||||
|
@ -34,7 +34,7 @@ abstract contract Collateral {
|
|||
|
||||
function deposit(uint256 amount) public collateralInvariant {
|
||||
_transferFrom(msg.sender, amount);
|
||||
funds.deposited += amount;
|
||||
_funds.deposited += amount;
|
||||
_add(msg.sender, amount);
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ abstract contract Collateral {
|
|||
function withdraw() public collateralInvariant {
|
||||
require(_isWithdrawAllowed(), "Account locked");
|
||||
uint256 amount = balanceOf(msg.sender);
|
||||
funds.withdrawn += amount;
|
||||
_funds.withdrawn += amount;
|
||||
_subtract(msg.sender, amount);
|
||||
assert(token.transfer(msg.sender, amount));
|
||||
}
|
||||
|
@ -53,17 +53,19 @@ abstract contract Collateral {
|
|||
uint256 percentage
|
||||
) internal collateralInvariant {
|
||||
uint256 amount = (balanceOf(account) * percentage) / 100;
|
||||
funds.slashed += amount;
|
||||
_funds.slashed += amount;
|
||||
_subtract(account, amount);
|
||||
}
|
||||
|
||||
modifier collateralInvariant() {
|
||||
CollateralFunds memory oldFunds = funds;
|
||||
CollateralFunds memory oldFunds = _funds;
|
||||
_;
|
||||
assert(funds.deposited >= oldFunds.deposited);
|
||||
assert(funds.withdrawn >= oldFunds.withdrawn);
|
||||
assert(funds.slashed >= oldFunds.slashed);
|
||||
assert(funds.deposited == funds.balance + funds.withdrawn + funds.slashed);
|
||||
assert(_funds.deposited >= oldFunds.deposited);
|
||||
assert(_funds.withdrawn >= oldFunds.withdrawn);
|
||||
assert(_funds.slashed >= oldFunds.slashed);
|
||||
assert(
|
||||
_funds.deposited == _funds.balance + _funds.withdrawn + _funds.slashed
|
||||
);
|
||||
}
|
||||
|
||||
struct CollateralFunds {
|
||||
|
|
|
@ -16,10 +16,10 @@ contract Marketplace is Collateral, Proofs, StateRetrieval {
|
|||
|
||||
MarketplaceConfig public config;
|
||||
|
||||
MarketplaceFunds private funds;
|
||||
mapping(RequestId => Request) private requests;
|
||||
mapping(RequestId => RequestContext) private requestContexts;
|
||||
mapping(SlotId => Slot) private slots;
|
||||
MarketplaceFunds private _funds;
|
||||
mapping(RequestId => Request) private _requests;
|
||||
mapping(RequestId => RequestContext) private _requestContexts;
|
||||
mapping(SlotId => Slot) private _slots;
|
||||
|
||||
struct RequestContext {
|
||||
RequestState state;
|
||||
|
@ -51,16 +51,16 @@ contract Marketplace is Collateral, Proofs, StateRetrieval {
|
|||
require(request.client == msg.sender, "Invalid client address");
|
||||
|
||||
RequestId id = request.id();
|
||||
require(requests[id].client == address(0), "Request already exists");
|
||||
require(_requests[id].client == address(0), "Request already exists");
|
||||
|
||||
requests[id] = request;
|
||||
requestContexts[id].endsAt = block.timestamp + request.ask.duration;
|
||||
_requests[id] = request;
|
||||
_requestContexts[id].endsAt = block.timestamp + request.ask.duration;
|
||||
|
||||
_addToMyRequests(request.client, id);
|
||||
|
||||
uint256 amount = request.price();
|
||||
funds.received += amount;
|
||||
funds.balance += amount;
|
||||
_funds.received += amount;
|
||||
_funds.balance += amount;
|
||||
_transferFrom(msg.sender, amount);
|
||||
|
||||
emit StorageRequested(id, request.ask);
|
||||
|
@ -71,11 +71,11 @@ contract Marketplace is Collateral, Proofs, StateRetrieval {
|
|||
uint256 slotIndex,
|
||||
bytes calldata proof
|
||||
) public requestIsKnown(requestId) {
|
||||
Request storage request = requests[requestId];
|
||||
Request storage request = _requests[requestId];
|
||||
require(slotIndex < request.ask.slots, "Invalid slot");
|
||||
|
||||
SlotId slotId = Requests.slotId(requestId, slotIndex);
|
||||
Slot storage slot = slots[slotId];
|
||||
Slot storage slot = _slots[slotId];
|
||||
slot.requestId = requestId;
|
||||
|
||||
require(slotState(slotId) == SlotState.Free, "Slot is not free");
|
||||
|
@ -90,7 +90,7 @@ contract Marketplace is Collateral, Proofs, StateRetrieval {
|
|||
|
||||
slot.host = msg.sender;
|
||||
slot.state = SlotState.Filled;
|
||||
RequestContext storage context = requestContexts[requestId];
|
||||
RequestContext storage context = _requestContexts[requestId];
|
||||
context.slotsFilled += 1;
|
||||
|
||||
_addToMySlots(slot.host, slotId);
|
||||
|
@ -104,7 +104,7 @@ contract Marketplace is Collateral, Proofs, StateRetrieval {
|
|||
}
|
||||
|
||||
function freeSlot(SlotId slotId) public slotIsNotFree(slotId) {
|
||||
Slot storage slot = slots[slotId];
|
||||
Slot storage slot = _slots[slotId];
|
||||
require(slot.host == msg.sender, "Slot filled by other host");
|
||||
SlotState state = slotState(slotId);
|
||||
require(state != SlotState.Paid, "Already paid");
|
||||
|
@ -134,9 +134,9 @@ contract Marketplace is Collateral, Proofs, StateRetrieval {
|
|||
}
|
||||
|
||||
function _forciblyFreeSlot(SlotId slotId) internal marketplaceInvariant {
|
||||
Slot storage slot = slots[slotId];
|
||||
Slot storage slot = _slots[slotId];
|
||||
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
|
||||
// missing reward
|
||||
|
@ -151,7 +151,7 @@ contract Marketplace is Collateral, Proofs, StateRetrieval {
|
|||
context.slotsFilled -= 1;
|
||||
emit SlotFreed(requestId, slotId);
|
||||
|
||||
Request storage request = requests[requestId];
|
||||
Request storage request = _requests[requestId];
|
||||
uint256 slotsLost = request.ask.slots - context.slotsFilled;
|
||||
if (
|
||||
slotsLost > request.ask.maxSlotLoss &&
|
||||
|
@ -171,17 +171,17 @@ contract Marketplace is Collateral, Proofs, StateRetrieval {
|
|||
RequestId requestId,
|
||||
SlotId slotId
|
||||
) private requestIsKnown(requestId) marketplaceInvariant {
|
||||
RequestContext storage context = requestContexts[requestId];
|
||||
Request storage request = requests[requestId];
|
||||
RequestContext storage context = _requestContexts[requestId];
|
||||
Request storage request = _requests[requestId];
|
||||
context.state = RequestState.Finished;
|
||||
_removeFromMyRequests(request.client, requestId);
|
||||
Slot storage slot = slots[slotId];
|
||||
Slot storage slot = _slots[slotId];
|
||||
|
||||
_removeFromMySlots(slot.host, slotId);
|
||||
|
||||
uint256 amount = requests[requestId].pricePerSlot();
|
||||
funds.sent += amount;
|
||||
funds.balance -= amount;
|
||||
uint256 amount = _requests[requestId].pricePerSlot();
|
||||
_funds.sent += amount;
|
||||
_funds.balance -= amount;
|
||||
slot.state = SlotState.Paid;
|
||||
require(token.transfer(slot.host, amount), "Payment failed");
|
||||
}
|
||||
|
@ -190,10 +190,10 @@ contract Marketplace is Collateral, Proofs, StateRetrieval {
|
|||
/// @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
|
||||
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(request.client == msg.sender, "Invalid client address");
|
||||
RequestContext storage context = requestContexts[requestId];
|
||||
RequestContext storage context = _requestContexts[requestId];
|
||||
require(context.state == RequestState.New, "Invalid state");
|
||||
|
||||
// Update request state to Cancelled. Handle in the withdraw transaction
|
||||
|
@ -207,33 +207,33 @@ contract Marketplace is Collateral, Proofs, StateRetrieval {
|
|||
// fill a slot. The amount that we paid to hosts will then have to be
|
||||
// deducted from the price.
|
||||
uint256 amount = request.price();
|
||||
funds.sent += amount;
|
||||
funds.balance -= amount;
|
||||
_funds.sent += amount;
|
||||
_funds.balance -= amount;
|
||||
require(token.transfer(msg.sender, amount), "Withdraw failed");
|
||||
}
|
||||
|
||||
function getHost(SlotId slotId) public view returns (address) {
|
||||
return slots[slotId].host;
|
||||
return _slots[slotId].host;
|
||||
}
|
||||
|
||||
modifier requestIsKnown(RequestId requestId) {
|
||||
require(requests[requestId].client != address(0), "Unknown request");
|
||||
require(_requests[requestId].client != address(0), "Unknown request");
|
||||
_;
|
||||
}
|
||||
|
||||
function getRequest(
|
||||
RequestId requestId
|
||||
) public view requestIsKnown(requestId) returns (Request memory) {
|
||||
return requests[requestId];
|
||||
return _requests[requestId];
|
||||
}
|
||||
|
||||
modifier slotIsNotFree(SlotId slotId) {
|
||||
require(slots[slotId].state != SlotState.Free, "Slot is free");
|
||||
require(_slots[slotId].state != SlotState.Free, "Slot is free");
|
||||
_;
|
||||
}
|
||||
|
||||
function requestEnd(RequestId requestId) public view returns (uint256) {
|
||||
uint256 end = requestContexts[requestId].endsAt;
|
||||
uint256 end = _requestContexts[requestId].endsAt;
|
||||
RequestState state = requestState(requestId);
|
||||
if (state == RequestState.New || state == RequestState.Started) {
|
||||
return end;
|
||||
|
@ -245,10 +245,10 @@ contract Marketplace is Collateral, Proofs, StateRetrieval {
|
|||
function requestState(
|
||||
RequestId requestId
|
||||
) public view requestIsKnown(requestId) returns (RequestState) {
|
||||
RequestContext storage context = requestContexts[requestId];
|
||||
RequestContext storage context = _requestContexts[requestId];
|
||||
if (
|
||||
context.state == RequestState.New &&
|
||||
block.timestamp > requests[requestId].expiry
|
||||
block.timestamp > _requests[requestId].expiry
|
||||
) {
|
||||
return RequestState.Cancelled;
|
||||
} else if (
|
||||
|
@ -261,7 +261,7 @@ contract Marketplace is Collateral, Proofs, StateRetrieval {
|
|||
}
|
||||
|
||||
function slotState(SlotId slotId) public view override returns (SlotState) {
|
||||
Slot storage slot = slots[slotId];
|
||||
Slot storage slot = _slots[slotId];
|
||||
if (RequestId.unwrap(slot.requestId) == 0) {
|
||||
return SlotState.Free;
|
||||
}
|
||||
|
@ -293,11 +293,11 @@ contract Marketplace is Collateral, Proofs, StateRetrieval {
|
|||
event RequestCancelled(RequestId indexed requestId);
|
||||
|
||||
modifier marketplaceInvariant() {
|
||||
MarketplaceFunds memory oldFunds = funds;
|
||||
MarketplaceFunds memory oldFunds = _funds;
|
||||
_;
|
||||
assert(funds.received >= oldFunds.received);
|
||||
assert(funds.sent >= oldFunds.sent);
|
||||
assert(funds.received == funds.balance + funds.sent);
|
||||
assert(_funds.received >= oldFunds.received);
|
||||
assert(_funds.sent >= oldFunds.sent);
|
||||
assert(_funds.received == _funds.balance + _funds.sent);
|
||||
}
|
||||
|
||||
struct MarketplaceFunds {
|
||||
|
|
|
@ -4,14 +4,14 @@ pragma solidity ^0.8.8;
|
|||
contract Periods {
|
||||
type Period is uint256;
|
||||
|
||||
uint256 internal immutable secondsPerPeriod;
|
||||
uint256 internal immutable _secondsPerPeriod;
|
||||
|
||||
constructor(uint256 _secondsPerPeriod) {
|
||||
secondsPerPeriod = _secondsPerPeriod;
|
||||
constructor(uint256 secondsPerPeriod) {
|
||||
_secondsPerPeriod = secondsPerPeriod;
|
||||
}
|
||||
|
||||
function _periodOf(uint256 timestamp) internal view returns (Period) {
|
||||
return Period.wrap(timestamp / secondsPerPeriod);
|
||||
return Period.wrap(timestamp / _secondsPerPeriod);
|
||||
}
|
||||
|
||||
function _blockPeriod() internal view returns (Period) {
|
||||
|
@ -23,7 +23,7 @@ contract Periods {
|
|||
}
|
||||
|
||||
function _periodStart(Period period) internal view returns (uint256) {
|
||||
return Period.unwrap(period) * secondsPerPeriod;
|
||||
return Period.unwrap(period) * _secondsPerPeriod;
|
||||
}
|
||||
|
||||
function _periodEnd(Period period) internal view returns (uint256) {
|
||||
|
|
|
@ -6,28 +6,28 @@ import "./Requests.sol";
|
|||
import "./Periods.sol";
|
||||
|
||||
abstract contract Proofs is Periods {
|
||||
ProofConfig private config;
|
||||
ProofConfig private _config;
|
||||
|
||||
constructor(ProofConfig memory _config) Periods(_config.period) {
|
||||
constructor(ProofConfig memory config) Periods(config.period) {
|
||||
require(block.number > 256, "Insufficient block height");
|
||||
config = _config;
|
||||
_config = config;
|
||||
}
|
||||
|
||||
mapping(SlotId => uint256) private slotStarts;
|
||||
mapping(SlotId => uint256) private probabilities;
|
||||
mapping(SlotId => uint256) private missed;
|
||||
mapping(SlotId => mapping(Period => bool)) private received;
|
||||
mapping(SlotId => mapping(Period => bool)) private missing;
|
||||
mapping(SlotId => uint256) private _slotStarts;
|
||||
mapping(SlotId => uint256) private _probabilities;
|
||||
mapping(SlotId => uint256) private _missed;
|
||||
mapping(SlotId => mapping(Period => bool)) private _received;
|
||||
mapping(SlotId => mapping(Period => bool)) private _missing;
|
||||
|
||||
function slotState(SlotId id) public view virtual returns (SlotState);
|
||||
|
||||
function missingProofs(SlotId slotId) public view returns (uint256) {
|
||||
return missed[slotId];
|
||||
return _missed[slotId];
|
||||
}
|
||||
|
||||
function _startRequiringProofs(SlotId id, uint256 probability) internal {
|
||||
slotStarts[id] = block.timestamp;
|
||||
probabilities[id] = probability;
|
||||
_slotStarts[id] = block.timestamp;
|
||||
_probabilities[id] = probability;
|
||||
}
|
||||
|
||||
function _getPointer(SlotId id, Period period) internal view returns (uint8) {
|
||||
|
@ -64,13 +64,13 @@ abstract contract Proofs is Periods {
|
|||
Period period
|
||||
) internal view returns (bool isRequired, uint8 pointer) {
|
||||
SlotState state = slotState(id);
|
||||
Period start = _periodOf(slotStarts[id]);
|
||||
Period start = _periodOf(_slotStarts[id]);
|
||||
if (state != SlotState.Filled || !_isAfter(period, start)) {
|
||||
return (false, 0);
|
||||
}
|
||||
pointer = _getPointer(id, period);
|
||||
bytes32 challenge = _getChallenge(pointer);
|
||||
uint256 probability = (probabilities[id] * (256 - config.downtime)) / 256;
|
||||
uint256 probability = (_probabilities[id] * (256 - _config.downtime)) / 256;
|
||||
isRequired = uint256(challenge) % probability == 0;
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ abstract contract Proofs is Periods {
|
|||
bool isRequired;
|
||||
uint8 pointer;
|
||||
(isRequired, pointer) = _getProofRequirement(id, period);
|
||||
return isRequired && pointer >= config.downtime;
|
||||
return isRequired && pointer >= _config.downtime;
|
||||
}
|
||||
|
||||
function isProofRequired(SlotId id) public view returns (bool) {
|
||||
|
@ -92,25 +92,25 @@ abstract contract Proofs is Periods {
|
|||
bool isRequired;
|
||||
uint8 pointer;
|
||||
(isRequired, pointer) = _getProofRequirement(id, _blockPeriod());
|
||||
return isRequired && pointer < config.downtime;
|
||||
return isRequired && pointer < _config.downtime;
|
||||
}
|
||||
|
||||
function submitProof(SlotId id, bytes calldata proof) public {
|
||||
require(proof.length > 0, "Invalid proof"); // TODO: replace by actual check
|
||||
require(!received[id][_blockPeriod()], "Proof already submitted");
|
||||
received[id][_blockPeriod()] = true;
|
||||
require(!_received[id][_blockPeriod()], "Proof already submitted");
|
||||
_received[id][_blockPeriod()] = true;
|
||||
emit ProofSubmitted(id, proof);
|
||||
}
|
||||
|
||||
function _markProofAsMissing(SlotId id, Period missedPeriod) internal {
|
||||
uint256 end = _periodEnd(missedPeriod);
|
||||
require(end < block.timestamp, "Period has not ended yet");
|
||||
require(block.timestamp < end + config.timeout, "Validation timed out");
|
||||
require(!received[id][missedPeriod], "Proof was submitted, not missing");
|
||||
require(block.timestamp < end + _config.timeout, "Validation timed out");
|
||||
require(!_received[id][missedPeriod], "Proof was submitted, not missing");
|
||||
require(_isProofRequired(id, missedPeriod), "Proof was not required");
|
||||
require(!missing[id][missedPeriod], "Proof already marked as missing");
|
||||
missing[id][missedPeriod] = true;
|
||||
missed[id] += 1;
|
||||
require(!_missing[id][missedPeriod], "Proof already marked as missing");
|
||||
_missing[id][missedPeriod] = true;
|
||||
_missed[id] += 1;
|
||||
}
|
||||
|
||||
event ProofSubmitted(SlotId id, bytes proof);
|
||||
|
|
|
@ -8,34 +8,34 @@ contract StateRetrieval {
|
|||
using EnumerableSet for EnumerableSet.Bytes32Set;
|
||||
using Requests for bytes32[];
|
||||
|
||||
mapping(address => EnumerableSet.Bytes32Set) private requestsPerClient;
|
||||
mapping(address => EnumerableSet.Bytes32Set) private slotsPerHost;
|
||||
mapping(address => EnumerableSet.Bytes32Set) private _requestsPerClient;
|
||||
mapping(address => EnumerableSet.Bytes32Set) private _slotsPerHost;
|
||||
|
||||
function myRequests() public view returns (RequestId[] memory) {
|
||||
return requestsPerClient[msg.sender].values().toRequestIds();
|
||||
return _requestsPerClient[msg.sender].values().toRequestIds();
|
||||
}
|
||||
|
||||
function mySlots() public view returns (SlotId[] memory) {
|
||||
return slotsPerHost[msg.sender].values().toSlotIds();
|
||||
return _slotsPerHost[msg.sender].values().toSlotIds();
|
||||
}
|
||||
|
||||
function _hasSlots(address host) internal view returns (bool) {
|
||||
return slotsPerHost[host].length() > 0;
|
||||
return _slotsPerHost[host].length() > 0;
|
||||
}
|
||||
|
||||
function _addToMyRequests(address client, RequestId requestId) internal {
|
||||
requestsPerClient[client].add(RequestId.unwrap(requestId));
|
||||
_requestsPerClient[client].add(RequestId.unwrap(requestId));
|
||||
}
|
||||
|
||||
function _addToMySlots(address host, SlotId slotId) internal {
|
||||
slotsPerHost[host].add(SlotId.unwrap(slotId));
|
||||
_slotsPerHost[host].add(SlotId.unwrap(slotId));
|
||||
}
|
||||
|
||||
function _removeFromMyRequests(address client, RequestId requestId) internal {
|
||||
requestsPerClient[client].remove(RequestId.unwrap(requestId));
|
||||
_requestsPerClient[client].remove(RequestId.unwrap(requestId));
|
||||
}
|
||||
|
||||
function _removeFromMySlots(address host, SlotId slotId) internal {
|
||||
slotsPerHost[host].remove(SlotId.unwrap(slotId));
|
||||
_slotsPerHost[host].remove(SlotId.unwrap(slotId));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,24 +5,24 @@ import "./Proofs.sol";
|
|||
|
||||
// exposes internal functions of Proofs for testing
|
||||
contract TestProofs is Proofs {
|
||||
mapping(SlotId => SlotState) private states;
|
||||
mapping(SlotId => SlotState) private _states;
|
||||
|
||||
// solhint-disable-next-line no-empty-blocks
|
||||
constructor(ProofConfig memory config) Proofs(config) {}
|
||||
|
||||
function slotState(SlotId slotId) public view override returns (SlotState) {
|
||||
return states[slotId];
|
||||
return _states[slotId];
|
||||
}
|
||||
|
||||
function startRequiringProofs(SlotId slot, uint256 _probability) public {
|
||||
_startRequiringProofs(slot, _probability);
|
||||
function startRequiringProofs(SlotId slot, uint256 probability) public {
|
||||
_startRequiringProofs(slot, probability);
|
||||
}
|
||||
|
||||
function markProofAsMissing(SlotId id, Period _period) public {
|
||||
_markProofAsMissing(id, _period);
|
||||
function markProofAsMissing(SlotId id, Period period) public {
|
||||
_markProofAsMissing(id, period);
|
||||
}
|
||||
|
||||
function setSlotState(SlotId id, SlotState state) public {
|
||||
states[id] = state;
|
||||
_states[id] = state;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue