Gas优化方法实例
待优化代码
测试流程 部署合约 执行函数 [1, 2, 3, 4, 5, 100]
优化思路
1、减少冗余代码
2、优化参数、缓存可以缓存的参数
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; contract GasGolf { uint public total; // [1, 2, 3, 4, 5, 100] function sumIfEvenAndLessThan99(uint[] memory nums) external { for (uint i = 0; i < nums.length; i += 1) { bool isEven = nums[i] % 2 == 0; bool isLessThan99 = nums[i] < 99; if (isEven && isLessThan99) { total += nums[i]; } } } }
1、calldata
必须用于外部函数的动态参数。
只能用于函数声明参数,不能用于函数逻辑声明。
是不可变的,不能被覆盖和更改。
function sumIfEvenAndLessThan99(uint[] calldata nums) external 将memory替换为calldata
2、改变状态变量为在内存中
contract GasGolf { uint public total; function sumIfEvenAndLessThan99(uint[] calldata nums) external { uint _total = total; for (uint i = 0; i < nums.length; i += 1) { bool isEven = nums[i] % 2 == 0; bool isLessThan99 = nums[i] < 99; if (isEven && isLessThan99) { _total += nums[i]; } } total = _total; } }
3、布尔值优化短路
if (nums[i] % 2 == 0 && nums[i] < 99) { _total += nums[i]; }
4、for换成++i
for (uint i = 0; i < len; ++i)
5、数组长度缓存、数组下标缓存
uint len = nums.length; for (uint i = 0; i < len; ++i) { uint num = nums[i]; if (num % 2 == 0 && num < 99) { _total += num; } }
优化完成的代码
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; contract GasGolf { // 看 execution cost GAS消耗 // 初始状态 - 50908 GAS // calldata替换 - 49163 GAS 节省1745 // 改变状态变量为在内存中 - 48952 GAS 节省211 // 布尔值优化短路 - 48634 GAS 节省318 // for换成++i - 48226 GAS 节省408 // 数组长度缓存 - 48191 GAS 节省35 // 数组下标缓存 - 48029 GAS 节省362 uint public total; // [1, 2, 3, 4, 5, 100] function sumIfEvenAndLessThan99(uint[] calldata nums) external { uint _total = total; uint len = nums.length; for (uint i = 0; i < len; ++i) { uint num = nums[i]; if (num % 2 == 0 && num < 99) { _total += num; } } total = _total; } }