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 #91

Open
code423n4 opened this issue Jun 18, 2022 · 5 comments
Open

Gas Optimizations #91

code423n4 opened this issue Jun 18, 2022 · 5 comments
Assignees
Labels

Comments

@code423n4
Copy link
Contributor

Gas Optimizations

The following sections detail the gas optimizations found throughout the codebase. Each optimization is documented with the setup, an explainer for the optimization, a gas report and line identifiers for each optimization across the codebase. For each section's gas report, the optimizer was turned on and set to 10000 runs. You can replicate any tests/gas reports by heading to 0xKitsune/gas-lab and cloning the repo. Then, simply copy/paste the contract examples from any section and run forge test --gas-report. You can also easily update the optimizer runs in the foundry.toml.


unchecked{++i} instead of i++ (or use assembly when applicable)

Use ++i instead of i++. This is especially useful in for loops but this optimization can be used anywhere in your code. You can also use unchecked{++i;} for even more gas savings but this will not check to see if i overflows. For extra safety if you are worried about this, you can add a require statement after the loop checking if i is equal to the final incremented value. For best gas savings, use inline assembly, however this limits the functionality you can achieve. For example you cant use Solidity syntax to internally call your own contract within an assembly block and external calls must be done with the call() or delegatecall() instruction. However when applicable, inline assembly will save much more gas.

contract GasTest is DSTest {
    Contract0 c0;
    Contract1 c1;
    Contract2 c2;
    Contract3 c3;
    Contract4 c4;

    function setUp() public {
        c0 = new Contract0();
        c1 = new Contract1();
        c2 = new Contract2();
        c3 = new Contract3();
        c4 = new Contract4();
    }

    function testGas() public {
        c0.iPlusPlus();
        c1.plusPlusI();
        c2.uncheckedPlusPlusI();
        c3.safeUncheckedPlusPlusI();
        c4.inlineAssemblyLoop();
    }
}

contract Contract0 {
    //loop with i++
    function iPlusPlus() public pure {
        uint256 j = 0;
        for (uint256 i; i < 10; i++) {
            j++;
        }
    }
}

contract Contract1 {
    //loop with ++i
    function plusPlusI() public pure {
        uint256 j = 0;
        for (uint256 i; i < 10; ++i) {
            j++;
        }
    }
}

contract Contract2 {
    //loop with unchecked{++i}
    function uncheckedPlusPlusI() public pure {
        uint256 j = 0;
        for (uint256 i; i < 10; ) {
            j++;

            unchecked {
                ++i;
            }
        }
    }
}

contract Contract3 {
    //loop with unchecked{++i} with additional overflow check
    function safeUncheckedPlusPlusI() public pure {
        uint256 j = 0;
        uint256 i = 0;
        for (i; i < 10; ) {
            j++;

            unchecked {
                ++i;
            }
        }

        //check for overflow
        assembly {
            if lt(i, 10) {
                mstore(0x00, "loop overflow")
                revert(0x00, 0x20)
            }
        }
    }
}

contract Contract4 {
    //loop with inline assembly
    function inlineAssemblyLoop() public pure {
        assembly {
            let j := 0

            for {
                let i := 0
            } lt(i, 10) {
                i := add(i, 0x01)
            } {
                j := add(j, 0x01)
            }
        }
    }
}

Gas Report

╭────────────────────┬─────────────────┬──────┬────────┬──────┬─────────╮
 Contract0 contract                                               
╞════════════════════╪═════════════════╪══════╪════════╪══════╪═════════╡
 Deployment Cost     Deployment Size                              
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 37687               219                                          
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg   median  max   # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 iPlusPlus           2039             2039  2039    2039  1       
╰────────────────────┴─────────────────┴──────┴────────┴──────┴─────────╯
╭────────────────────┬─────────────────┬──────┬────────┬──────┬─────────╮
 Contract1 contract                                               
