Using assembly to revert with an error message
在智能合约中优化 Gas 使用时,使用汇编语言来实现 revert 语句可以节省 Gas。 While Solidity's require
and revert
statements are convenient, implementing the same functionality with assembly can be more gas-efficient.
Solidity 在使用标准 revert 语句时,会因内存扩展和类型检查而产生额外的 Gas 消耗。 而通过使用汇编语言,我们可以绕过这些额外的开销,同时保持相同的功能。
Gas比较示例
下面是两种方法的比较示例:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SolidityRevert {
address owner;
uint256 specialNumber = 1;
constructor() {
owner = msg.sender;
}
function restrictedAction(uint256 num) external {
require(owner == msg.sender, "caller is not owner");
specialNumber = num;
}
}
contract AssemblyRevert {
address owner;
uint256 specialNumber = 1;
constructor() {
owner = msg.sender;
}
function restrictedAction(uint256 num) external {
assembly {
if sub(caller(), sload(owner.slot)) {
// Store offset to error message length
mstore(0x00, 0x20)
// Store length of error message
mstore(0x20, 0x13)
// Store the error message
mstore(0x40, 0x63616c6c6572206973206e6f74206f776e657200000000000000000000000000)
// Revert with data (offset, size)
revert(0x00, 0x60)
}
}
specialNumber = num;
}
}