使用unchecked有什么好处?
What is the benefit of using uncheked?
在OpenZeppelin ERC20实现中,有一个_transfer方法:
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
_afterTokenTransfer(sender, recipient, amount);
}
为什么他们使用无校验算法来减少余额?我知道在未选中的情况下,2-3 将 return 2**256-1 而不是异常。但是为什么我们需要这个?
unchecked
与常规算术运算相比生成更小的字节码,因为它不包含 underflow/overflow 验证。
因此,如果您想在发生溢出时自定义错误消息,则此代码比 运行
消耗更少的 gas
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
// no validation here as it's already validated in the `require()` condition
_balances[sender] = senderBalance - amount;
}
与这个相比
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
// redundant validation here
_balances[sender] = senderBalance - amount;
如果没有自定义消息,这将是最便宜但仍然安全的选项:
// contains the check and fails without custom message in case of underflow
_balances[sender] -= amount;
与上一个相比,这个会更便宜。但它不安全,因为它不检查下流:
unchecked {
// UNSAFE, DO NOT USE
_balances[sender] -= amount;
}
在OpenZeppelin ERC20实现中,有一个_transfer方法:
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
_afterTokenTransfer(sender, recipient, amount);
}
为什么他们使用无校验算法来减少余额?我知道在未选中的情况下,2-3 将 return 2**256-1 而不是异常。但是为什么我们需要这个?
unchecked
与常规算术运算相比生成更小的字节码,因为它不包含 underflow/overflow 验证。
因此,如果您想在发生溢出时自定义错误消息,则此代码比 运行
消耗更少的 gasuint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
// no validation here as it's already validated in the `require()` condition
_balances[sender] = senderBalance - amount;
}
与这个相比
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
// redundant validation here
_balances[sender] = senderBalance - amount;
如果没有自定义消息,这将是最便宜但仍然安全的选项:
// contains the check and fails without custom message in case of underflow
_balances[sender] -= amount;
与上一个相比,这个会更便宜。但它不安全,因为它不检查下流:
unchecked {
// UNSAFE, DO NOT USE
_balances[sender] -= amount;
}