code-423n4 / 2024-03-taiko-findings

3 stars 2 forks source link

Gas Optimizations #134

Open c4-bot-1 opened 7 months ago

c4-bot-1 commented 7 months ago

See the markdown file with the details of this report here.

c4-judge commented 6 months ago

0xean marked the issue as grade-b

albahaca0000 commented 6 months ago

Hi @0xean thanks for judging

I dont' know why my report has grade b , I suggest a lot of gas optimization techniques, That are similar to the grade a reports and with more unique ones,Please kindly review my report again

SUMMARY

issue instance
[G‑01] Use calldata instead of memory for function arguments that do not get mutated 70
[G‑02] Use assembly to check for address(0) 55
[G‑03] State variables that are used multiple times in a function should be cached in stack variables 14
[G‑04] Can Make The Variable Outside The Loop To Save Gas 17
[G‑05] Use assembly to write address storage values 17
[G‑06] Use nested if statements instead of && 20
[G‑07] Multiple Address/id Mappings Can Be Combined Into A Single Mapping Of An Address/id To A Struct, Where Appropriate 5
[G‑08] internal functions not called by the contract should be removed to save deployment gas 13
[G‑09] Amounts should be checked for 0 before calling a transfer 6
[G‑10] Avoid updating storage when the value hasn't changed 20
[G‑11] Do not calculate constants 2
[G‑12] State variables can be packed into fewer storage slots 2
[G‑13] With assembly, .call (bool success) transfer can be done gas-optimized 1
[G‑14] Use hardcode address instead address(this) 31
[G‑15] Structs can be packed to use fewer storage slots 4
[G‑16] use Mappings Instead of Arrays 1
[G‑17] Use constants instead of type(uintx).max 4
[G‑18] Duplicated require()/if() checks should be refactored to a modifier or function 3
[G‑19] Not using the named return variables when a function returns, wastes deployment gas 10
[G‑20] Using storage instead of memory for structs/arrays saves gas 2
[G‑21] Multiple accesses of a mapping/array should use a local variable cache 45
[G‑22] internal functions only called once can be inlined to save gas 23
[G‑23] bytes constants are more eficient than string constans 5
[G‑24] Use assembly to hash instead of solidity 28
[G‑25] Stack variable used as a cheaper cache for a state variable is only used once 1
[G‑26] Use assembly to emit an event 55
[G‑27] Using a positive conditional flow to save a NOT opcode 2
[G‑28] Avoid contract existence checks by using low level calls 25
[G‑29] Use do while loops instead of for loops 5
[G‑30] Splitting require() statements that use && saves gas 3
[G‑31] Do not shrink Variables 2
[G‑32] Constructors can be marked payable 3
[G‑33] The result of function calls should be cached rather than re-calling the function 33
[G‑34] Empty Blocks Should Be Removed Or Emit Something 4
[G‑35] Use custom errors rather than revert()/require() strings to save gas 35
[G‑36] State variables only set in the constructor should be declared immutable 2
[G‑37] Caching global variables is more expensive than using the actual variable (use msg.sender instead of caching it) 2
[G‑38] Use local variables for emitting 6
[G‑39] Use selfbalance() instead of address(this).balance 6
[G‑40] Private functions used once can be inlined 35
[G‑41] State variable read in a loop 15
[G‑42] Use struct dot notation to avoid memory allocation 4
[G‑43] Use assembly in place of abi.decode to extract calldata values more efficiently 16
[G‑44] Cache external calls outside of loop to avoid re-calling function on each iteration 6
[G‑45] Structs can be modified to fit in fewer storage slots 1
[G‑46] Use assembly to validate msg.sender 10
[G‑47] Pre-increment and pre-decrement are cheaper thanĀ +1 ,-1 5
[G‑48] Storage re-read via storage pointer 4
[G‑49] Initializer can be marked payable 25
[G‑50] Use inline assembly to access the chain ID 37
[G‑51] Consider using OZ EnumerateSet in place of nested mappings 7
[G‑52] Instead of counting down in for statements, count up 25
[G‑53] require() or revert() statements that check input arguments should be at the top of the function 4
[G‑54] Structs should group like types together to save gas 12
[G‑55] >= costs less gas than > 1
[G‑56] Usage of uints/ints smaller than 32 bytes (256 bits) incurs overhead 16
[G‑57] Emit Used In Loop 3
[G‑58] Require()/revert() Strings Longer Than 32 Bytes Cost Extra Gas 1
[G‑59] Using private rather than public for constants, saves gas 2
[G‑60] Functions guaranteed to revert when called by normal users can be marked payable 2
[G‑61] Superfluous event fields 1
[G‑62] Use assembly to perform efficient back-to-back calls 2
[G‑63] Delete variables that you don't need 1

This encompasses my gas optimization technique suggestions, akin to those found in grade-A reports.

[G-01] Use calldata instead of memory for function arguments that do not get mutated

[G-02] Use assembly to check for address(0)

[G‑03] State variables that are used multiple times in a function should be cached in stack variables

[G-04] Can Make The Variable Outside The Loop To Save Gas

[G-05] Use assembly to write address storage values

[G-06] Use nested if statements instead of &&

[G-07] Multiple Address/id Mappings Can Be Combined Into A Single Mapping Of An Address/id To A Struct, Where Appropriate

[G-08] internal functions not called by the contract should be removed to save deployment gas

[G-09] Amounts should be checked for 0 before calling a transfer

[G-10] Avoid updating storage when the value hasn't changed

[G-11] Do not calculate constants

[G-12] State variables can be packed into fewer storage slots

[G-13] With assembly, .call (bool success) transfer can be done gas-optimized

[G-14] Use hardcode address instead address(this)

[G-15] Structs can be packed to use fewer storage slots

[G-16] use Mappings Instead of Arrays

[G-17] Use constants instead of type(uintx).max

[G-18] Duplicated require()/if() checks should be refactored to a modifier or function

[G-19] Not using the named return variables when a function returns, wastes deployment gas

[G-20] Using storage instead of memory for structs/arrays saves gas

[G‑21] Multiple accesses of a mapping/array should use a local variable cache

[G‑22] internal functions only called once can be inlined to save gas

[G-23] bytes constants are more eficient than string constans

[G-24] Use assembly to hash instead of solidity

[G-25] Stack variable used as a cheaper cache for a state variable is only used once

[G-26] Use assembly to emit an event

[G-27] Using a positive conditional flow to save a NOT opcode uniqe

[G-28] Avoid contract existence checks by using low level calls

[G-29] Use do while loops instead of for loops

[G-30] Splitting require() statements that use && saves gas

[G-31] Do not shrink Variables

[G-32] Constructors can be marked payable

[G-33] The result of function calls should be cached rather than re-calling the function

[G-34] Empty Blocks Should Be Removed Or Emit Something

[G‑35] Use custom errors rather than revert()/require() strings to save gas note: these are instance missed from bots

[G‑36] State variables only set in the constructor should be declared immutable

[G-37] Caching global variables is more expensive than using the actual variable (use msg.sender instead of caching it)

[G-38] Use local variables for emitting

[G-39] Use selfbalance() instead of address(this).balance

[G-40] Private functions used once can be inlined

[G-41] State variable read in a loop

[G-42] Use struct dot notation to avoid memory allocation

[G-43] Use assembly in place of abi.decode to extract calldata values more efficiently

[G-44] Cache external calls outside of loop to avoid re-calling function on each iteration

[G-45] Structs can be modified to fit in fewer storage slots

[G‑46] Use assembly to validate msg.sender

[G-47] Pre-increment and pre-decrement are cheaper thanĀ +1 ,-1

[G-48] Storage re-read via storage pointer

[G-49] Initializer can be marked payable

[G‑50] Use inline assembly to access the chain ID

[G-51] Consider using OZ EnumerateSet in place of nested mappings

[G-52] Instead of counting down in for statements, count up

[G-53] require() or revert() statements that check input arguments should be at the top of the function

[G-54] Structs should group like types together to save gas

[G-55] >= costs less gas than > [G-56] Usage of uints/ints smaller than 32 bytes (256 bits) incurs overhead

[G-57] Emit Used In Loop

[G-58] Require()/revert() Strings Longer Than 32 Bytes Cost Extra Gas

[G-59] Using private rather than public for constants, saves gas

[G-60] Functions guaranteed to revert when called by normal users can be marked payable Note: these insteance are missed from bots

[G-61] Superfluous event fields

[G-62] Use assembly to perform efficient back-to-back calls [G-63] Delete variables that you don't need

0xean commented 6 months ago

in the future would encourage you to quantify the gas savings in the report and ensure its fully de-duped against the bot findings.

albahaca0000 commented 6 months ago

Hi @0xean thanks for judging

Thank you for your review once again. Regarding the gas findings, I followed a specific approach. I used a checklist to manually examine each finding. Additionally, I checked the bot findings for any missed instances of the issues. In my report, I made sure to include a note in the description section to indicate the instances that were missed by the bot.

Note: In my report, I manually identified additional issues, but the ones I mentioned specifically stand out due to their significant cost implications

Here are the issues found by the bots but with incomplete instances. I thoroughly checked everything manually and identified these missed instances:

Furthermore, I discovered additional expensive issues in my report that were not only identified by me but also by other wardens. These issues are particularly costly to address. Despite being marked as grade-A reports, not all of them were thoroughly examined. In one report, these high-cost issues were notably overlooked, underscoring the importance of addressing such critical matters comprehensively.

Additionally, Some wardens might not have conducted a thorough examination of the complete codebase, resulting in the identification of only a limited number of instances for each issue. Conversely, in my report, I carefully reviewed the entire codebase.

This issue is costly, and they were not identified by other wardens. It's important to note that external calls can be particularly expensive, especially when they're used within a loop. By caching external calls outside of the loop, you can prevent the function from being recalled on each iteration, saving a significant amount of gas.

This issue also stands out as unique

c4-judge commented 6 months ago

0xean marked the issue as grade-a