Platform: Code4rena
Start Date: 28/10/2022
Pot Size: $165,500 USDC
Total HM: 2
Participants: 24
Period: 12 days
Judge: GalloDaSballo
Total Solo HM: 1
Id: 177
League: ETH
Rank: 21/24
Findings: 1
Award: $229.76
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0x1f8b
Also found by: Aymen0909, HardlyCodeMan, IllIllI, ReyAdmirado, Rolezn, TomJ, c3phas, gogo, mcwildy
229.7602 USDC - $229.76
Each slot saved can avoid an extra Gsset (20000 gas) for the first setting of the struct. Subsequent reads as well as writes have smaller gas savings
zkPorterIsAvailable
can be put after or before one of the address variables to make the struct smaller and save gas
even if they are for readability, consider making them comments instead
<x> += <y>
costs more gas than <x> = <x> + <y>
for state variablesUsing the addition operator instead of plus-equals saves gas
here ++s.diamondCutStorage.currentProposalId
would be even cheaper
logSender
priorityOp
currentBlockCommitment
facetAddr
facetToSelectors
hashedBytecode
&&
saves gasthis will have a large deployment gas cost but with enough runtime calls the split require version will be 3 gas cheaper
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.
bring this require before the 2 requires before it because of possible gas saves
first part of the require() is being repeated so under no circumstances it will happen
Use a solidity version of at least 0.8.2 to get 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
calldata
instead of memory
for read-only arguments in external functions saves gasWhen a function with a memory array is called externally, the abi.decode() step has to use a for-loop to copy each index of the calldata to the memory index. Each iteration of this for-loop costs at least 60 gas (i.e. 60 * <mem_array>.length). Using calldata directly, obliviates the need for such a loop in the contract code and runtime execution.
_lastCommittedBlockData
_log
Not inlining costs 20 to 40 gas because of two extra JUMP instructions and additional stack operations needed for function calls.
_collectOperationsFromPriorityQueue
_executeOneBlock
_getBlockProofPublicInput
_verifyRecursivePartOfProof
_maxU256
_createBlockCommitment
_blockPassThroughData
_blockMetaParameters
_blockAuxilaryOutput
_L2MessageToLog
_requestL2Transaction
_writePriorityOp
_hashFactoryDeps
_depositFunds
_getDepositL2Calldata
_getERC20Getters
_parseL2WithdrawalMessage
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.
When using elements that are smaller than 32 bytes, your contract’s gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size. Each operation involving a uint8 costs an extra 22-28 gas (depending on whether the other operand is also a variable of type uint8) as compared to ones involving uint256, due to the compiler having to clear the higher bits of the memory word before operating on the uint8, as well as the associated stack operations of doing so. Use a larger size then downcast where needed https://docs.soliditylang.org/en/v0.8.11/internals/layout_in_storage.html Use a larger size then downcast where needed
Contracts are allowed to override their parents’ functions and change the visibility from external to public and can save gas by doing so.
l2TokenAddress
use newTotalBlocksCommitted
instead of s.totalBlocksCommitted
#0 - GalloDaSballo
2022-11-25T01:31:49Z
1 | Structs can be packed into fewer storage slots 2k
2 | expressions for constant values such as a call to keccak256(), should use immutable rather than constant Not anymore, fixed a long time ago
3 | state var is defined but not used anywhere but 4 | <x> += <y> costs more gas than <x> = <x> + <y> for state variables 34
5 | not using the named return variables when a function returns, wastes deployment gas 3 6 | can make the variable outside the loop to save gas Not gonna save gas, also you should explain what this is supposed to mean (and add benchmarks)
7 | splitting require() statements that use && saves gas 3
8 | require() or revert() statements that check input arguments should be at the top of the function
9 | require() is repeated so it wastes has due to being checked again
10 | use a more recent version of solidity 200 in lack of skipped checks
11 | using calldata instead of memory for read-only arguments in external functions saves gas Will not compile
12 | internal functions only called once can be inlined to save gas 19 * 24 456
13 | Multiple address/ID mappings can be combined into a single mapping of an address/ID to a struct 2k
14 | abi.encode() is less efficient than abi.encodepacked() 15 | usage of uint/int smaller than 32 bytes (256 bits) incurs overhead 16 | public functions not called by the contract should be declared external instead 17 | emit can be optimized 100
The ones without math I either cannot quantify or don't think are correct
4796
#1 - c4-judge
2022-12-03T19:02:40Z
GalloDaSballo marked the issue as grade-b