gas-optimizations icon indicating copy to clipboard operation
gas-optimizations copied to clipboard

Conditional statement "!=" is not more gas efficient than ">" or ">="

Open PaulRBerg opened this issue 2 years ago • 9 comments

Alleged Gas Costs

At the time of opening the issue, the Optimal Comparison Operator document makes the following claim:

In the case of a conditional statement, it is further optimal to use != when possible.

And then, the following gas costs are provided:

// 164 gas
function d() external pure {
  require(1 > 0);
}

// 208 gas
function e() external pure {
  require(1 >= 0);
}

// 120 gas
function f() external pure {
  require(1 != 0);
}

Actual Gas Costs

In the first example below, each function execution will consume exactly 21,162 gas (with the function compare per se consuming exactly 98 gas).

Try these on Remix with the optimizer enabled and set to 200 runs

1. Require example
pragma solidity =0.8.17;

contract A {
    function compare() external pure {
        require(1 > 0);
    }
}

contract B {
    function compare() external pure {
        require(1 >= 0);
    }
}

contract C {
    function compare() external pure {
        require(1 != 0);
    }
}
2. If/ else example

And in this case, the reported gasUsed will be 7.

pragma solidity =0.8.17;

contract A {
    function compare(uint256 x) external view returns (uint256 gasUsed) {
        uint256 startGas = gasleft();
        if (x >= 0) {
            uint256 foo = 1 + 2;
            foo;
        }
        gasUsed = startGas - gasleft();
    }
}

contract B {
    function compare(uint256 x) external view returns (uint256 gasUsed) {
        uint256 startGas = gasleft();
        if (x > 0) {
            uint256 foo = 1 + 2;
            foo;
        }
        gasUsed = startGas - gasleft();
    }
}

contract C {
    function compare(uint256 x) external view returns (uint256 gasUsed) {
        uint256 startGas = gasleft();
        if (x != 0) {
            uint256 foo = 1 + 2;
            foo;
        }
        gasUsed = startGas - gasleft();
    }
}

Possible Explanations

Let's start with this is what definitely isn't - this is not a matter of enabling the optimizer. Even with the optimizer disabled, the > 0 and != 0 checks cost the same in Solidity v0.8.17. That leaves with a couple of options left:

  1. You defined all functions in the same contract, which made the 4-byte function signature add extra gas, depending upon the results of the keccak256 hsah.
  2. Older compiler had different gas costs for these comparison operations? Unlikely, but possible.
  3. Some other unintentional benchmarking/ instrumenting mistake.

Whatever the case, as discussed in https://github.com/kadenzipfel/gas-optimizations/issues/3 and https://github.com/kadenzipfel/gas-optimizations/issues/15, the best way to avoid situations like this in the future would be to document the methodology that you used to obtain the reported gas costs, so that others can repeat your process and catch mistakes more easily.

PaulRBerg avatar Nov 28 '22 12:11 PaulRBerg