Ethos Reserve contest - 0x6980'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: 140/154

Findings: 1

Award: $42.07

Gas:
grade-b

🌟 Selected for report: 0

πŸš€ Solo Findings: 0

1. Using private rather than public for constants, saves gas.

If needed, the values can be read from the verified contract source code, or if there are multiple values there can be a single getter function that returns a tuple of the values of all currently-public constants. Saves 3406-3606 gas in deployment gas due to the compiler not having to create non-payable getter functions for deployment calldata, not having to store the bytes of the value outside of where it’s used, and not adding another entry to the method ID table.

2. <x> += <y> Costs More Gas Than <x> = <x> + <y> For State Variables

3. Splitting require() statements that use && saves gas

4. Expressions for constant values such as a call to keccak256(), should use immutable rather than constant

5. State variables should be cached in stack variables rather than re-reading them from storage.

The instances below point to the second+ access of a state variable within a function. Caching of a state variable replace each Gwarmaccess (100 gas) with a much cheaper stack read. Other less obvious fixes/optimizations include having local memory caches of state variable structs, or having local caches of state variable contracts/addresses.

6. Add unchecked {} for subtractions where the operands cannot underflow because of a previous require() or if statement.

7. Not using the named return variables when a function returns, wastes deployment gas

8. Can make the variable outside the loop to save gas.

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

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

10. require() or revert() statements that check input arguments should be at the top of the function]

Checks that involve constants should come before checks that involve state variables, function calls, and calculations. By doing these checks first, the function is able to revert before wasting a Gcoldsload (2100 gas*) in a function that may ultimately revert in the unhappy case.

Change the position of these 2 requires at least before L153) for possible gas save:

11. Use a more recent version of solidity.

Use a Solidity version of at least 0.8.2 to get simple compiler automatic inlining.

Use a Solidity version of at least 0.8.3 to get better struct packing and cheaper multiple storage reads.

Use a Solidity version of at least 0.8.4 to get custom errors, which are cheaper at deployment than revert()/require() strings.

Use a Solidity version of at least 0.8.10 to have external calls skip contract existence checks if the external call has a return value.

Use a Solidity version of at least 0.8.12 to get string.concat() to be used instead of abi.encodePacked(<str>,<str>).

Use a solidity version of at least 0.8.13 to get the ability to use using for with a list of free functions.

12. Internal functions only called once can be inlined to save gas.

Not inlining costs 20 to 40 gas because of two extra JUMP instructions and additional stack operations needed for function calls.

13. Use asssembly to check for address(0)

14. Should check some variables before some functions for possible save gas.

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

If a function modifier or require such as onlyOwner/onlyX 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.

16. ++i costs less than i++, specially when it's used in for -loops.

#0 - c4-judge

2023-03-09T14:14:25Z

trust1995 marked the issue as grade-b

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