╞════════════════════╪═════════════════╪══════╪════════╪══════╪═════════╡
 Deployment Cost     Deployment Size                              
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 37287               217                                          
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg   median  max   # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 plusPlusI           1989             1989  1989    1989  1       
╰────────────────────┴─────────────────┴──────┴────────┴──────┴─────────╯
╭────────────────────────┬─────────────────┬──────┬────────┬──────┬─────────╮
 Contract3 contract                                                   
╞════════════════════════╪═════════════════╪══════╪════════╪══════╪═════════╡
 Deployment Cost         Deployment Size                              
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 42693                   244                                          
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name           min              avg   median  max   # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 safeUncheckedPlusPlusI  1355             1355  1355    1355  1       
╰────────────────────────┴─────────────────┴──────┴────────┴──────┴─────────╯
╭────────────────────┬─────────────────┬──────┬────────┬──────┬─────────╮
 Contract2 contract                                               
╞════════════════════╪═════════════════╪══════╪════════╪══════╪═════════╡
 Deployment Cost     Deployment Size                              
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 35887               210                                          
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg   median  max   # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 uncheckedPlusPlusI  1329             1329  1329    1329  1       
╰────────────────────┴─────────────────┴──────┴────────┴──────┴─────────╯
╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract4 contract                                             
╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost     Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 26881               164                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 inlineAssemblyLoop  709              709  709     709  1       
╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯

Lines

  • BeefyVaultOperator.sol:18

  • BeefyZapUniswapLPVaultOperator.sol:27

  • YearnCurveVaultOperator.sol:42

  • NestedFactory.sol:124

  • NestedFactory.sol:136

  • NestedFactory.sol:196

  • NestedFactory.sol:256

  • NestedFactory.sol:315

  • NestedFactory.sol:333

  • NestedFactory.sol:369

  • NestedFactory.sol:412

  • NestedFactory.sol:651

  • TimelockControllerEmergency.sol:84

  • TimelockControllerEmergency.sol:89

  • TimelockControllerEmergency.sol:234

  • TimelockControllerEmergency.sol:324

  • MixinOperatorResolver.sol:37

  • MixinOperatorResolver.sol:56

  • BeefyZapBiswapLPVaultOperator.sol:27

  • OperatorScripts.sol:67

  • OperatorScripts.sol:80

  • CurveHelpers.sol:22

  • CurveHelpers.sol:42

  • CurveHelpers.sol:62

  • CurveHelpers.sol:86

  • OperatorResolver.sol:40

  • OperatorResolver.sol:60

  • OperatorResolver.sol:75


Use assembly to check for address(0)

contract GasTest is DSTest {
    Contract0 c0;
    Contract1 c1;

    function setUp() public {
        c0 = new Contract0();
        c1 = new Contract1();
    }

    function testGas() public view {
        c0.ownerNotZero(address(this));
        c1.assemblyOwnerNotZero(address(this));
    }
}

contract Contract0 {
    function ownerNotZero(address _addr) public pure {
        require(_addr != address(0), "zero address)");
    }
}

contract Contract1 {
    function assemblyOwnerNotZero(address _addr) public pure {
        assembly {
            if iszero(_addr) {
                mstore(0x00, "zero address")
                revert(0x00, 0x20)
            }
        }
    }
}

Gas Report

╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract0 contract                                             
╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost     Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 61311               338                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 ownerNotZero        258              258  258     258  1       
╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
╭──────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract1 contract                                               
╞══════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost       Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 44893                 255                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name         min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 assemblyOwnerNotZero  252              252  252     252  1       
╰──────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯

