gas优化:改进for循环[0.8.22已内置]

在我们用solidity的for循环时,大概是这样用的:

for (uint256 i = 0; i < length; ++i) {
        ...
}

其实在新版本的solidity中,由于uint类型在进行运算时会自动检测溢出,所以在for循环中,有一个改进的写法:

for (uint256 i = 0; i < length; ) {
        ...
        unchecked {
            ++i
        }
}

就是将++i从for循环表达式中移除,然后在循环体末尾加上unchecked关键词然后写上++i。因为for循环中已经有了i < length这个数值范围检测,所以没有必要每次都做溢出检测。这样会节约很多gas,我们将通过一个例子来说明:

// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.10;

contract Test {
    uint256[] arr = [1, 2, 3, 4, 5, 6, 7];
    uint256[] arrCopy;

    constructor() {
        arrCopy = new uint256[](arr.length);
    }

    function getArrCopy() external view returns(uint256[] memory) {
        return arrCopy;
    }

    function unset() external {
        arrCopy = new uint256[](arr.length);
    }

    function origin() external {
        uint256 length = arr.length;
        arrCopy = new uint256[](length);
        for (uint256 i = 0; i < length; ++i) {
            arrCopy[i] = arr[i];
        }
    }

    function optimize() external {
        uint256 length = arr.length;
        arrCopy = new uint256[](length);
        for (uint256 i = 0; i < length; ) {
            arrCopy[i] = arr[i];
            unchecked {
                ++i;
            }
        }
    }
}

这个合约就是将arr中的值拷贝到arrCopy中来。然后origin方法就是用最普通的for循环来写入,optimize就是用改进后用unchecked关键词的for循环来写入。gas消耗如下:

函数 写入类型 gas消耗量
origin 普通for循环 230502
optimize uncheked形式for循环 229511

节约了比较细微的gas量。
这里的数组长度只有7,所以结果上可能不太明显;如果数组长度够长的话,应该能节约更多的gas。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容