If a variable is not set/initialized, it is assumed to have the default value (0, false, 0x0 etc depending on the data type).
Explicitly initializing it with its default value is an anti-pattern and wastes gas.
Remove explicit initialization for default values.
Unchecked arithmetic
IMPACT
The default "checked" behavior costs more gas when adding/diving/multiplying, because under-the-hood those checks are implemented as a series of opcodes that, prior to performing the actual arithmetic, check for under/overflow and revert if it is detected.
if it can statically be determined there is no possible way for your arithmetic to under/overflow (such as a condition in an if statement), surrounding the arithmetic in an unchecked block will save gas.
Gas Report
Table of Contents
Comparison Operators
IMPACT
In the EVM, there is no opcode for
>=
or<=
. When using greater than or equal, two operations are performed:>
and=
.Using strict comparison operators hence saves gas
PROOF OF CONCEPT
Instances include:
ConduitController.sol
channelIndex >= totalChannels
CriteriaResolution.sol
orderIndex >= totalAdvancedOrders\ componentIndex >= offer.length\ componentIndex >= consideration.length
Verifiers.sol
endTime <= block.timestamp\ orderStatus.numerator >= orderStatus.denominator
TOOLS USED
Manual Analysis
MITIGATION
Replace
<=
with<
, and>=
with>
. Do not forget to increment/decrement the compared variableexample:
However, if
1
is negligible compared to the value of the variable, we can omit the increment.example:
Default value initialization
IMPACT
If a variable is not set/initialized, it is assumed to have the default value (0, false, 0x0 etc depending on the data type). Explicitly initializing it with its default value is an anti-pattern and wastes gas.
PROOF OF CONCEPT
Instances include:
Conduit.sol
uint256 i = 0\ uint256 i = 0
AmountDeriver.sol
uint256 extraCeiling = 0
BasicOrderFulfiller.sol
uint256 i = 0\ uint256 i = 0
ConsiderationConstants
uint256 constant NoContract_error_sig_ptr = 0x0
CriteriaResolution.sol
uint256 i = 0\ uint256 i = 0\ uint256 j = 0\ uint256 j = 0
OrderCombiner.sol
uint256 i = 0\ uint256 j = 0\ uint256 j = 0\ uint256 i = 0\ uint256 totalFilteredExecutions = 0\ uint256 i = 0\ uint256 i = 0\ uint256 i = 0\ uint256 j = 0\ uint256 i = 0\ uint256 totalFilteredExecutions = 0\ uint256 i = 0
OrderFulfiller.sol
uint256 i = 0\ uint256 i = 0\ uint256 i = 0
OrderValidator.sol
uint256 i = 0\ uint256 i = 0
TokenTransferrerConstants.sol
uint256 constant ERC20_transferFrom_sig_ptr = 0x0\ uint256 constant ERC1155_safeTransferFrom_sig_ptr = 0x0\ uint256 constant ERC721_transferFrom_sig_ptr = 0x0\ uint256 constant NoContract_error_sig_ptr = 0x0\ uint256 constant TokenTransferGenericFailure_error_sig_ptr = 0x0\ uint256 constant BadReturnValueFromERC20OnTransfer_error_sig_ptr = 0x0\ uint256 constant Invalid1155BatchTransferEncoding_ptr = 0x0
TOOLS USED
Manual Analysis
MITIGATION
Remove explicit initialization for default values.
Unchecked arithmetic
IMPACT
The default "checked" behavior costs more gas when adding/diving/multiplying, because under-the-hood those checks are implemented as a series of opcodes that, prior to performing the actual arithmetic, check for under/overflow and revert if it is detected.
if it can statically be determined there is no possible way for your arithmetic to under/overflow (such as a condition in an if statement), surrounding the arithmetic in an
unchecked
block will save gas.PROOF OF CONCEPT
Instances include:
FulfillmentApplier.sol
considerationItem.amount - execution.item.amount: because of the check line 90, this cannot underflow\ execution.item.amount - considerationItem.amount: because of the check line 90, this cannot underflow
TOOLS USED
Manual Analysis
MITIGATION
Place the arithmetic operations in an
unchecked
block