Lines

  • BeefyVaultOperator.sol:43

  • BeefyVaultOperator.sol:85

  • BeefyZapUniswapLPVaultOperator.sol:54

  • BeefyZapUniswapLPVaultOperator.sol:99

  • YearnVaultStorage.sol:30

  • YearnVaultStorage.sol:31

  • YearnVaultStorage.sol:32

  • YearnVaultStorage.sol:33

  • YearnVaultStorage.sol:34

  • YearnVaultStorage.sol:42

  • YearnCurveVaultOperator.sol:73

  • YearnCurveVaultOperator.sol:123

  • YearnCurveVaultOperator.sol:167

  • YearnCurveVaultOperator.sol:215

  • YearnCurveVaultOperator.sol:263

  • OwnerProxy.sol:17

  • NestedFactory.sol:67

  • NestedFactory.sol:68

  • NestedFactory.sol:69

  • NestedFactory.sol:70

  • NestedFactory.sol:71

  • NestedFactory.sol:72

  • NestedFactory.sol:73

  • NestedFactory.sol:140

  • NestedFactory.sol:153

  • NestedFactory.sol:574

  • MixinOperatorResolver.sol:23

  • MixinOperatorResolver.sol:41

  • MixinOperatorResolver.sol:64

  • MixinOperatorResolver.sol:77

  • BeefyVaultStorage.sol:25

  • BeefyVaultStorage.sol:26

  • BeefyVaultStorage.sol:27

  • BeefyVaultStorage.sol:35

  • BeefyZapBiswapLPVaultOperator.sol:54

  • BeefyZapBiswapLPVaultOperator.sol:99

  • OperatorScripts.sol:19

  • OperatorScripts.sol:20

  • OperatorScripts.sol:29

  • OperatorScripts.sol:61

  • ParaswapOperator.sol:16

  • OwnableProxyDelegation.sol:25

  • OwnableProxyDelegation.sol:57

  • OperatorResolver.sol:27


Use multiple require() statments insted of require(expression && expression && ...)

contract GasTest is DSTest {
    Contract0 c0;
    Contract1 c1;

    function setUp() public {
        c0 = new Contract0();
        c1 = new Contract1();
    }

    function testGas() public {
        c0.singleRequire(3);
        c1.multipleRequire(3);
    }
}

contract Contract0 {
    function singleRequire(uint256 num) public {
        require(num > 1 && num < 10 && num == 3);
    }
}

contract Contract1 {
    function multipleRequire(uint256 num) public {
        require(num > 1);
        require(num < 10);
        require(num == 3);
    }
}

Gas Report

╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract0 contract                                             
╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost     Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 35487               208                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 singleRequire       286              286  286     286  1       
╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract1 contract                                             
╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost     Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 35887               210                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 multipleRequire     270              270  270     270  1       
╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯

Lines

  • BeefyVaultOperator.sol:54

  • BeefyZapUniswapLPVaultOperator.sol:64

  • BeefyZapUniswapLPVaultOperator.sol:65

  • NestedFactory.sol:67

  • BeefyZapBiswapLPVaultOperator.sol:64

  • BeefyZapBiswapLPVaultOperator.sol:65

  • ParaswapOperator.sol:16


Use assembly to hash instead of Solidity

contract GasTest is DSTest {
    Contract0 c0;
    Contract1 c1;

    function setUp() public {
        c0 = new Contract0();
        c1 = new Contract1();
    }

    function testGas() public view {
        c0.solidityHash(2309349, 2304923409);
        c1.assemblyHash(2309349, 2304923409);
    }
}

contract Contract0 {
    function solidityHash(uint256 a, uint256 b) public view {
        //unoptimized
        keccak256(abi.encodePacked(a, b));
    }
}

contract Contract1 {
    function assemblyHash(uint256 a, uint256 b) public view {
        //optimized
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            let hashedVal := keccak256(0x00, 0x40)
        }
    }
}

Gas Report

╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract0 contract                                             
╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost     Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 36687               214                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 solidityHash        313              313  313     313  1       
╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract1 contract                                             
╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost     Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 31281               186                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 assemblyHash        231              231  231     231  1       
╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯

Lines

  • StakingLPVaultHelpers.sol:105

  • StakingLPVaultHelpers.sol:135

  • TimelockControllerEmergency.sol:173

  • TimelockControllerEmergency.sol:187


Use assembly for math (add, sub, mul, div)

Use assembly for math instead of Solidity. You can check for overflow/underflow in assembly to ensure safety. If using Solidity versions < 0.8.0 and you are using Safemath, you can gain significant gas savings by using assembly to calculate values and checking for overflow/underflow.

