更新说明:本章节列出了在新版本 Solidity、EVM 升级或生态系统变化后不再有效或重要性大幅降低的优化技巧。
过时原因: 编译器优化改进
如果函数无法在合约内部调用,为了清晰起见,仍然应该优先选择 external 修饰符,但它对于节省 gas 没有影响。
时间线: 约 Solidity 0.8.x 之后效果不明显
过时原因: 编译器优化改进
大约在 Solidity 0.8.12 左右,这个说法不再成立。如果你被迫使用旧版本,你仍然可以对其进行基准测试。
时间线: Solidity 0.8.12+
⚠️ 重要: 这是 Cancun 升级影响最大的变更之一!
过时原因: EIP-6780 限制了 SELFDESTRUCT 的行为
在 Cancun 升级(2024年3月)之后,SELFDESTRUCT 仅在以下情况保留完整功能:
对于已存在的合约调用 SELFDESTRUCT:
// ❌ 不再有效:跨交易销毁
contract OldPattern {
function cleanup() external {
selfdestruct(payable(msg.sender));
// 代码和存储不会被删除!
}
}
// ❌ 不再有效:CREATE2 + SELFDESTRUCT 重新部署
contract RedeployPattern {
function redeploy(bytes32 salt) external {
address deployed = address(new Contract{salt: salt}());
Contract(deployed).destroy();
// 无法在同一地址重新部署
}
}
参考:
时间线: Cancun 升级(2024年3月)后
⚠️ 重要: EIP-4844 对 L2 的 calldata 优化策略产生革命性影响!
过时原因: EIP-4844 引入的 Blob 交易改变了 L2 的数据发布机制
在 EIP-4844 之前,L2 需要将所有交易数据作为 calldata 发布到 L1:
在 EIP-4844 之后,L2 主要使用 Blob 交易发布数据:
// ⚠️ 在 L2 上重要性大幅降低
contract CalldataOptimization {
// 使用虚荣地址(前导零)
address public constant TOKEN = 0x0000000000000000000000000000000000000001;
// 压缩地址到 uint160
function compress(address addr) external pure returns (uint160) {
return uint160(addr);
}
// 使用短函数名
function t() external {} // 而不是 transfer()
}
高优先级:
低优先级:
参考: Chapter 5 完整分析
时间线: Cancun 升级(2024年3月)后
过时原因: 编译器自动优化改进
随着 Solidity 编译器的不断改进(0.8.20 → 0.8.28),某些手动优化已被编译器自动应用:
// 编译器现在自动使用 PUSH0
function getZero() public pure returns (uint256) {
return 0; // 自动使用 PUSH0 操作码
}
影响: 无需手动优化零值初始化
// 编译器可能自动识别安全的循环
for (uint256 i = 0; i < arr.length; i++) {
// 某些情况下编译器会自动优化
}
影响: 但仍建议显式使用 unchecked { ++i }
// 编译器可能自动优化为位移
uint256 x = y * 2; // 可能优化为 y << 1
uint256 z = y / 4; // 可能优化为 y >> 2
影响: 对于 2 的幂次乘除法,编译器可能自动优化
时间线: Solidity 0.8.20+ 逐步改进
过时原因: 临时存储(Transient Storage)提供了更好的方案
SSTORE2(传统方案):
临时存储(EIP-1153):
// ❌ 使用 SSTORE2 存储临时数据(不再推荐)
contract OldApproach {
mapping(uint256 => address) tempDataPointers;
function processBatch(bytes[] calldata items) external {
// 将临时数据存储到 SSTORE2
address pointer = SSTORE2.write(abi.encode(items));
tempDataPointers[block.number] = pointer;
// 处理...
// 需要手动清理
}
}
// ✅ 使用临时存储(推荐)
contract NewApproach {
mapping(uint256 => bytes) private transient tempData;
function processBatch(bytes[] calldata items) external {
for (uint256 i = 0; i < items.length; i++) {
tempData[i] = items[i]; // TSTORE: 100 gas
}
// 处理...
// 交易结束后自动清零,无需手动清理
}
}
参考:
时间线: Cancun 升级(2024年3月)后
编译器改进导致:
EVM 升级导致: