Platform: Code4rena
Start Date: 01/08/2022
Pot Size: $50,000 USDC
Total HM: 26
Participants: 133
Period: 5 days
Judge: Jack the Pug
Total Solo HM: 6
Id: 151
League: ETH
Rank: 114/133
Findings: 1
Award: $22.03
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: c3phas
Also found by: 0x040, 0x1f8b, 0xA5DF, 0xNazgul, 0xSmartContract, 0xSolus, 0xc0ffEE, 0xkatana, 0xsam, 8olidity, Aymen0909, Bnke0x0, CertoraInc, Chinmay, Chom, CodingNameKiki, Deivitto, Dravee, ElKu, Extropy, Fitraldys, Funen, GalloDaSballo, Guardian, IllIllI, JC, Lambda, MEP, Metatron, MiloTruck, Noah3o6, NoamYakov, PaludoX0, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, SooYa, TomJ, Tomio, Waze, _Adam, __141345__, a12jmx, ajtra, ak1, apostle0x01, asutorufos, ballx, benbaessler, bharg4v, bobirichman, brgltd, cryptonue, defsec, delfin454000, dharma09, djxploit, durianSausage, eierina, erictee, fatherOfBlocks, gerdusx, gogo, hake, hyh, ignacio, jag, kaden, kyteg, lucacez, mics, minhquanym, oyc_109, pfapostol, rbserver, ret2basic, robee, rokinot, sach1r0, saian, samruna, scaraven, sikorico, simon135, supernova, teddav, tofunmi, zeesaw
22.0296 USDC - $22.03
diff --git a/contracts/Community.sol b/contracts/Community.sol index 1585670..9b43119 100644 --- a/contracts/Community.sol +++ b/contracts/Community.sol @@ -136,18 +136,22 @@ contract Community is // Revert if currency is not supported by HomeFi homeFi.validCurrency(_currency); + //Use local variable to track communityCount + uint256 _communityCount; // Increment community counter - communityCount++; + unchecked { + _communityCount = ++communityCount; + } // Store community details - CommunityStruct storage _community = _communities[communityCount]; + CommunityStruct storage _community = _communities[_communityCount]; _community.owner = _sender; _community.currency = IDebtToken(_currency); _community.memberCount = 1; _community.members[0] = _sender; _community.isMember[_sender] = true; - emit CommunityAdded(communityCount, _sender, _currency, _hash); + emit CommunityAdded(_communityCount, _sender, _currency, _hash); } /// @inheritdoc ICommunity @@ -195,7 +199,10 @@ contract Community is // Store updated community details uint256 _memberCount = _community.memberCount; - _community.memberCount = _memberCount + 1; + //memberCount is not expected to cross 2**256-1 limit + unchecked { + _community.memberCount = _memberCount + 1; + } _community.members[_memberCount] = _newMemberAddr; _community.isMember[_newMemberAddr] = true; @@ -263,7 +270,10 @@ contract Community is } // Store updated details - _community.publishNonce = ++_community.publishNonce; + // _publishNonce is same as _community.publishNonce + unchecked { + _community.publishNonce = ++_publishNonce; + } _communityProject.apr = _apr; _communityProject.publishFee = _publishFee; projectPublished[_project] = _communityID;
diff --git a/contracts/Disputes.sol b/contracts/Disputes.sol index afe58c6..095f844 100644 --- a/contracts/Disputes.sol +++ b/contracts/Disputes.sol @@ -109,7 +109,9 @@ contract Disputes is ); // Store dispute details - Dispute storage _dispute = disputes[disputeCount]; + // Create local variable to refer disputeCount + uint256 _disputeCount = disputeCount; + Dispute storage _dispute = disputes[_disputeCount]; _dispute.status = Status.Active; _dispute.project = _project; _dispute.taskID = _taskID; @@ -117,8 +119,12 @@ contract Disputes is _dispute.actionType = ActionType(_actionType); _dispute.actionData = _actionData; - // Increment dispute counter and emit event - emit DisputeRaised(disputeCount++, _reason); + // Increment disputeCount + unchecked { + ++disputeCount; + } + //emit event with local disputeCount + emit DisputeRaised(_disputeCount, _reason); } /// @inheritdoc IDisputes
diff --git a/contracts/HomeFi.sol b/contracts/HomeFi.sol index b148c81..1219eda 100644 --- a/contracts/HomeFi.sol +++ b/contracts/HomeFi.sol @@ -225,10 +225,12 @@ contract HomeFi is mintNFT(_sender, string(_hash)); // Update project related mappings - projects[projectCount] = _project; - projectTokenId[_project] = projectCount; + //Use local reference to projectCount + uint256 _projectCount = projectCount; + projects[_projectCount] = _project; + projectTokenId[_project] = _projectCount; - emit ProjectAdded(projectCount, _project, _sender, _currency, _hash); + emit ProjectAdded(_projectCount, _project, _sender, _currency, _hash); } /******************************************************************************* @@ -286,14 +288,18 @@ contract HomeFi is returns (uint256) { // Project count starts from 1 - projectCount += 1; + //Use local reference to projectCount + uint256 _projectCount; + unchecked { + _projectCount = ++projectCount; + } // Mints NFT and set token URI - _mint(_to, projectCount); - _setTokenURI(projectCount, _tokenURI); + _mint(_to, _projectCount); + _setTokenURI(_projectCount, _tokenURI); - emit NftCreated(projectCount, _to); - return projectCount; + emit NftCreated(_projectCount, _to); + return _projectCount; } /*******************************************************************************
diff --git a/contracts/HomeFiProxy.sol b/contracts/HomeFiProxy.sol index 0d47d76..103e21c 100644 --- a/contracts/HomeFiProxy.sol +++ b/contracts/HomeFiProxy.sol @@ -84,8 +84,11 @@ contract HomeFiProxy is OwnableUpgradeable { contractsActive[address(this)] = true; // Generate proxy for all implementation - for (uint256 i = 0; i < _length; i++) { + for (uint256 i; i < _length;) { _generateProxy(allContractNames[i], _implementations[i]); + unchecked { + ++i; + } } } @@ -133,8 +136,11 @@ contract HomeFiProxy is OwnableUpgradeable { require(_length == _contractAddresses.length, "Proxy::Lengths !match"); // Replace implementations - for (uint256 i = 0; i < _length; i++) { + for (uint256 i; i < _length;) { _replaceImplementation(_contractNames[i], _contractAddresses[i]); + unchecked { + ++i; + } } }
diff --git a/contracts/Project.sol b/contracts/Project.sol index 4a1dcf5..a316abc 100644 --- a/contracts/Project.sol +++ b/contracts/Project.sol @@ -141,7 +141,7 @@ contract Project is // Check signature for builder and contractor checkSignature(_data, _signature); - emit ContractorInvited(contractor); + emit ContractorInvited(_contractor); } /// @inheritdoc IProject @@ -176,7 +176,9 @@ contract Project is require(_nonce == hashChangeNonce, "Project::!Nonce"); // Increment to ensure a set of data and signature cannot be re-used. - hashChangeNonce += 1; + unchecked { + ++hashChangeNonce; + } emit HashUpdated(_hash); } @@ -245,15 +247,19 @@ contract Project is require(_length == _taskCosts.length, "Project::Lengths !match"); // Loop over all the new tasks. - for (uint256 i = 0; i < _length; i++) { + for (uint256 i; i < _length;) { // Increment local task counter. - _taskCount += 1; - + unchecked { + ++_taskCount; + } // Check task cost precision. Revert if too precise. checkPrecision(_taskCosts[i]); // Initialize task. tasks[_taskCount].initialize(_taskCosts[i]); + unchecked { + ++i; + } } // Update task counter equal to local task counter. @@ -287,7 +293,9 @@ contract Project is } // Increment to ensure a set of data and signature cannot be re-used. - hashChangeNonce += 1; + unchecked { + ++hashChangeNonce; + } emit TaskHashUpdated(_taskID, _taskHash); } @@ -308,8 +316,11 @@ contract Project is require(_length == _scList.length, "Project::Lengths !match"); // Invite subcontractor for each task. - for (uint256 i = 0; i < _length; i++) { + for (uint256 i; i < _length;) { _inviteSC(_taskList[i], _scList[i], false); + unchecked { + ++i; + } } emit MultipleSCInvited(_taskList, _scList); @@ -319,8 +330,11 @@ contract Project is function acceptInviteSC(uint256[] calldata _taskList) external override { // Accept invitation for each task in taskList. uint256 _length = _taskList.length; - for (uint256 i = 0; i < _length; i++) { + for (uint256 i; i < _length;) { tasks[_taskList[i]].acceptInvitation(_msgSender()); + unchecked { + ++i; + } } emit SCConfirmed(_taskList); @@ -365,8 +379,11 @@ contract Project is if (_tokenAddress == address(currency)) { // Iterate for each task and check if it is complete. uint256 _length = taskCount; - for (uint256 _taskID = 1; _taskID <= _length; _taskID++) { + for (uint256 _taskID = 1; _taskID <= _length;) { require(tasks[_taskID].getState() == 3, "Project::!Complete"); + unchecked { + ++_taskID; + } } } @@ -453,7 +470,10 @@ contract Project is // Reduce total allocation by old task cost. // As as needs to go though funding process again. - totalAllocated -= _taskCost; + // Cannot underflow since old task code is added earlier and subtracted now + unchecked { + totalAllocated -= _taskCost; + } // Add this task to _changeOrderedTask array. These tasks will be allocated first. _changeOrderedTask.push(_taskID); @@ -576,7 +596,9 @@ contract Project is uint256 _maxLoop = 50; // Difference of totalLent and totalAllocated is what can be used to allocate new tasks - uint256 _costToAllocate = totalLent - totalAllocated; + //create local variable to refer totalLent + uint256 _totalLent = totalLent; + uint256 _costToAllocate = _totalLent - totalAllocated; // Bool if max loop limit is exceeded bool _exceedLimit; @@ -587,9 +609,11 @@ contract Project is // Local instance of lastAllocatedTask. To save gas. uint256 j = lastAllocatedTask; + //Local instance of _changeOrderedTask.length + uint256 _len = _changeOrderedTask.length; // Initialize empty array in which allocated tasks will be added. uint256[] memory _tasksAllocated = new uint256[]( - taskCount - j + _changeOrderedTask.length - i + taskCount - j + _len - i ); // Number of times a loop has run. @@ -600,7 +624,7 @@ contract Project is // Any tasks added to _changeOrderedTask will be allocated first if (_changeOrderedTask.length > 0) { // Loop from lastAllocatedChangeOrderTask to _changeOrderedTask length (until _maxLoop) - for (; i < _changeOrderedTask.length; i++) { + for (; i < _len;) { // Local instance of task cost. To save gas. uint256 _taskCost = tasks[_changeOrderedTask[i]].cost; @@ -622,17 +646,22 @@ contract Project is _tasksAllocated[_loopCount] = _changeOrderedTask[i]; // Increment loop counter - _loopCount++; + unchecked { + ++_loopCount; + } } // If there are not enough funds to allocate this task then stop looping else { break; } + unchecked { + ++i; + } } // If all the change ordered tasks are allocated, then delete // the changeOrderedTask array and reset lastAllocatedChangeOrderTask. - if (i == _changeOrderedTask.length) { + if (i == _len) { lastAllocatedChangeOrderTask = 0; delete _changeOrderedTask; } @@ -647,7 +676,7 @@ contract Project is // If lastAllocatedTask is lesser than taskCount, that means there are un-allocated tasks if (j < taskCount) { // Loop from lastAllocatedTask + 1 to taskCount (until _maxLoop) - for (++j; j <= taskCount; j++) { + for (++j; j <= taskCount;) { // Local instance of task cost. To save gas. uint256 _taskCost = tasks[j].cost; @@ -669,12 +698,17 @@ contract Project is _tasksAllocated[_loopCount] = j; // Increment loop counter - _loopCount++; + unchecked { + ++_loopCount; + } } // If there are not enough funds to allocate this task then stop looping else { break; } + unchecked { + ++j; + } } // If all pending tasks are allocated store lastAllocatedTask equal to taskCount @@ -694,7 +728,9 @@ contract Project is if (_exceedLimit) emit IncompleteAllocation(); // Update totalAllocated with all allocations - totalAllocated = totalLent - _costToAllocate; + unchecked { + totalAllocated = _totalLent - _costToAllocate; + } } /******************************************************************************* @@ -707,8 +743,11 @@ contract Project is uint256 _length = taskCount; // Iterate over all tasks to sum their cost - for (uint256 _taskID = 1; _taskID <= _length; _taskID++) { + for (uint256 _taskID = 1; _taskID <= _length;) { _cost += tasks[_taskID].cost; + unchecked { + ++_taskID; + } } } @@ -769,7 +808,9 @@ contract Project is */ function autoWithdraw(uint256 _amount) internal { // Reduce amount from totalLent - totalLent -= _amount; + unchecked { + totalLent -= _amount; + } // Transfer amount to builder address currency.safeTransfer(builder, _amount);
diff --git a/contracts/libraries/Tasks.sol b/contracts/libraries/Tasks.sol index a7b4815..108517c 100644 --- a/contracts/libraries/Tasks.sol +++ b/contracts/libraries/Tasks.sol @@ -177,8 +177,13 @@ library Tasks { view returns (bool[3] memory _alerts) { - uint256 _length = _alerts.length; - for (uint256 i = 0; i < _length; i++) _alerts[i] = _self.alerts[i]; + for (uint256 i; i < 3;) { + _alerts[i] = _self.alerts[i]; + //we know i will reach 3 and cannot overflow + unchecked { + ++i; + } + } } /**
Gas saving report. Existing vs gas optimized.
@@ -6,21 +6,21 @@ ····························|··································|·············|·············|·············|···············|·············· | Contract · Method · Min · Max · Avg · # calls · usd (avg) │ ····························|··································|·············|·············|·············|···············|·············· -| Community · addMember · 95801 · 101386 · 100460 · 48 · - │ +| Community · addMember · 95755 · 101340 · 100414 · 48 · - │ ····························|··································|·············|·············|·············|···············|·············· | Community · approveHash · 63326 · 70137 · 68173 · 14 · - │ ····························|··································|·············|·············|·············|···············|·············· -| Community · createCommunity · 170003 · 187125 · 176852 · 20 · - │ +| Community · createCommunity · 169749 · 186871 · 176600 · 20 · - │ ····························|··································|·············|·············|·············|···············|·············· -| Community · escrow · 129972 · 130149 · 130078 · 16 · - │ +| Community · escrow · 129972 · 130149 · 130076 · 16 · - │ ····························|··································|·············|·············|·············|···············|·············· | Community · initialize · 74050 · 164197 · 119129 · 52 · - │ ····························|··································|·············|·············|·············|···············|·············· -| Community · lendToProject · 190993 · 328877 · 295225 · 40 · - │ +| Community · lendToProject · 190619 · 328101 · 294770 · 40 · - │ ····························|··································|·············|·············|·············|···············|·············· | Community · payPublishFee · 123376 · 123420 · 123398 · 4 · - │ ····························|··································|·············|·············|·············|···············|·············· -| Community · publishProject · 130014 · 177575 · 171428 · 26 · - │ +| Community · publishProject · 129722 · 177291 · 171145 · 26 · - │ ····························|··································|·············|·············|·············|···············|·············· | Community · reduceDebt · 83621 · 99729 · 94632 · 14 · - │ ····························|··································|·············|·············|·············|···············|·············· @@ -28,7 +28,7 @@ ····························|··································|·············|·············|·············|···············|·············· | Community · restrictToAdmin · 54365 · 54387 · 54376 · 4 · - │ ····························|··································|·············|·············|·············|···············|·············· -| Community · toggleLendingNeeded · 78622 · 95756 · 88133 · 18 · - │ +| Community · toggleLendingNeeded · 78400 · 95534 · 87911 · 18 · - │ ····························|··································|·············|·············|·············|···············|·············· | Community · unpublishProject · - · - · 64393 · 4 · - │ ····························|··································|·············|·············|·············|···············|·············· @@ -42,15 +42,15 @@ ····························|··································|·············|·············|·············|···············|·············· | Disputes · attachDocument · 69779 · 69889 · 69834 · 4 · - │ ····························|··································|·············|·············|·············|···············|·············· -| Disputes · raiseDispute · 217459 · 393526 · 278937 · 32 · - │ +| Disputes · raiseDispute · 217395 · 393422 · 278814 · 32 · - │ ····························|··································|·············|·············|·············|···············|·············· -| Disputes · resolveDispute · 61337 · 202445 · 115923 · 30 · - │ +| Disputes · resolveDispute · 61337 · 202315 · 115886 · 30 · - │ ····························|··································|·············|·············|·············|···············|·············· | ERC20PresetMinterPauser · pause · 73460 · 73482 · 73471 · 4 · - │ ····························|··································|·············|·············|·············|···············|·············· | ERC20PresetMinterPauser · unpause · 51617 · 51639 · 51628 · 4 · - │ ····························|··································|·············|·············|·············|···············|·············· -| HomeFi · createProject · 329136 · 383248 · 339543 · 86 · - │ +| HomeFi · createProject · 328550 · 382662 · 339148 · 86 · - │ ····························|··································|·············|·············|·············|···············|·············· | HomeFi · initialize · 277701 · 277713 · 277708 · 25 · - │ ····························|··································|·············|·············|·············|···············|·············· @@ -60,7 +60,7 @@ ····························|··································|·············|·············|·············|···············|·············· | HomeFi · replaceTreasury · 39853 · 39859 · 39856 · 6 · - │ ····························|··································|·············|·············|·············|···············|·············· -| HomeFi · setAddr · 60001 · 176579 · 168249 · 28 · - │ +| HomeFi · setAddr · 60001 · 176579 · 168245 · 28 · - │ ····························|··································|·············|·············|·············|···············|·············· | HomeFi · setTrustedForwarder · 35732 · 37587 · 36666 · 5 · - │ ····························|··································|·············|·············|·············|···············|·············· @@ -68,9 +68,9 @@ ····························|··································|·············|·············|·············|···············|·············· | HomeFiProxy · changeProxyAdminOwner · - · - · 36055 · 2 · - │ ····························|··································|·············|·············|·············|···············|·············· -| HomeFiProxy · initiateHomeFi · 4467840 · 4467852 · 4467847 · 28 · - │ +| HomeFiProxy · initiateHomeFi · 4467310 · 4467334 · 4467328 · 28 · - │ ····························|··································|·············|·············|·············|···············|·············· -| HomeFiProxy · upgradeMultipleImplementations · - · - · 49955 · 18 · - │ +| HomeFiProxy · upgradeMultipleImplementations · - · - · 49881 · 18 · - │ ····························|··································|·············|·············|·············|···············|·············· | HomeFiV2Mock · incrementCounter · - · - · 50803 · 1 · - │ ····························|··································|·············|·············|·············|···············|·············· @@ -78,51 +78,51 @@ ····························|··································|·············|·············|·············|···············|·············· | MinimalForwarder · execute · 73827 · 75841 · 75170 · 3 · - │ ····························|··································|·············|·············|·············|···············|·············· -| Project · acceptInviteSC · 69534 · 1713402 · 304295 · 42 · - │ +| Project · acceptInviteSC · 69460 · 1709332 · 303650 · 42 · - │ ····························|··································|·············|·············|·············|···············|·············· -| Project · addTasks · 136589 · 3908727 · 427567 · 40 · - │ +| Project · addTasks · 136491 · 3901577 · 426925 · 40 · - │ ····························|··································|·············|·············|·············|···············|·············· -| Project · allocateFunds · 37549 · 78813 · 63493 · 18 · - │ +| Project · allocateFunds · 37397 · 78227 · 63152 · 18 · - │ ····························|··································|·············|·············|·············|···············|·············· -| Project · changeOrder · 75632 · 140907 · 120672 · 256 · - │ +| Project · changeOrder · 75636 · 140833 · 120606 · 256 · - │ ····························|··································|·············|·············|·············|···············|·············· | Project · delegateContractor · 44918 · 66852 · 52900 · 12 · - │ ····························|··································|·············|·············|·············|···············|·············· -| Project · inviteContractor · 67775 · 69839 · 69561 · 32 · - │ +| Project · inviteContractor · 67693 · 69733 · 69460 · 32 · - │ ····························|··································|·············|·············|·············|···············|·············· -| Project · inviteSC · 51646 · 424055 · 95727 · 38 · - │ +| Project · inviteSC · 51572 · 420059 · 95019 · 38 · - │ ····························|··································|·············|·············|·············|···············|·············· -| Project · lendToProject · 108069 · 1550340 · 460655 · 68 · - │ +| Project · lendToProject · 107335 · 1534070 · 456449 · 68 · - │ ····························|··································|·············|·············|·············|···············|·············· -| Project · recoverTokens · 37236 · 187679 · 91142 · 6 · - │ +| Project · recoverTokens · 37236 · 183461 · 89736 · 6 · - │ ····························|··································|·············|·············|·············|···············|·············· -| Project · setComplete · 93653 · 97735 · 97535 · 132 · - │ +| Project · setComplete · 93653 · 97735 · 97533 · 132 · - │ ····························|··································|·············|·············|·············|···············|·············· -| Project · updateProjectHash · 39293 · 62161 · 54538 · 6 · - │ +| Project · updateProjectHash · 39213 · 62081 · 54458 · 6 · - │ ····························|··································|·············|·············|·············|···············|·············· -| Project · updateTaskHash · 53554 · 62816 · 58185 · 8 · - │ +| Project · updateTaskHash · 53247 · 62509 · 57878 · 8 · - │ ····························|··································|·············|·············|·············|···············|·············· -| ProjectFactory · changeProjectImplementation · 53502 · 53526 · 53517 · 4 · - │ +| ProjectFactory · changeProjectImplementation · 53514 · 53526 · 53523 · 4 · - │ ····························|··································|·············|·············|·············|···············|·············· -| ProjectFactory · initialize · 96662 · 96686 · 96682 · 26 · - │ +| ProjectFactory · initialize · 96674 · 96686 · 96684 · 26 · - │ ····························|··································|·············|·············|·············|···············|·············· | Deployments · · % of limit · │ ·······························································|·············|·············|·············|···············|·············· -| Community · - · - · 3425844 · 11.4 % · - │ +| Community · - · - · 3419596 · 11.4 % · - │ ·······························································|·············|·············|·············|···············|·············· -| CommunityV2Mock · - · - · 3437299 · 11.5 % · - │ +| CommunityV2Mock · - · - · 3431076 · 11.4 % · - │ ·······························································|·············|·············|·············|···············|·············· | DebtToken · - · - · 844982 · 2.8 % · - │ ·······························································|·············|·············|·············|···············|·············· | DebtTokenV2Mock · - · - · 859263 · 2.9 % · - │ ·······························································|·············|·············|·············|···············|·············· -| Disputes · - · - · 1340217 · 4.5 % · - │ +| Disputes · - · - · 1331167 · 4.4 % · - │ ·······························································|·············|·············|·············|···············|·············· -| DisputesV2Mock · - · - · 1351672 · 4.5 % · - │ +| DisputesV2Mock · - · - · 1342629 · 4.5 % · - │ ·······························································|·············|·············|·············|···············|·············· -| HomeFi · - · - · 2230658 · 7.4 % · - │ +| HomeFi · - · - · 2224190 · 7.4 % · - │ ·······························································|·············|·············|·············|···············|·············· -| HomeFiProxy · - · - · 2157489 · 7.2 % · - │ +| HomeFiProxy · - · - · 2143363 · 7.1 % · - │ ·······························································|·············|·············|·············|···············|·············· | HomeFiV2Mock · - · - · 2271946 · 7.6 % · - │ ·······························································|·············|·············|·············|···············|·············· @@ -130,14 +130,18 @@ ·······························································|·············|·············|·············|···············|·············· | MinimalForwarder · - · - · 683397 · 2.3 % · - │ ·······························································|·············|·············|·············|···············|·············· -| Project · 3141486 · 3141498 · 3141496 · 10.5 % · - │ +| Project · 3105643 · 3105655 · 3105653 · 10.4 % · - │ ·······························································|·············|·············|·············|···············|·············· -| ProjectFactory · - · - · 426108 · 1.4 % · - │ +| ProjectFactory · - · - · 426120 · 1.4 % · - │ ·······························································|·············|·············|·············|···············|·············· -| ProjectV2Mock · - · - · 3152965 · 10.5 % · - │ +| ProjectV2Mock · - · - · 3117119 · 10.4 % · - │ ·······························································|·············|·············|·············|···············|·············· | ProxyAdmin · - · - · 472762 · 1.6 % · - │ ·······························································|·············|·············|·············|···············|·············· | SignatureDecoderMock · - · - · 230621 · 0.8 % · - │ ·······························································|·············|·············|·············|···············|·············· -| Tasks · - · - · 101769 · 0.3 % · +| Tasks · - · - · 101757 · 0.3 % · - │ +·--------------------------------------------------------------|-------------|-------------|-------------|---------------|-------------·