contract GasTest is DSTest {
    Contract0 c0;
    Contract1 c1;
    Contract2 c2;
    Contract3 c3;
    Contract4 c4;
    Contract5 c5;
    Contract6 c6;
    Contract7 c7;

    function setUp() public {
        c0 = new Contract0();
        c1 = new Contract1();
        c2 = new Contract2();
        c3 = new Contract3();
        c4 = new Contract4();
        c5 = new Contract5();
        c6 = new Contract6();
        c7 = new Contract7();
    }

    function testGas() public {
        c0.addTest(34598345, 100);
        c1.addAssemblyTest(34598345, 100);
        c2.subTest(34598345, 100);
        c3.subAssemblyTest(34598345, 100);
        c4.mulTest(34598345, 100);
        c5.mulAssemblyTest(34598345, 100);
        c6.divTest(34598345, 100);
        c7.divAssemblyTest(34598345, 100);
    }
}

contract Contract0 {
    //addition in Solidity
    function addTest(uint256 a, uint256 b) public pure {
        uint256 c = a + b;
    }
}

contract Contract1 {
    //addition in assembly
    function addAssemblyTest(uint256 a, uint256 b) public pure {
        assembly {
            let c := add(a, b)

            if lt(c, a) {
                mstore(0x00, "overflow")
                revert(0x00, 0x20)
            }
        }
    }
}

contract Contract2 {
    //subtraction in Solidity
    function subTest(uint256 a, uint256 b) public pure {
        uint256 c = a - b;
    }
}

contract Contract3 {
    //subtraction in assembly
    function subAssemblyTest(uint256 a, uint256 b) public pure {
        assembly {
            let c := sub(a, b)

            if gt(c, a) {
                mstore(0x00, "underflow")
                revert(0x00, 0x20)
            }
        }
    }
}

contract Contract4 {
    //multiplication in Solidity
    function mulTest(uint256 a, uint256 b) public pure {
        uint256 c = a * b;
    }
}

contract Contract5 {
    //multiplication in assembly
    function mulAssemblyTest(uint256 a, uint256 b) public pure {
        assembly {
            let c := mul(a, b)

            if lt(c, a) {
                mstore(0x00, "overflow")
                revert(0x00, 0x20)
            }
        }
    }
}

contract Contract6 {
    //division in Solidity
    function divTest(uint256 a, uint256 b) public pure {
        uint256 c = a * b;
    }
}

contract Contract7 {
    //division in assembly
    function divAssemblyTest(uint256 a, uint256 b) public pure {
        assembly {
            let c := div(a, b)

            if gt(c, a) {
                mstore(0x00, "underflow")
                revert(0x00, 0x20)
            }
        }
    }
}

Gas Report

╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract0 contract                                             
╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost     Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 40493               233                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 addTest             303              303  303     303  1       
╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract1 contract                                             
╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost     Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 37087               216                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 addAssemblyTest     263              263  263     263  1       
╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract2 contract                                             
╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost     Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 40293               232                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 subTest             300              300  300     300  1       
╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract3 contract                                             
╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost     Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 37287               217                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 subAssemblyTest     263              263  263     263  1       
╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract4 contract                                             
╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost     Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 41893               240                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 mulTest             325              325  325     325  1       
╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract5 contract                                             
╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost     Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 37087               216                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 mulAssemblyTest     265              265  265     265  1       
╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract6 contract                                             
╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost     Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 41893               240                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 divTest             325              325  325     325  1       
╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract7 contract                                             
╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost     Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 37287               217                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 divAssemblyTest     265              265  265     265  1       
╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯

