把节约gas的几个方法测试了下,蛮有效的。以前看起来有些多余的操作其实是另有深意啊。比如常见的语句uint _arr = arr[i]
,直接写arr[i]
不是更直观么,为什么非要定义一个变量呢?!现在终于揭晓了谜团:原来是为了节约gas啊!
案例集 中把这些方法都总结了,我也测试了下,还是很实用嘀!
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// gas golf
contract GasGolf {
// start 56530 gas
//public -> external 最小化权限 56530 gas
//变量memory -> calldata 54104 gas
//多个条件变短 53816 gas
// total -> _total 加载状态变量到内存变量 52291 gas
// nums.length -> len 数组长度缓存到内存 52232 gas
// nums[i] -> num 缓存多次使用的数组元素到内存 51581 gas
//i+=1 -> ++i 51023 gas
uint public total;
// start - not gas optimized [2, 10, 30, 55, 56, 62, 52, 2, 16]
function sum1(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];
}
}
}
// gas optimized
function sum2(uint[] calldata nums) external {
uint _total = total;
uint len = nums.length;
for (uint i = 0; i < len; ) {
uint num = nums[i];
if (num % 2 == 0 && num < 99) {
_total += num;
}
unchecked {
++i;
}
}
total = _total;
}
}
测试合约如上,大家也可以尝试着去做。节约gas的方法可以总结如下:
- 最小化权限控制,尽量用
external, private, internal, 尽量不用public
- 变量类型优先使用
calldata
而不是memory
- 加载状态变量到内存变量
- 多个条件判断使用短路方式
- 在循环中使用
++i,而不是i+=1, i++
- 数组长度缓存到内存
- 缓存多次使用的数组元素到内存