uint256返回值错误:Solidity合约MASK异常,shiftedGroupId无返回问题排查
问题根因
- 常量
GROUP_MASK的定义存在有符号数隐式转换的编译器兼容问题:~0在Solidity中默认是有符号int256类型(值为-1),虽然逻辑上uint256(uint128(~0)) << 128应该得到高128位全1、低128位全0的掩码,但0.7.6版本的编译器在处理跨有符号/无符号类型转换+移位的编译期常量计算时,有概率出现预期外的计算错误,极端情况会得到全0的掩码,导致shiftedGroupId永远为0,最终返回的groupId也恒为0,和你感知的shiftedGroupId未返回值的表现一致。 - 原有函数的修饰符不规范:函数没有读取任何合约状态变量,却标记为
view,虽然不影响运行结果,但不符合Solidity语法规范。
修复方案
直接使用无歧义的十六进制字面量定义掩码,彻底规避类型转换的坑,同时优化函数修饰符:
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.7.6; /** * @title Storage * @dev Extract high 128 bits as group id from input id */ contract Storage { // 直接定义高128位全1的掩码,无类型转换歧义,编译器计算不会出错 uint256 public constant GROUP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000; /** * @dev Extract group id from input id * @param id 256bit input value * @return groupId high 128 bits of input id */ function store(uint256 id) public pure returns (uint256){ uint256 shiftedGroupId = (id & GROUP_MASK); uint256 groupId = shiftedGroupId >> 128; return groupId; } }
验证方法
传入高128位非0的测试用例即可验证逻辑正确性,例如传入id = 0x12340000000000000000000000000000ffffffffffffffffffffffffffffffff,修复后的代码会正确返回0x12340000000000000000000000000000。
内容的提问来源于stack exchange,提问作者Victor Fernandez
相关产品推荐
相关产品推荐