Lines

  • BeefyVaultOperator.sol:52

  • BeefyVaultOperator.sol:53

  • BeefyVaultOperator.sol:93

  • BeefyVaultOperator.sol:94

  • BeefyZapUniswapLPVaultOperator.sol:61

  • BeefyZapUniswapLPVaultOperator.sol:62

  • BeefyZapUniswapLPVaultOperator.sol:106

  • BeefyZapUniswapLPVaultOperator.sol:107

  • BeefyZapUniswapLPVaultOperator.sol:145

  • BeefyZapUniswapLPVaultOperator.sol:249

  • BeefyZapUniswapLPVaultOperator.sol:273

  • BeefyZapUniswapLPVaultOperator.sol:280

  • BeefyZapUniswapLPVaultOperator.sol:284

  • NestedFactory.sol:138

  • NestedFactory.sol:263

  • NestedFactory.sol:264

  • NestedFactory.sol:341

  • NestedFactory.sol:378

  • NestedFactory.sol:379

  • NestedFactory.sol:381

  • NestedFactory.sol:388

  • NestedFactory.sol:431

  • NestedFactory.sol:435

  • NestedFactory.sol:439

  • NestedFactory.sol:443

  • NestedFactory.sol:446

  • NestedFactory.sol:497

  • NestedFactory.sol:525

  • NestedFactory.sol:560

  • NestedFactory.sol:593

  • NestedFactory.sol:629

  • NestedFactory.sol:632

  • NestedFactory.sol:644

  • StakingLPVaultHelpers.sol:44

  • StakingLPVaultHelpers.sol:76

  • StakingLPVaultHelpers.sol:102

  • StakingLPVaultHelpers.sol:132

  • TimelockControllerEmergency.sol:245

  • BeefyZapBiswapLPVaultOperator.sol:61

  • BeefyZapBiswapLPVaultOperator.sol:62

  • BeefyZapBiswapLPVaultOperator.sol:106

  • BeefyZapBiswapLPVaultOperator.sol:107

  • BeefyZapBiswapLPVaultOperator.sol:145

  • BeefyZapBiswapLPVaultOperator.sol:249

  • BeefyZapBiswapLPVaultOperator.sol:275

  • BeefyZapBiswapLPVaultOperator.sol:282

  • BeefyZapBiswapLPVaultOperator.sol:286

  • ParaswapOperator.sol:37

  • ParaswapOperator.sol:38


Use assembly when getting a contract's balance of ETH.

You can use selfbalance() instead of address(this).balance when getting your contract's balance of ETH to save gas. Additionally, you can use balance(address) instead of address.balance() when getting an external contract's balance of ETH.

contract GasTest is DSTest {
    Contract0 c0;
    Contract1 c1;
    Contract2 c2;
    Contract3 c3;

    function setUp() public {
        c0 = new Contract0();
        c1 = new Contract1();
        c2 = new Contract2();
        c3 = new Contract3();
    }

    function testGas() public {
        c0.addressInternalBalance();
        c1.assemblyInternalBalance();
        c2.addressExternalBalance(address(this));
        c3.assemblyExternalBalance(address(this));
    }
}

contract Contract0 {
    function addressInternalBalance() public returns (uint256) {
        return address(this).balance;
    }
}

contract Contract1 {
    function assemblyInternalBalance() public returns (uint256) {
        assembly {
            let c := selfbalance()
            mstore(0x00, c)
            return(0x00, 0x20)
        }
    }
}

contract Contract2 {
    function addressExternalBalance(address addr) public {
        uint256 bal = address(addr).balance;
        bal++;
    }
}

contract Contract3 {
    function assemblyExternalBalance(address addr) public {
        uint256 bal;
        assembly {
            bal := balance(addr)
        }
        bal++;
    }
}

Gas Report

╭────────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract0 contract                                                 
╞════════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost         Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 23675                   147                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name           min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 addressInternalBalance  148              148  148     148  1       
╰────────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
╭─────────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract1 contract                                                  
╞═════════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost          Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 27081                    165                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name            min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 assemblyInternalBalance  133              133  133     133  1       
╰─────────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
╭────────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract2 contract                                                 
╞════════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost         Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 61511                   339                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name           min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 addressExternalBalance  417              417  417     417  1       
╰────────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
╭─────────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract3 contract                                                  
╞═════════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost          Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 57105                    317                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name            min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 assemblyExternalBalance  411              411  411     411  1       
╰─────────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯

Lines

  • NestedFactory.sol:544

