Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gas Optimizations #88

Open
code423n4 opened this issue Oct 10, 2022 · 0 comments
Open

Gas Optimizations #88

code423n4 opened this issue Oct 10, 2022 · 0 comments
Labels
bug Something isn't working G (Gas Optimization)

Comments

@code423n4
Copy link
Contributor

code423n4 commented Oct 10, 2022

Gas Optimizations

Summary Of Findings:

  Issue
1 Optimizations in Governed.sol
2 Optimizations in Pausable.sol
3 Optimizations in L2GraphToken.sol

Detailed Report on Gas Optimization Findings:

1. Optimizations in Governed.sol

The optimizations are based on the following points:

  • If the value which want to emit is already available in the function argument or in a memory variable, then avoid emitting it from a state variable.
  • If a state variable is used more than once, cache it into a memory variable to save gas.
  • Often the emit statement can be placed before the state variable is assignined to avoid reading from the state variable twice.

The following diff along with comments show the exact optimizations.

diff --git "a/.\\orig.sol" "b/.\\modified.sol"
index 12eced1..b8b78f6 100644
--- "a/.\\orig.sol"
+++ "b/.\\modified.sol"
@@ -43,7 +43,7 @@ contract Governed {
         address oldPendingGovernor = pendingGovernor;
         pendingGovernor = _newGovernor;
 
-        emit NewPendingOwnership(oldPendingGovernor, pendingGovernor);
+        emit NewPendingOwnership(oldPendingGovernor, _newGovernor);   //@audit gas saving: emit _newGovernor which was just assigend to pendingGovernor
     }
 
     /**
@@ -51,18 +51,16 @@ contract Governed {
      * This function must called by the pending governor.
      */
     function acceptOwnership() external {
+        address oldPendingGovernor = pendingGovernor;  //@audit gas saving: cache it. read twice within require statement
         require(
-            pendingGovernor != address(0) && msg.sender == pendingGovernor,
+            oldPendingGovernor != address(0) && msg.sender == oldPendingGovernor,
             "Caller must be pending governor"
         );
-
         address oldGovernor = governor;
-        address oldPendingGovernor = pendingGovernor;
-
-        governor = pendingGovernor;
+        governor = msg.sender;  //@audit gas saving: works because of previous require statement
         pendingGovernor = address(0);
-
-        emit NewOwnership(oldGovernor, governor);
-        emit NewPendingOwnership(oldPendingGovernor, pendingGovernor);
+        emit NewOwnership(oldGovernor, msg.sender);  //@audit gas saving: emit cached value
+        emit NewPendingOwnership(msg.sender, address(0));  //@audit gas saving: works because of previous require statement
+        
     }
-}
\ No newline at end of file
+}

Two functions, transferOwnership and acceptOwnership were gas optimized. The hardhat gas results before and after optimization are given below:

Function  Avg gas cost before Optimization Avg gas cost After Optimization Gas saving
transferOwnership 47567 47561 6
acceptOwnership 29993 29746 247

Total gas saved in Governed.sol = 6 + 247 = 253.

2. Optimizations in Pausable.sol

The optimizations are based on the following points:

  • Sometimes storage slots could be saved by packing your state variables together to fit into one slot. This works only on variables which declared one after each other.
  • If the value which want to emit is already available in the function argument or in a memory variable, then avoid emitting it from a state variable.
  • If a state variable is used more than once, cache it into a memory variable to save gas.

The following diff along with comments show the exact optimizations.

