# 为什么bool比uint256消耗更多的gas

By [Canvie.crypto](https://paragraph.com/@canvie-crypto) · 2025-07-12

---

之前遇到有朋友这么问：“为什么bool比uint256消耗更多的gas”。首先要说明的是这个说法是不准确的，并不是简单的bool和uint256这个类型差异造成的。我们在看OpenZeppelin的**ReentrancyGuard.sol**的源码时，会看到下面的写法，我们从底层机制上分析

    // 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.
    //.....
        uint256 private constant NOT_ENTERED = 1;
        uint256 private constant ENTERED = 2;
    

  
一. 首先，slot存储槽基本最小长度是256bit，EVM每次会按照整个slot进行读取，这个可以在instructions.go中找到“opSload”方法。

[https://github.com/ethereum/go-ethereum/blob/master/core/vm/instructions.go](https://github.com/ethereum/go-ethereum/blob/master/core/vm/instructions.go)

    val := interpreter.evm.StateDB.GetState(scope.Contract.Address(), hash)
    // 此处就是从slot中获取值，并不会判断变量的类型，直接返回整个32字节的内容
    

二. bool是1bit，如果是连续定义多个bool变量，编译器会把多个bool变量打包进同一个slot，用offset来定义每个变量的在slot中的位置。我们可以编译一段代码

    contract Test {
        bool a;
        bool b;
        uint8 f;
        uint256 c;
        bool d;
        uint256 e;
    
        function getA() public view returns (bool){
          return a;
        }
    
        function setA(bool _a) public {
          a = _a;
        }
    
        function getC() public view returns (uint256) {
            return c;
        }
    
        function setC(uint256 _c) public {
            c = _c;
        }
    
        function getD() public view returns (bool) {
            return d;
        }
    
        function setD(bool _d) public {
            d = _d;
        }
    }
    

  
在“Solidity Compile Details”中可以看到”STORAGELAYOUT”

    {
        "storage": [
            {
                "astId": 3,
                "contract": "Test.sol:Test",
                "label": "a",
                "offset": 0,
                "slot": "0",
                "type": "t_bool"
            },
            {
                "astId": 5,
                "contract": "Test.sol:Test",
                "label": "b",
                "offset": 1,
                "slot": "0",
                "type": "t_bool"
            },
            {
                "astId": 7,
                "contract": "Test.sol:Test",
                "label": "f",
                "offset": 2,
                "slot": "0",
                "type": "t_uint8"
            },
            {
                "astId": 9,
                "contract": "Test.sol:Test",
                "label": "c",
                "offset": 0,
                "slot": "1",
                "type": "t_uint256"
            },
            {
                "astId": 11,
                "contract": "Test.sol:Test",
                "label": "d",
                "offset": 0,
                "slot": "2",
                "type": "t_bool"
            },
            {
                "astId": 13,
                "contract": "Test.sol:Test",
                "label": "e",
                "offset": 0,
                "slot": "3",
                "type": "t_uint256"
            }
        ],
        "types": {
            "t_bool": {
                "encoding": "inplace",
                "label": "bool",
                "numberOfBytes": "1"
            },
            "t_uint256": {
                "encoding": "inplace",
                "label": "uint256",
                "numberOfBytes": "32"
            },
            "t_uint8": {
                "encoding": "inplace",
                "label": "uint8",
                "numberOfBytes": "1"
            }
        }
    }
    

  
我们可以看到a，b，f 所在slot的编号都是0，由此可以知道都被打包进了一个slot。但是d又是独占slot2。这里有个编译规则，如果是多个变量挤压在同一个slot中，则写的过程是SLOAD-SSTORE，如是变量独占一个slot，则写的过程就是SSTORE。前一个操作多了一个SLOAD，因此gas消费更多。

由此可以总结出

*   **多个小变量打包进同一个 slot（如多个 bool、uint8、uint16），“单独写入”某个变量时，必须先 SLOAD slot（读出旧值）、在内存中修改对应 bit/byte、再 SSTORE（整体写回 slot）。**
    
*   **如果变量独占一个 slot（如 uint256、单独的 bool），写操作通常可以直接 SSTORE，不需要预读。**
    

这个在初学的时候是非常容易混淆和不好理解的概念。

---

*Originally published on [Canvie.crypto](https://paragraph.com/@canvie-crypto/bool-uint256-gas)*