Use custom errors instead of string error messages

contract GasTest is DSTest {
    Contract0 c0;
    Contract1 c1;

    function setUp() public {
        c0 = new Contract0();
        c1 = new Contract1();
    }

    function testFailGas() public {
        c0.stringErrorMessage();
        c1.customErrorMessage();
    }
}

contract Contract0 {
    function stringErrorMessage() public {
        bool check = false;
        require(check, "error message");
    }
}

contract Contract1 {
    error CustomError();

    function customErrorMessage() public {
        bool check = false;
        if (!check) {
            revert CustomError();
        }
    }
}

Gas Report

╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract0 contract                                             
╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost     Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 34087               200                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 stringErrorMessage  218              218  218     218  1       
╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract1 contract                                             
╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost     Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 26881               164                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 customErrorMessage  161              161  161     161  1       
╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯

Lines

  • BeefyVaultOperator.sol:15

  • BeefyVaultOperator.sol:41

  • BeefyVaultOperator.sol:43

  • BeefyVaultOperator.sol:50

  • BeefyVaultOperator.sol:54

  • BeefyVaultOperator.sol:55

  • BeefyVaultOperator.sol:83

  • BeefyVaultOperator.sol:85

  • BeefyVaultOperator.sol:91

  • BeefyVaultOperator.sol:95

  • BeefyVaultOperator.sol:96

  • BeefyZapUniswapLPVaultOperator.sol:23

  • BeefyZapUniswapLPVaultOperator.sol:52

  • BeefyZapUniswapLPVaultOperator.sol:54

  • BeefyZapUniswapLPVaultOperator.sol:64

  • BeefyZapUniswapLPVaultOperator.sol:65

  • BeefyZapUniswapLPVaultOperator.sol:97

  • BeefyZapUniswapLPVaultOperator.sol:99

  • BeefyZapUniswapLPVaultOperator.sol:108

  • BeefyZapUniswapLPVaultOperator.sol:109

  • BeefyZapUniswapLPVaultOperator.sol:142

  • BeefyZapUniswapLPVaultOperator.sol:187

  • BeefyZapUniswapLPVaultOperator.sol:198

  • BeefyZapUniswapLPVaultOperator.sol:269

  • BeefyZapUniswapLPVaultOperator.sol:270

  • YearnVaultStorage.sol:30

  • YearnVaultStorage.sol:31

  • YearnVaultStorage.sol:32

  • YearnVaultStorage.sol:33

  • YearnVaultStorage.sol:34

  • YearnVaultStorage.sol:42

  • YearnCurveVaultOperator.sol:39

  • YearnCurveVaultOperator.sol:70

  • YearnCurveVaultOperator.sol:73

  • YearnCurveVaultOperator.sol:121

  • YearnCurveVaultOperator.sol:123

  • YearnCurveVaultOperator.sol:164

  • YearnCurveVaultOperator.sol:167

  • YearnCurveVaultOperator.sol:212

  • YearnCurveVaultOperator.sol:215

  • YearnCurveVaultOperator.sol:260

  • YearnCurveVaultOperator.sol:263

  • Withdrawer.sol:21

  • OwnerProxy.sol:17

  • NestedFactory.sol:74

  • NestedFactory.sol:99

  • NestedFactory.sol:107

  • NestedFactory.sol:122

  • NestedFactory.sol:125

  • NestedFactory.sol:153

  • NestedFactory.sol:160

  • NestedFactory.sol:161

  • NestedFactory.sol:168

  • NestedFactory.sol:169

  • NestedFactory.sol:191

  • NestedFactory.sol:250

  • NestedFactory.sol:251

  • NestedFactory.sol:252

  • NestedFactory.sol:286

  • NestedFactory.sol:288

  • NestedFactory.sol:289

  • NestedFactory.sol:312

  • NestedFactory.sol:313

  • NestedFactory.sol:330

  • NestedFactory.sol:331

  • NestedFactory.sol:359

  • NestedFactory.sol:379

  • NestedFactory.sol:406

  • NestedFactory.sol:407

  • NestedFactory.sol:428

  • NestedFactory.sol:469

  • NestedFactory.sol:495

  • NestedFactory.sol:543

  • NestedFactory.sol:544

  • NestedFactory.sol:553

  • NestedFactory.sol:612

  • NestedFactory.sol:656

  • StakingLPVaultHelpers.sol:108

  • StakingLPVaultHelpers.sol:138

  • TimelockControllerEmergency.sol:229

  • TimelockControllerEmergency.sol:230

  • TimelockControllerEmergency.sol:243

  • TimelockControllerEmergency.sol:244

  • TimelockControllerEmergency.sol:256

  • TimelockControllerEmergency.sol:319

  • TimelockControllerEmergency.sol:320

  • TimelockControllerEmergency.sol:334

  • TimelockControllerEmergency.sol:335

  • TimelockControllerEmergency.sol:342

  • TimelockControllerEmergency.sol:359

  • TimelockControllerEmergency.sol:375

  • MixinOperatorResolver.sol:23

  • MixinOperatorResolver.sol:103

  • MixinOperatorResolver.sol:104

  • BeefyVaultStorage.sol:25

  • BeefyVaultStorage.sol:26

  • BeefyVaultStorage.sol:27

  • BeefyVaultStorage.sol:35

  • BeefyZapBiswapLPVaultOperator.sol:23

  • BeefyZapBiswapLPVaultOperator.sol:52

  • BeefyZapBiswapLPVaultOperator.sol:54

  • BeefyZapBiswapLPVaultOperator.sol:64

  • BeefyZapBiswapLPVaultOperator.sol:65

  • BeefyZapBiswapLPVaultOperator.sol:97

  • BeefyZapBiswapLPVaultOperator.sol:99

  • BeefyZapBiswapLPVaultOperator.sol:108

  • BeefyZapBiswapLPVaultOperator.sol:109

  • BeefyZapBiswapLPVaultOperator.sol:142

  • BeefyZapBiswapLPVaultOperator.sol:187

  • BeefyZapBiswapLPVaultOperator.sol:198

  • BeefyZapBiswapLPVaultOperator.sol:271

  • BeefyZapBiswapLPVaultOperator.sol:272

  • OperatorScripts.sol:19

  • OperatorScripts.sol:20

  • OperatorScripts.sol:29

  • OperatorScripts.sol:54

  • OperatorScripts.sol:55

  • OperatorScripts.sol:61

  • ParaswapOperator.sol:16

  • ParaswapOperator.sol:27

  • ParaswapOperator.sol:35

  • ParaswapOperator.sol:39

  • ParaswapOperator.sol:40

  • OwnableProxyDelegation.sol:25

  • OwnableProxyDelegation.sol:26

  • OwnableProxyDelegation.sol:27

  • OwnableProxyDelegation.sol:41

  • OwnableProxyDelegation.sol:57

  • OperatorResolver.sol:39

  • OperatorResolver.sol:57


