Rigor Protocol contest - bharg4v's results

Community lending and instant payments for new home construction.

General Information

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

Rigor Protocol

Findings Distribution

Researcher Performance

Rank: 116/133

Findings: 1

Award: $21.76

🌟 Selected for report: 0

🚀 Solo Findings: 0

Gas Optimizations Report

Table of Contents

  1. Don't Initialize Variables with Default Value
  2. Cache Array Length Outside of Loop
  3. Use != 0 instead of > 0 for Unsigned Integer Comparison
  4. ++i/i++ should be unchecked{++i}/unchecked{i++} when it is not possible for them to overflow, for example when used in for- and while-loops
  5. Prefix increments cheaper than Postfix increments
  6. Multiple address mappings can be combined into a single mapping of an address to a struct, where appropriate

1. Don't Initialize Variables with Default Value

Impact

Uninitialized variables are assigned with the types default value. Explicitly initializing a variable with it's default value costs unnecesary gas.

Background Information

POC

2022-08-rigor/contracts/Community.sol::624 => for (uint256 i = 0; i < _communities[_communityID].memberCount; i++) { 2022-08-rigor/contracts/HomeFiProxy.sol::87 => for (uint256 i = 0; i < _length; i++) { 2022-08-rigor/contracts/HomeFiProxy.sol::136 => for (uint256 i = 0; i < _length; i++) { 2022-08-rigor/contracts/Project.sol::248 => for (uint256 i = 0; i < _length; i++) { 2022-08-rigor/contracts/Project.sol::311 => for (uint256 i = 0; i < _length; i++) { 2022-08-rigor/contracts/Project.sol::322 => for (uint256 i = 0; i < _length; i++) { 2022-08-rigor/contracts/libraries/Tasks.sol::181 => for (uint256 i = 0; i < _length; i++) _alerts[i] = _self.alerts[i];

2. Cache Array Length Outside of Loop

Impact

Caching the array length outside a loop saves reading it on each iteration, as long as the array's length is not changed during the loop.

POC

2022-08-rigor/contracts/Project.sol::603 => for (; i < _changeOrderedTask.length; i++) {

Background Information

3. Use != 0 instead of > 0 for Unsigned Integer Comparison

Impact

When dealing with unsigned integer types, comparisons with != 0 are cheaper then with > 0. This change saves 6 gas per instance.

POC

2022-08-rigor/contracts/Community.sol::764 => require(_repayAmount > 0, "Community::!repay"); 2022-08-rigor/contracts/Community.sol::840 => if (_interestEarned > 0) { 2022-08-rigor/contracts/Disputes.sol::107 => _actionType > 0 && _actionType <= uint8(ActionType.TaskPay), 2022-08-rigor/contracts/Project.sol::195 => require(_cost > 0, "Project::!value>0"); 2022-08-rigor/contracts/Project.sol::380 => if (_leftOutTokens > 0) { 2022-08-rigor/contracts/Project.sol::691 => if (_loopCount > 0) emit TaskAllocated(_tasksAllocated);

4. ++i/i++ should be unchecked{++i}/unchecked{i++} when it is not possible for them to overflow, for example when used in for- and while-loops

Impact

The unchecked keyword is new in solidity version 0.8.0, so this only applies to that version or higher, which these instances are. This saves 30-40 gas per loop

POC

2022-08-rigor/contracts/HomeFiProxy.sol::87 => for (uint256 i = 0; i < _length; i++) 2022-08-rigor/contracts/HomeFiProxy.sol::136 => for (uint256 i = 0; i < _length; i++) { 2022-08-rigor/contracts/Project.sol::311 => for (uint256 i = 0; i < _length; i++) { 2022-08-rigor/contracts/libraries/Tasks.sol::181 => for (uint256 i = 0; i < _length; i++) _alerts[i] = _self.alerts[i];

5. Prefix increments cheaper than Postfix increments

Impact

++i costs less gas than i++, especially when it's used in for-loops (--i/i-- too) Saves S gas PER LOOP

POC

2022-08-rigor/contracts/HomeFiProxy.sol::87 => for (uint256 i = 0; i < _length; i++) 2022-08-rigor/contracts/HomeFiProxy.sol::136 => for (uint256 i = 0; i < _length; i++) { 2022-08-rigor/contracts/Project.sol::311 => for (uint256 i = 0; i < _length; i++) { 2022-08-rigor/contracts/libraries/Tasks.sol::181 => for (uint256 i = 0; i < _length; i++) _alerts[i] = _self.alerts[i];

6. Multiple address mappings can be combined into a single mapping of an address to a struct, where appropriate

Saves a storage slot for the mapping. Depending on the circumstances and sizes of types, can avoid a Gsset (20000 gas) per mapping combined. Reads and subsequent writes can also be cheaper when a function requires both values and they both fit in the same storage slot. Finally, if both fields are accessed in the same function, can save -42 gas per access due to not having to recalculate the key's keccak256 hash (Gkeccak256 - 30 gas) and that calculation's associated stack operations.

POC

https://github.com/code-423n4/2022-08-rigor/blob/5ab7ea84a1516cb726421ef690af5bc41029f88f/contracts/Community.sol#L41
AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter