跳到主要内容

位图和位运算

在区块链上存储数据的成本极高。 很多项目创新性地使用了一些巧妙的方法来降低gas费用。 我们今天将会讨论那些常见于龙头项目的源代码中的方法。

对于一个 uint8 类型数据,用二进制表示为 00000000,其中每个位可以是 01。 默认情况下,1 被视为真,0 被视为假。 这种策略允许通过位运算高效且低成本地管理布尔值。

在Solidity中,1 << n 代表一个位移操作,将数字 1 向左移动 n 位,右侧空出的位用 0 填充。 例如,如果 n2,则 1 << 2 的结果是 100

代码演示

以下演示了使用布尔数组和位运算管理同一数据的方法。

contract Bitmap {
bool[8] boolArrayImplementation;
uint8 bitmapImplementation;

function setBoolArrayData(bool[8] memory data) external {
boolArrayImplementation = data;
}

function setBitmapData(uint8 data) external {
bitmapImplementation = data;
}

// gas:35729
function readBoolArray(uint8 index) external returns (bool) {
return boolArrayImplementation[index];
}

// gas:22366
function readBitmap(uint indexFromRight) external returns (bool) {
uint256 bitAtIndex = bitmapImplementation & (1 << indexFromRight);
return bitAtIndex > 0;
}
}

readBitmap 函数中, & 执行了 bitmapImplementation(1 << indexFromRight) 每一位上的 AND 操作。 只有当该位置的两个位都为 1 时,结果位才为 1 ,否则为 0。 这种操作通常用于检查特定位是否被设置为 1

Gas优化建议:

🌟考虑到实际情况,可以使用位运算符来管理特定变量以节省gas。