diff --git a/.solhint.json b/.solhint.json index fb4f173..18fb6b6 100644 --- a/.solhint.json +++ b/.solhint.json @@ -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" } } diff --git a/contracts/Collateral.sol b/contracts/Collateral.sol index 4400ba2..301e97f 100644 --- a/contracts/Collateral.sol +++ b/contracts/Collateral.sol @@ -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 { diff --git a/contracts/Marketplace.sol b/contracts/Marketplace.sol index f957b59..4841b4a 100644 --- a/contracts/Marketplace.sol +++ b/contracts/Marketplace.sol @@ -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 { diff --git a/contracts/Periods.sol b/contracts/Periods.sol index e380e8f..796b61a 100644 --- a/contracts/Periods.sol +++ b/contracts/Periods.sol @@ -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) { diff --git a/contracts/Proofs.sol b/contracts/Proofs.sol index b13ef41..aa9c3b2 100644 --- a/contracts/Proofs.sol +++ b/contracts/Proofs.sol @@ -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); diff --git a/contracts/StateRetrieval.sol b/contracts/StateRetrieval.sol index 34b4ab4..3293932 100644 --- a/contracts/StateRetrieval.sol +++ b/contracts/StateRetrieval.sol @@ -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)); } } diff --git a/contracts/TestProofs.sol b/contracts/TestProofs.sol index 3d2645a..e765eb2 100644 --- a/contracts/TestProofs.sol +++ b/contracts/TestProofs.sol @@ -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; } }