Solidity Gas Optimization: Stop Using Bools for True/False Values

Follow the author on Twitter for more crypto

Alex Otsu
2 min readMar 9, 2023

When you want to store a true/false value, the first instinct is naturally to store it as a boolean. However, because the EVM stores boolean values as a uint8 type, which takes up two bytes, it is actually more expensive to access the value. This is because it EVM words are 32 bytes long, so extra logic is needed to tell the VM to parse a value that is smaller than standard.

The next instinct is to store false as uint256(0), and true as uint256(1). That, it turns out, incurs significant gas costs as well because there is a fixed fee associated with flipping a zero value to something else.

The most efficient way to store true/false values, then, is to use 1 for false and 2 for true.

OpenZeppelin describes it in their ReentrancyGuard contract:

Booleans are more expensive than uint256 or any type that takes up a full word because each write operation emits an extra SLOAD to first read the slot’s contents, replace the bits taken up by the boolean, and then write back. This is the compiler’s defense against contract upgrades and pointer aliasing, and it cannot be disabled.

The values being non-zero value makes deployment a bit more expensive, but in exchange the refund on every call to nonReentrant will be lower inamount. Since refunds are capped to a percentage of the total transaction’s gas, it is best to keep them low in cases like this one, to increase the likelihood of the full refund coming into effect.

Let’s test these ideas out to see how drastic the gas savings are. As usual, the code is available in GitHub.

Comparison of various read and write operations.

Note that the reset{type} functions set a true value back to false, represented as false for boolean tests and 1 for uint tests.

The “min” value for storeUint was from flipping a 1 value to a 2. But because Solidity initializes uint values as 0, it is actually more expensive to flip the 0 to a non-zero value in the first place; that operation accounts for the “max” value for storeUint. But if you have a boolean that will only ever be flipped once from true to false, while it is slightly more efficient to use the bool type for writing the value, any gas savings will be negated the first time a contract has to read the value.

--

--