Reading array length at each iteration of the loop takes 6 gas (3 for mload and 3 to place memory_offset) in the stack. Caching the array length in the stack saves around 3 gas per iteration.
Proof of Concept
lib\OrderCombiner.sol::247 => for (uint256 j = 0; j < offer.length; ++j) {
lib\OrderCombiner.sol::291 => for (uint256 j = 0; j < consideration.length; ++j) {
lib\OrderCombiner.sol::598 => for (uint256 j = 0; j < consideration.length; ++j) {
lib\OrderCombiner.sol::621 => for (uint256 i = 0; i < executions.length; ) {
lib\OrderFulfiller.sol::217 => for (uint256 i = 0; i < orderParameters.offer.length; ) {
lib\OrderFulfiller.sol::306 => for (uint256 i = 0; i < orderParameters.consideration.length; ) {
Recommendation
Store the array’s length in a variable before the for-loop.
[G-02] No need to initialize variables with default values
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
conduit\Conduit.sol::66 => for (uint256 i = 0; i < totalStandardTransfers; ) {
conduit\Conduit.sol::130 => for (uint256 i = 0; i < totalStandardTransfers; ) {
lib\AmountDeriver.sol::44 => uint256 extraCeiling = 0;
lib\BasicOrderFulfiller.sol::948 => for (uint256 i = 0; i < totalAdditionalRecipients; ) {
lib\BasicOrderFulfiller.sol::1040 => for (uint256 i = 0; i < totalAdditionalRecipients; ) {
lib\CriteriaResolution.sol::56 => for (uint256 i = 0; i < totalCriteriaResolvers; ++i) {
lib\CriteriaResolution.sol::166 => for (uint256 i = 0; i < totalAdvancedOrders; ++i) {
lib\CriteriaResolution.sol::184 => for (uint256 j = 0; j < totalItems; ++j) {
lib\CriteriaResolution.sol::199 => for (uint256 j = 0; j < totalItems; ++j) {
lib\OrderCombiner.sol::181 => for (uint256 i = 0; i < totalOrders; ++i) {
lib\OrderCombiner.sol::247 => for (uint256 j = 0; j < offer.length; ++j) {
lib\OrderCombiner.sol::291 => for (uint256 j = 0; j < consideration.length; ++j) {
lib\OrderCombiner.sol::373 => for (uint256 i = 0; i < totalOrders; ++i) {
lib\OrderCombiner.sol::470 => uint256 totalFilteredExecutions = 0;
lib\OrderCombiner.sol::473 => for (uint256 i = 0; i < totalOfferFulfillments; ++i) {
lib\OrderCombiner.sol::498 => for (uint256 i = 0; i < totalConsiderationFulfillments; ++i) {
lib\OrderCombiner.sol::577 => for (uint256 i = 0; i < totalOrders; ++i) {
lib\OrderCombiner.sol::598 => for (uint256 j = 0; j < consideration.length; ++j) {
lib\OrderCombiner.sol::621 => for (uint256 i = 0; i < executions.length; ) {
lib\OrderCombiner.sol::751 => uint256 totalFilteredExecutions = 0;
lib\OrderCombiner.sol::754 => for (uint256 i = 0; i < totalFulfillments; ++i) {
lib\OrderFulfiller.sol::217 => for (uint256 i = 0; i < orderParameters.offer.length; ) {
lib\OrderFulfiller.sol::306 => for (uint256 i = 0; i < orderParameters.consideration.length; ) {
lib\OrderFulfiller.sol::471 => for (uint256 i = 0; i < totalOrders; ++i) {
lib\OrderValidator.sol::272 => for (uint256 i = 0; i < totalOrders; ) {
lib\OrderValidator.sol::350 => for (uint256 i = 0; i < totalOrders; ) {
Gas
[G-01] Cache Array Length Outside of Loop.
Impact
Reading array length at each iteration of the loop takes 6 gas (3 for mload and 3 to place memory_offset) in the stack. Caching the array length in the stack saves around 3 gas per iteration.
Proof of Concept
Recommendation
Store the array’s length in a variable before the for-loop.
[G-02] No need to initialize variables with default values
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
Recommendation
Remove explicit default initializations.
Tools used
manual
Gas Diffchecker
yarn profile
https://www.diffchecker.com/8afIz8bOGas Before
Gas After