Skip to content

Commit 7e760ef

Browse files
authored
[Certora Audit] G-08. Use shift right/left instead of division/multiplication if possible (safe-global#895)
This pull request includes optimizations to the gas usage in the `Safe.sol` and `StorageAccessible.sol` contracts by replacing multiplication operations with bitwise shift operations. While the `DIV / MUL` opcode uses 5 gas, the `SHR / SHL` opcode only uses 3 gas. Gas optimization changes: * [`contracts/Safe.sol`](diffhunk://#diff-587b494ea631bb6b7adf4fc3e1a2e6a277a385ff16e1163b26e39de24e9483deL168-R169): Replaced the multiplication operation `* 64` with the bitwise shift operation `<< 6` to reduce gas costs in the `gasleft` check. * [`contracts/common/StorageAccessible.sol`](diffhunk://#diff-a7dd65d90b0567bb9ba14ecd4ff414529a934cd3752ccf309800fad93fba354eL18-R18): Replaced the multiplication operation `* 32` with the bitwise shift operation `<< 5` to reduce gas costs when creating a new bytes array.
1 parent 5c8c6c0 commit 7e760ef

File tree

2 files changed

+4
-2
lines changed

2 files changed

+4
-2
lines changed

contracts/Safe.sol

+2-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ contract Safe is
165165

166166
// We require some gas to emit the events (at least 2500) after the execution and some to perform code until the execution (500)
167167
// We also include the 1/64 in the check that is not sent along with a call to counteract potential shortings because of EIP-150
168-
if (gasleft() < ((safeTxGas * 64) / 63).max(safeTxGas + 2500) + 500) revertWithError("GS010");
168+
// We use `<< 6` instead of `* 64` as SHR / SHL opcode only uses 3 gas, while DIV / MUL opcode uses 5 gas.
169+
if (gasleft() < ((safeTxGas << 6) / 63).max(safeTxGas + 2500) + 500) revertWithError("GS010");
169170
// Use scope here to limit variable lifetime and prevent `stack too deep` errors
170171
{
171172
uint256 gasUsed = gasleft();

contracts/common/StorageAccessible.sol

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ abstract contract StorageAccessible {
1515
* @return the bytes that were read.
1616
*/
1717
function getStorageAt(uint256 offset, uint256 length) public view returns (bytes memory) {
18-
bytes memory result = new bytes(length * 32);
18+
// We use `<< 5` instead of `* 32` as SHR / SHL opcode only uses 3 gas, while DIV / MUL opcode uses 5 gas.
19+
bytes memory result = new bytes(length << 5);
1920
for (uint256 index = 0; index < length; ++index) {
2021
/* solhint-disable no-inline-assembly */
2122
/// @solidity memory-safe-assembly

0 commit comments

Comments
 (0)