Right shift instead of dividing by two

contract GasTest is DSTest {
    Contract0 c0;
    Contract1 c1;

    function setUp() public {
        c0 = new Contract0();
        c1 = new Contract1();
    }

    function testGas() public view {
        c0.div2();
        c1.shr2();
    }
}

contract Contract0 {
    function div2() public view {
        uint256 val = 10;
        uint256 valDivTwo = val / 2;
        valDivTwo++;
    }
}

contract Contract1 {
    function shr2() public view {
        uint256 val = 10;
        uint256 valDivTwo = val >> 1;
        valDivTwo++;
    }
}

Gas Report

╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract0 contract                                             
╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost     Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 41493               238                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 div2                268              268  268     268  1       
╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯
╭────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮
 Contract1 contract                                             
╞════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡
 Deployment Cost     Deployment Size                            
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 32687               193                                        
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg  median  max  # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 shr2                203              203  203     203  1       
╰────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯

Lines

  • BeefyZapUniswapLPVaultOperator.sol:273

  • BeefyZapBiswapLPVaultOperator.sol:275


Use assembly to write storage values

contract GasTest is DSTest {
    Contract0 c0;
    Contract1 c1;

    function setUp() public {
        c0 = new Contract0();
        c1 = new Contract1();
    }

    function testGas() public {
        c0.updateOwner(0x158B28A1b1CB1BE12C6bD8f5a646a0e3B2024734);
        c1.assemblyUpdateOwner(0x158B28A1b1CB1BE12C6bD8f5a646a0e3B2024734);
    }
}

