为何Solidity汇编函数中布尔类型无法正常工作?
Solidity汇编实现IsPrime函数:直接返回布尔值的优化方案
问题背景
用Solidity内联汇编编写质数判断函数时,无法直接使用true/false字面量,只能通过uint类型中转结果,再在外层用if/else转换为bool返回。尝试用switch语句时会报错“true and false are not valid literals”,希望简化逻辑,去掉外层的变通处理。
核心原因
Solidity的内联汇编中没有原生bool类型,bool在底层是uint1,true对应数值1,false对应数值0,不能直接使用Solidity层面的true/false字面量。
优化方案1:用uint中转直接转bool
直接在汇编里用1和0表示真假,外层无需额外判断,直接转换为bool返回,同时补上边界值处理(原代码未处理0、1的情况):
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.4.26; contract PrimeNumber{ function isPrimeNumber(uint num1) public view returns(bool) { uint result = 1; // 初始设为1,对应true assembly{ // 处理边界:小于2的数不是质数 if lt(num1, 2) { result := 0 leave // 提前退出汇编块 } for {let i := 2} lt(i, num1) {i := add(i, 1)}{ if eq(mod(num1, i), 0) { result := 0 // 找到因数,设为0(false) leave // 找到结果后直接退出循环 } } } return bool(result); // 直接将uint转成bool返回 } }
优化方案2:直接操作返回内存(更高效)
跳过临时变量,直接在内存中写入返回值,用return指令直接返回,减少不必要的变量转换:
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.4.26; contract PrimeNumber{ function isPrimeNumber(uint num1) public view returns(bool) { assembly{ // 先在内存默认写入true(1) mstore(0x0, 1) // 边界判断:0、1不是质数 if lt(num1, 2) { mstore(0x0, 0) return(0x0, 32) // 直接返回false } for {let i := 2} lt(i, num1) {i := add(i, 1)}{ if eq(mod(num1, i), 0) { mstore(0x0, 0) return(0x0, 32) // 找到因数后立即返回false } } // 循环结束无因数,返回默认的true return(0x0, 32) } } }
额外说明
- 原代码中用20和10作为标记完全没必要,直接用1和0对应bool的底层数值更直观
leave指令可以提前退出当前汇编块,避免无效循环;直接用return则能直接结束函数,提升执行效率- 一定要处理边界值:0、1以及负数(不过参数是uint,所以不用考虑负数),否则会出现错误判断
内容的提问来源于stack exchange,提问作者Taylor Lepper
相关产品推荐
相关产品推荐