diff --git "a/.\\orig.sol" "b/.\\modified.sol"
index 1f88ceb..e1b39a3 100644
--- "a/.\\orig.sol"
+++ "b/.\\modified.sol"
@@ -3,11 +3,6 @@
 pragma solidity ^0.7.6;
 
 contract Pausable {
-    // Partial paused paused exit and enter functions for GRT, but not internal
-    // functions, such as allocating
-    bool internal _partialPaused;
-    // Paused will pause all major protocol functions
-    bool internal _paused;
 
     // Time last paused for both pauses
     uint256 public lastPausePartialTime;
@@ -16,6 +11,13 @@ contract Pausable {
     // Pause guardian is a separate entity from the governor that can pause
     address public pauseGuardian;
 
+    //@audit gas saving: moved the two bool's here to save one storage slot.
+    // Partial paused paused exit and enter functions for GRT, but not internal
+    // functions, such as allocating
+    bool internal _partialPaused;
+    // Paused will pause all major protocol functions
+    bool internal _paused;
+
     event PartialPauseChanged(bool isPaused);
     event PauseChanged(bool isPaused);
     event NewPauseGuardian(address indexed oldPauseGuardian, address indexed pauseGuardian);
@@ -28,10 +30,10 @@ contract Pausable {
             return;
         }
         _partialPaused = _toPause;
-        if (_partialPaused) {
+        if (_toPause) {    //@audit gas saving: use _toPause as it was just assigned to _partialPaused
             lastPausePartialTime = block.timestamp;
         }
-        emit PartialPauseChanged(_partialPaused);
+        emit PartialPauseChanged(_toPause);   //@audit gas saving: use _toPause as it was just assigned to _partialPaused
     }
 
     /**
@@ -42,10 +44,10 @@ contract Pausable {
             return;
         }
         _paused = _toPause;
-        if (_paused) {
+        if (_toPause) {  //@audit gas saving: use _toPause as it was just assigned to _paused
             lastPauseTime = block.timestamp;
         }
-        emit PauseChanged(_paused);
+        emit PauseChanged(_toPause);  //@audit gas saving: use _toPause as it was just assigned to _paused
     }
 
     /**
@@ -55,6 +57,6 @@ contract Pausable {
     function _setPauseGuardian(address newPauseGuardian) internal {
         address oldPauseGuardian = pauseGuardian;
         pauseGuardian = newPauseGuardian;
-        emit NewPauseGuardian(oldPauseGuardian, pauseGuardian);
+        emit NewPauseGuardian(oldPauseGuardian, newPauseGuardian);  //@audit gas saving: emit newPauseGuardian which was just assigend to pauseGuardian
     }
-}
\ No newline at end of file
+}

Three functions, _setPartialPaused , _setPaused and _setPauseGuardian were gas optimized. The hardhat gas results before and after optimization are given below:

Function  Avg gas cost before Optimization Avg gas cost After Optimization Gas saving
_setPartialPaused 49195 45795 3400
_setPaused 30817 29626 1191
_setPauseGuardian 47575 47569 6

Total gas saved in Pausable.sol = 3400 + 1191 + 6 = 4597.

3. Optimizations in L2GraphToken.sol

In L2GraphToken, a function called setGateway was optimized by emitting the function argument instead of the state variable which was just assigned.

The following diff along with comments show the exact optimizations.

diff --git "a/.\\orig.sol" "b/.\\modified.sol"
index b3f01c6..374bcfd 100644
--- "a/.\\orig.sol"
+++ "b/.\\modified.sol"
@@ -59,7 +59,7 @@ contract L2GraphToken is GraphTokenUpgradeable, IArbToken {
     function setGateway(address _gw) external onlyGovernor {
         require(_gw != address(0), "INVALID_GATEWAY");
         gateway = _gw;
-        emit GatewaySet(gateway);
+        emit GatewaySet(_gw);  //@audit gas saving: use _gw as it was just assigned to gateway
     }
 
     /**
@@ -91,4 +91,4 @@ contract L2GraphToken is GraphTokenUpgradeable, IArbToken {
         burnFrom(_account, _amount);
         emit BridgeBurned(_account, _amount);
     }
-}
\ No newline at end of file
+}

The hardhat gas results before and after optimization are given below:

Function  Avg gas cost before Optimization Avg gas cost After Optimization Gas saving
setGateway 54314 54296 18

Total gas saved in L2GraphToken.sol = 18.

Conclusions:

  Issue Avg Gas Saved
1 Optimizations in Governed.sol 253
2 Optimizations in Pausable.sol 4597
3 Optimizations in L2GraphToken.sol 18

TOTAL GAS SAVED = 253 + 4597 + 18 = 4868.

@code423n4 code423n4 added bug Something isn't working G (Gas Optimization) labels Oct 10, 2022
code423n4 added a commit that referenced this issue Oct 10, 2022
code423n4 added a commit that referenced this issue Oct 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working G (Gas Optimization)
Projects
None yet
Development

No branches or pull requests

1 participant