Solidity如何提取bytes32前13个十六进制字符并转换为uint256
Solidity 提取bytes32前13个十六进制字符并转uint256实现方案
核心概念说明
首先明确两个基础规则,之前的尝试报错都是因为对这两点的认知偏差:
- bytes32类型存储的是原始二进制数据,每1个字节对应2个十六进制字符,你要的13个十六进制字符对应
13 * 4 = 52个bit(每个十六进制字符占4bit) - 直接把bytes32转string会把二进制数据当做ASCII编码解析,自然会出现编码错误,需要先把二进制数据转成十六进制可打印字符串再做切片
完整实现代码
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract TestContract { // 十六进制字符集,用于字节转十六进制字符串 bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; function getsubstring1() public pure returns (string memory, uint256) { bytes32 hmacSha256 = 0xf83bf40815929b2448b230d51fa2eaa5b8ccffd87691db7e62bf817b2cbb56ad; // 第一步:直接获取对应的uint256值,无需处理字符串 // 前13个十六进制字符对应高52位,右移256-52=204位即可 uint256 targetUint = uint256(hmacSha256) >> 204; // 第二步:转成带0x前缀的十六进制字符串 string memory targetHexStr = uintToHexStr(targetUint, 13); return (targetHexStr, targetUint); } // uint转指定长度的十六进制字符串,length为十六进制字符长度(不含0x前缀) function uintToHexStr(uint256 value, uint256 length) public pure returns (string memory) { bytes memory result = new bytes(length + 2); // 加2是预留0x前缀位置 result[0] = '0'; result[1] = 'x'; for (uint256 i = 0; i < length; i++) { uint256 shift = (length - 1 - i) * 4; uint8 nibble = uint8((value >> shift) & 0xf); result[2 + i] = _HEX_SYMBOLS[nibble]; } return string(result); } }
结果验证
调用getsubstring1会返回两个完全符合预期的结果:
- 字符串:
0xf83bf40815929 - uint256值:
4366982094870825
原尝试方案错误说明
- 用
bytes13(hmacSha256)取的是前13个字节,对应26个十六进制字符,所以长度是你预期的两倍 - 直接对
abi.encodePacked(hmacSha256)转string是解析二进制字节的ASCII值,哈希的二进制值大多是非可打印字符,所以会报编码错误 - memory类型的bytes数组不支持切片操作,只有calldata类型的动态字节数组才能直接用
[x:y]切片
内容的提问来源于stack exchange,提问作者Satya
相关产品推荐
相关产品推荐

