You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 09:06:01