Solidity哈希值不匹配问题:传入bytes32哈希与本地计算结果不一致
哈希不匹配问题排查与解决
核心原因:两次哈希的输入字节结构完全不同
你遇到的问题本质是两次哈希运算的输入数据根本不是同一组字节:
- 第一步在线哈希的是完整字符串"2test2",对应的字节是ASCII编码的
0x327465737432(共6字节),直接对这组字节做Keccak256哈希得到你存储的0x0698472c4668bddd0c694601ca101551bd7b5cfe6dc780ab37bccfc99ad22e4c。 - 第二步合约中
getSaltedHash函数的输入是**uint256(2) + bytes32("test2")**的拼接结果:- uint256(2)会被编码为8字节的大端数据:
0x0000000000000002 - bytes32("test2")是32字节的固定长度数据:
0x0000000000000000000000000000000000000000000000000000007465737432 - 两者拼接后是40字节的数组,对这组字节哈希的结果自然和第一步的6字节输入哈希完全不同。
- uint256(2)会被编码为8字节的大端数据:
两种修复方案
方案1:调整合约哈希逻辑,匹配在线哈希的输入
如果你希望合约计算的哈希和在线工具的"2test2"结果一致,需要把answer(uint256类型)转换为字符串,再和salt对应的字符串拼接成完整的"2test2",再做哈希:
function getSaltedHash(uint256 answer, string memory salt) public pure returns (bytes32) { // 将uint256转成字符串,和salt拼接后哈希 return keccak256(abi.encodePacked(string(abi.encodePacked(answer)), salt)); }
注意:如果你的salt原本是bytes32类型,需要先把它转换为去掉前导空字节的字符串(比如用自定义bytesToString工具函数),再传入这个函数。
方案2:调整在线哈希的计算方式,匹配合约逻辑
如果你想保留合约当前的abi.encodePacked(uint256, bytes32)逻辑,需要在线工具中模拟相同的字节拼接:
- 将uint256(2)转换为8字节大端数据:
0x0000000000000002 - 取bytes32("test2")的32字节数据:
0x0000000000000000000000000000000000000000000000000000007465737432 - 把这两段字节拼接成完整的40字节数组,再用在线Keccak256工具哈希,得到的结果就会和合约计算的一致。
验证示例
用Solidity代码直接验证两种输入的差异:
// 在线哈希的输入:字符串"2test2" bytes32 hash1 = keccak256(abi.encodePacked("2test2")); // 合约原逻辑的输入:uint256(2) + bytes32("test2") bytes32 hash2 = keccak256(abi.encodePacked(uint256(2), bytes32("test2"))); // hash1 != hash2,两者完全不同
内容的提问来源于stack exchange,提问作者Ayudh
相关产品推荐
相关产品推荐

