code-423n4 / 2022-06-nested-findings

0 stars 1 forks source link

Gas Optimizations #49

Open code423n4 opened 2 years ago

code423n4 commented 2 years ago

NestedFactory.sol

transferToReserveAndStore: balanceReserveAfter can be inlined

In the _transferToReserveAndStore function, we store the reserve balance after the transfer in the balanceReserveAfter variable, on line 523.

This variable being only used once, we can inline it and save one mstore.

Recommendation:

nestedRecords.store(_nftId, address(_token), _token.balanceOf(reserveAddr) - balanceReserveBefore, reserveAddr);

TimelockControllerEmergency.sol

scheduleBatch: targets.length should be stored in a variable

In the scheduleBatch function on line 221, we call targets.length to compare the targets length and also to loop through the targets and emit the CallScheduled event.

For a better code legibility and also to save some mload, targets length should be stored in a variable.

Recommendation:

uint256 _targetsLength = targets.length;

require(targetsLength == values.length, "TimelockController: length mismatch");
require(targetsLength == datas.length, "TimelockController: length mismatch");

bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);
schedule(id, delay);
for (uint256 i = 0; i < targetsLength; ++i) {
  emit CallScheduled(id, i, targets[i], values[i], datas[i], predecessor, delay);
}

executeBatch: targets.length should be stored in a variable

In the executeBatch function on line 312, we call targets.length to compare the targets length and also to loop through the targets and call the _call function.

For a better code legibility and also to save some mload, targets length should be stored in a variable.

Recommendation:

uint256 _targetsLength = targets.length;

require(_targetsLength == values.length, "TimelockController: length mismatch");
require(_targetsLength == datas.length, "TimelockController: length mismatch");

bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);
_beforeCall(id, predecessor);
for (uint256 i = 0; i < _targetsLength; ++i) {
    _call(id, i, targets[i], values[i], datas[i]);
}
_afterCall(id);
Yashiru commented 2 years ago

TransferToReserveAndStore: balanceReserveAfter can be inlined (Confirmed)

Gas optimization confirmed

Yashiru commented 2 years ago

ScheduleBatch: targets.length should be stored in a variable (Confirmed)

Gas optimization confirmed

ExecuteBatch: targets.length should be stored in a variable (Confirmed)

Gas optimization confirmed