Skip to content

Instantly share code, notes, and snippets.

@GalloDaSballo
Last active February 4, 2023 09:35
Show Gist options
  • Save GalloDaSballo/8521d2cb6dcc4eea5523a06957f0ea15 to your computer and use it in GitHub Desktop.
Save GalloDaSballo/8521d2cb6dcc4eea5523a06957f0ea15 to your computer and use it in GitHub Desktop.

I was asked to recompute the savings for various findings, boasting 100+ gas per +=

This is factually incorrect, using += will save 13 gas (for some reason), when

// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;

import "../../lib/test.sol";
import "../../lib/Console.sol";

contract GasTest is DSTest {
    Adder c0;
    AdderWithCache c1;
    AdderWithUnchecked c2;
    AdderWithUncheckedCache c3;

    function setUp() public {
        c0 = new Adder();
        c1 = new AdderWithCache();
        c2 = new AdderWithUnchecked();
        c3 = new AdderWithUncheckedCache();
    }

    function testGas() public {
        c0.addValue(123);
        c1.addValue(123);
        c2.addValue(123);
        c3.addValue(123);
    }
}

contract Adder {
    uint256 value = 123;
    function addValue(uint256 input) external returns (uint256) {
        return value += input;
    }
}

contract AdderWithCache {
    uint256 value = 123;
    function addValue(uint256 input) external returns (uint256) {
        return value = value + input;
    }
}

contract AdderWithUnchecked {
    uint256 value = 123;
    function addValue(uint256 input) external returns (uint256) {
        unchecked {
            return value += input;
        }
    }
}

contract AdderWithUncheckedCache {
    uint256 value = 123;
    function addValue(uint256 input) external returns (uint256) {
        unchecked {
            return value = value + input;
        }
    }
}

The finding saves at most 13 gas per instance, but won't save gas if used with unchecked

[PASS] testGas() (gas: 41203)
Test result: ok. 1 passed; 0 failed; finished in 905.07µs
| src/test/GasTest.t.sol:Adder contract |                 |      |        |      |         |
|---------------------------------------|-----------------|------|--------|------|---------|
| Deployment Cost                       | Deployment Size |      |        |      |         |
| 71805                                 | 284             |      |        |      |         |
| Function Name                         | min             | avg  | median | max  | # calls |
| addValue                              | 5360            | 5360 | 5360   | 5360 | 1       |


| src/test/GasTest.t.sol:AdderWithCache contract |                 |      |        |      |         |
|------------------------------------------------|-----------------|------|--------|------|---------|
| Deployment Cost                                | Deployment Size |      |        |      |         |
| 71005                                          | 280             |      |        |      |         |
| Function Name                                  | min             | avg  | median | max  | # calls |
| addValue                                       | 5347            | 5347 | 5347   | 5347 | 1       |


| src/test/GasTest.t.sol:AdderWithUnchecked contract |                 |      |        |      |         |
|----------------------------------------------------|-----------------|------|--------|------|---------|
| Deployment Cost                                    | Deployment Size |      |        |      |         |
| 55393                                              | 201             |      |        |      |         |
| Function Name                                      | min             | avg  | median | max  | # calls |
| addValue                                           | 5259            | 5259 | 5259   | 5259 | 1       |


| src/test/GasTest.t.sol:AdderWithUncheckedCache contract |                 |      |        |      |         |
|---------------------------------------------------------|-----------------|------|--------|------|---------|
| Deployment Cost                                         | Deployment Size |      |        |      |         |
| 55393                                                   | 201             |      |        |      |         |
| Function Name                                           | min             | avg  | median | max  | # calls |
| addValue                                                | 5259            | 5259 | 5259   | 5259 | 1       |

For this specific finding optimizer doesn't matter (try for yourself)

I've used the excellent starter repo: https://github.com/0xKitsune/gas-lab

@IllIllI000
Copy link

IllIllI000 commented Feb 4, 2023

When I flag this issue, I always link to my gist and it shows the byte code differences, and there's an extra sload. You can check in remix too with the following:

// SPDX-License-Identifier: MIT
pragma solidity 0.8.7; // optimize 200

contract StateVarPlusEqVsEqPlus1 {
    uint256 varr = 1;

    function test() external returns (uint256) {
        varr += block.number; // 26439 gas 
        return varr;
    }
}

contract StateVarPlusEqVsEqPlus2 {
    uint256 varr = 1;

    function test() external returns (uint256) {
        varr = varr + block.number; // 26326 gas 
        return varr;
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment