Ethos Reserve contest - Deivitto's results

A CDP-backed stablecoin platform designed to generate yield on underlying assets to establish a sustainable DeFi stable interest rate.

General Information

Platform: Code4rena

Start Date: 16/02/2023

Pot Size: $144,750 USDC

Total HM: 17

Participants: 154

Period: 19 days

Judge: Trust

Total Solo HM: 5

Id: 216

League: ETH

Ethos Reserve

Findings Distribution

Researcher Performance

Rank: 36/154

Findings: 2

Award: $370.05

Gas:
grade-a

🌟 Selected for report: 0

🚀 Solo Findings: 0

Gas

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

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.

Both mapping being used in the same functions mostly consider making them a struct instead



  • ActivePool.sol#L41 mapping (address => uint256) internal collAmount; // collateral => amount tracker
  • ActivePool.sol#L42 mapping (address => uint256) internal LUSDDebt; // collateral => corresponding debt tracker
  • ActivePool.sol#L44 mapping (address => uint256) public yieldingPercentage; // collateral => % to use for yield farming (in BPS, <= 10k)
  • ActivePool.sol#L45 mapping (address => uint256) public yieldingAmount; // collateral => actual wei amount being used for yield farming
  • ActivePool.sol#L46 mapping (address => address) public yieldGenerator; // collateral => corresponding ERC4626 vault
  • ActivePool.sol#L47 mapping (address => uint256) public yieldClaimThreshold; // collateral => minimum wei amount of yield to claim and redistribute




<x> += <y> costs more gas than <x> = <x> + <y> for state variables

Using the addition operator instead of plus-equals saves gas. Same goes for other operands like -=.

Redeclaring variables each loop iteration consumes extra gas

Rather than re assigning values to the variables each iterations, at for loops it is being redeclared each variable all over again.

-StabilityPool.sol#L352-L353

-StabilityPool.sol#L398-L399

-StabilityPool.sol#L832-L833

-StabilityPool.sol#L860-L864

-TroveManager.sol#L610

-TroveManager.sol#L819

-LQTYStaking.sol#L207-L208

-LQTYStaking.sol#L229

-LQTYStaking.sol#L242

-ReaperStrategyGranarySupplyOnly.sol#L120

-ReaperVaultV2.sol#L265

Increments at loops can be unchecked{++i} to save gas

In Solidity 0.8+, there’s a default overflow check on unsigned integers. It’s possible to uncheck this in for-loops and save some gas at each iteration, but at the cost of some code readability, as this uncheck cannot be made inline without an extra function. This extra function is used in some parts of the code, however in some locations it is not used

require()/revert() strings longer than 32 bytes cost extra gas

NOTE: None of these findings where found by 4naly3er output - Gas

Each extra memory word of bytes past the original 32 incurs an MSTORE which costs 3 gas

bytes constants are more efficient than string constants

If data can fit into 32 bytes, then you should use bytes32 datatype rather than bytes or strings as it is cheaper in solidity.

Should use arguments instead of state variable

This removes an extra SLOAD

Superfluous event fields can be omitted

block.timestamp and block.number are added to event information by default so adding them manually wastes extra gas.

abi.encode() is less gas efficient than abi.encodePacked()

Changing the abi.encode function to abi.encodePacked can save gas since the abi.encode function pads extra null bytes at the end of the call data, which is unnecessary. Also, in general, abi.encodePacked is more gas-efficient.

Splitting require() / assert() statements that use && saves gas

Instead of using the && operator in a single require statement to check multiple conditions, consider using multiple require statements with 1 condition per require statement (saving 3 gas per &).

Use of safeMath can be avoided to save gas

In other parts of the project solidity version ^0.8 it's being used and has overflow protection by default so it's not needed safeMath.

Use Custom Errors consumes less gas than regular require strings

NOTE: None of these findings where found by 4naly3er output - Gas

Source Instead of using error strings, to reduce deployment and runtime cost, you should use Custom Errors. This would save both deployment and runtime cost.

Use assembly to check for address(0) for gas saves

NOTE: None of these findings where found by 4naly3er output - Gas

Saves 6 gas per instance

Initializing variables with default value wastes extra gas

NOTE: None of these findings where found by 4naly3er output - Gas

Functions guaranteed to revert when called by normal users can be marked payable

NOTE: None of these findings where found by 4naly3er output - Gas

If a function modifier such as onlyOwner is used, the function will revert if a normal user tries to pay the function. Marking the function as payable will lower the gas cost for legitimate callers because the compiler will not include checks for whether a payment was provided.

The extra opcodes avoided are: CALLVALUE (2), DUP1 (3), ISZERO (3), PUSH2 (3), JUMPI (10), PUSH1 (3), DUP1 (3), REVERT(0), JUMPDEST (1), POP (2), which costs an average of about 21 gas per call to the function, in addition to the extra deployment cost

unchecked block can be used to save gas

Where is not expected to overflow, unchecked can be used

Explicit named return can be removed

decimals can be set as uint8 for convention and to save 1 storage slot

value of distributionPeriod can be set as default value to save gas

Remove testing libs for gas saves

#0 - c4-judge

2023-03-08T12:44:04Z

trust1995 marked the issue as grade-a

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