unchecked
在 Solidity 0.8.0 及以上版本中,引入了一个新的关键字 unchecked
。在 unchecked
块中,算术运算将不会进行溢出检查,这意味着如果结果超过了类型的最大值,它将回滚到类型的最小值,反之亦然。
这是一个使用 unchecked
的例子:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
contract UncheckedExample {
function add(uint256 x, uint256 y) external pure returns (uint256) {
// gas: 949
return x + y;
// // gas: 770
// unchecked {
// return x + y;
// }
}
function overflow() public pure returns (uint256) {
uint256 max = type(uint256).max;
// gas: 329
// 1
unchecked {
return max + 2;
}
}
function underflow() public pure returns (uint256) {
uint256 min = type(uint256).min;
// gas: 372
// 115792089237316195423570985008687907853269984665640564039457584007913129639935
unchecked {
return min - 1;
}
}
}
在这个例子中,overflow
函数返回的结果将是 0,因为 uint
类型的最大值加 1 将回滚到 0。同样,underflow
函数返回的结果将是 uint
类型的最大值,因为 uint
类型的最小值减 1 将回滚到 uint
类型的最大值。
需要注意的是,unchecked
关键字只影响其块内的算术运算。在 unchecked
块外的算术运算仍然会进行溢出检查。因此,你应该只在你确定溢出不会导致问题的情况下使用 unchecked
块。
此外,unchecked
块也可以嵌套。在嵌套的 unchecked
块中,算术运算仍然不会进行溢出检查。
assembly
在Solidity中,assembly
关键字用于引入一段内联汇编代码。内联汇编可以让你直接编写EVM(以太坊虚拟机)的汇编语言代码,这可以让你实现一些Solidity本身不支持的底层操作,或者优化你的代码以减少gas消耗。
以下是一个使用assembly
关键字的例子:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
contract AssemblyExampl {
function assemblyExample() public pure returns (uint256 _ret) {
assembly {
_ret := add(1, 2)
}
}
}
在这个例子中,我们使用内联汇编来计算1+2的结果。add
是EVM的一个汇编指令,它从栈顶取出两个元素,将它们相加,然后将结果放回栈顶。
使用assembly
关键字,你可以直接编写EVM(以太坊虚拟机)的汇编语言代码,这可以让你实现一些Solidity本身不支持的底层操作。以下是一些例子:
- 直接访问存储:在Solidity中,你不能直接访问存储的特定位置。但在汇编中,你可以使用
sload
和sstore
指令来直接读写存储。 - 更低级别的跳转:Solidity的控制流语句(如
if
,for
等)在编译后会转换为EVM的跳转指令。在汇编中,你可以直接使用这些跳转指令,实现更复杂的控制流。 - 访问特定的系统操作码:EVM有一些系统操作码,如
gas
,blockhash
,difficulty
等,这些在Solidity中无法直接访问,但在汇编中可以。 - 优化代码以减少gas消耗:有时,你可以通过直接编写汇编代码,绕过Solidity的一些抽象,来优化你的代码以减少gas消耗。
需要注意的是,虽然使用汇编可以实现更底层的操作,但它也更容易出错,而且对于阅读和理解代码的人来说,它也更难理解。因此,除非有必要,否则一般不建议在Solidity代码中直接使用汇编。
声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意
腾讯云开发者社区:孟斯特