contract Contract0 {
    address owner = 0xb4c79daB8f259C7Aee6E5b2Aa729821864227e84;

    function updateOwner(address newOwner) public {
        owner = newOwner;
    }
}

contract Contract1 {
    address owner = 0xb4c79daB8f259C7Aee6E5b2Aa729821864227e84;

    function assemblyUpdateOwner(address newOwner) public {
        assembly {
            sstore(owner.slot, newOwner)
        }
    }
}

Gas Report

╭────────────────────┬─────────────────┬──────┬────────┬──────┬─────────╮
 Contract0 contract                                               
╞════════════════════╪═════════════════╪══════╪════════╪══════╪═════════╡
 Deployment Cost     Deployment Size                              
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 60623               261                                          
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg   median  max   # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 updateOwner         5302             5302  5302    5302  1       
╰────────────────────┴─────────────────┴──────┴────────┴──────┴─────────╯
╭────────────────────┬─────────────────┬──────┬────────┬──────┬─────────╮
 Contract1 contract                                               
╞════════════════════╪═════════════════╪══════╪════════╪══════╪═════════╡
 Deployment Cost     Deployment Size                              
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 54823               232                                          
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 Function Name       min              avg   median  max   # calls 
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
 assemblyUpdateOwner┆ 5236             5236  5236    5236  1       
╰────────────────────┴─────────────────┴──────┴────────┴──────┴─────────╯

Lines

  • YearnCurveVaultOperator.sol:48

  • NestedFactory.sol:162

  • NestedFactory.sol:170

  • TimelockControllerEmergency.sol:93

  • TimelockControllerEmergency.sol:377

  • OperatorScripts.sol:21

  • OperatorScripts.sol:22

  • ParaswapOperator.sol:17

  • ParaswapOperator.sol:18

  • OwnableProxyDelegation.sol:31

  • OwnableProxyDelegation.sol:65


@code423n4 code423n4 added bug Something isn't working G (Gas Optimization) labels Jun 18, 2022
code423n4 added a commit that referenced this issue Jun 18, 2022
@obatirou obatirou self-assigned this Jun 21, 2022
@obatirou
Copy link
Collaborator

Use assembly to check for address(0) (disputed)

Solidity audit
We do not want to do it
Would reduce readability

Use assembly when getting a contract's balance of ETH. (disputed)

Solidity audit
We do not want to do it
Would reduce readability

Use assembly to hash instead of Solidity (disputed)

Solidity audit
We do not want to do it
Would reduce readability

Use assembly for math (add, sub, mul, div) (disputed)

Solidity audit
We do not want to do it
Would reduce readability

Use assembly to write storage values (disputed)

Solidity audit
We do not want to do it
Would reduce readability

@Yashiru
Copy link
Collaborator

Yashiru commented Jun 24, 2022

Right shift instead of dividing by two (Duplicated)

Duplicated of #89 at Use Shift Right/Left instead of Division/Multiplication

@maximebrugel
Copy link
Collaborator

Use custom errors instead of string error messages (Duplicated)

#6 (see comment)

@Yashiru
Copy link
Collaborator

Yashiru commented Jun 24, 2022

unchecked{++i} instead of i++ (or use assembly when applicable (Duplicated)

Duplicated of #2 at For loop optimizaion

@obatirou
Copy link
Collaborator

Use multiple require() statments insted of require(expression && expression && ...) (duplicate).

#29 (comment)

@Yashiru Yashiru added the duplicate This issue or pull request already exists label Jun 27, 2022
@JeeberC4 JeeberC4 removed the duplicate This issue or pull request already exists label Jul 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants