Skip to content

Commit

Permalink
[Certora Audit] G-08. Use shift right/left instead of division/multip…
Browse files Browse the repository at this point in the history
…lication if possible (#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.
  • Loading branch information
remedcu authored Jan 10, 2025
1 parent 5c8c6c0 commit 7e760ef
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 2 deletions.
3 changes: 2 additions & 1 deletion contracts/Safe.sol
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ contract Safe is

// We require some gas to emit the events (at least 2500) after the execution and some to perform code until the execution (500)
// 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
if (gasleft() < ((safeTxGas * 64) / 63).max(safeTxGas + 2500) + 500) revertWithError("GS010");
// We use `<< 6` instead of `* 64` as SHR / SHL opcode only uses 3 gas, while DIV / MUL opcode uses 5 gas.
if (gasleft() < ((safeTxGas << 6) / 63).max(safeTxGas + 2500) + 500) revertWithError("GS010");
// Use scope here to limit variable lifetime and prevent `stack too deep` errors
{
uint256 gasUsed = gasleft();
Expand Down
3 changes: 2 additions & 1 deletion contracts/common/StorageAccessible.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ abstract contract StorageAccessible {
* @return the bytes that were read.
*/
function getStorageAt(uint256 offset, uint256 length) public view returns (bytes memory) {
bytes memory result = new bytes(length * 32);
// We use `<< 5` instead of `* 32` as SHR / SHL opcode only uses 3 gas, while DIV / MUL opcode uses 5 gas.
bytes memory result = new bytes(length << 5);
for (uint256 index = 0; index < length; ++index) {
/* solhint-disable no-inline-assembly */
/// @solidity memory-safe-assembly
Expand Down

0 comments on commit 7e760ef

Please sign in to comment.