您观察到的行为的原因
abi.encodePacked(myBytes3) 产生 3 个字节,因为每 2 个十六进制字符产生 1 个字节。因此,当您将其包装在 string(..) 中时,您确实会得到一个每 1 个字节有 1 个字符的字符串,在这种情况下,会产生一个包含 3 个字符的字符串。对于某些输入,这会产生一个 可以 呈现为人类可读字符串的字符串。在其他情况下,它会导致字符串不能,因此会出现解析错误。
解决方案
在这种情况下,您不能使用 abi.encodePacked(..),因为“打包”与您要完成的操作相反相反 - 将 bytes3 呈现为十六进制 string - 一个那是人类可读的,ASCII编码的——你需要做类似的事情
my answer to your previous question,您可以结合使用位移和位掩码来每半字节提取一个字符。
代码
将单个uint8 转换为以十六进制表示它的ASCII 字符的实用函数:
function uint8tohexchar(uint8 i) public pure returns (uint8) {
return (i > 9) ?
(i + 87) : // ascii a-f
(i + 48); // ascii 0-9
}
将uint24 转换为6 个字符的十六进制string 的函数。
请注意,由于这次您不是在寻找“通用”解决方案,而是特定于 bytes3 的解决方案,因此不需要任何循环,而是一组顺序语句就可以了.可能也节省了一些气体。(有待确认!)
function uint24tohexstr(uint24 i) public pure returns (string memory) {
bytes memory o = new bytes(6);
uint24 mask = 0x00000f;
o[5] = bytes1(uint8tohexchar(uint8(i & mask)));
i = i >> 4;
o[4] = bytes1(uint8tohexchar(uint8(i & mask)));
i = i >> 4;
o[3] = bytes1(uint8tohexchar(uint8(i & mask)));
i = i >> 4;
o[2] = bytes1(uint8tohexchar(uint8(i & mask)));
i = i >> 4;
o[1] = bytes1(uint8tohexchar(uint8(i & mask)));
i = i >> 4;
o[0] = bytes1(uint8tohexchar(uint8(i & mask)));
return string(o);
}
最后,您可能需要一个明确接受bytes3 作为参数的函数。
请注意,这纯粹是为了方便,因为它所做的只是类型转换。 bytes3 和 uint24 可以简单地视为以不同方式查看/解释的“24 位”。
function bytes3tohexstr(bytes3 i) public pure returns (string memory) {
uint24 n = uint24(i);
return uint24tohexstr(n);
}