Solidity 将十六进制数字转换为十六进制字符串

Ale*_*hin 7 bit-manipulation solidity rsk

我需要在 Solidity 智能合约中存储这种类型的值0xff00000x00ff08(十六进制颜色表示),并能够在合约内将其转换为具有相同文本字符的字符串"ff0000"。我打算在 RSK 上部署这个智能合约。

我的想法是将这些值存储在一个bytes3or 简单的uint变量中,并使用一个纯函数将bytes3or转换uint为相应的字符串。我找到了一个可以完成这项工作并在 Solidity 0.4.9 上工作的函数

pragma solidity 0.4.9;

contract UintToString {
    function uint2hexstr(uint i) public constant returns (string) {
        if (i == 0) return "0";
        uint j = i;
        uint length;
        while (j != 0) {
            length++;
            j = j >> 4;
        }
        uint mask = 15;
        bytes memory bstr = new bytes(length);
        uint k = length - 1;
        while (i != 0){
            uint curr = (i & mask);
            bstr[k--] = curr > 9 ? byte(55 + curr ) : byte(48 + curr); // 55 = 65 - 10
            i = i >> 4;
        }
        return string(bstr);
    }
}
Run Code Online (Sandbox Code Playgroud)

但我需要更新的编译器版本(至少 0.8.0)。以上功能不适用于较新的版本。

在 Solidity >=0.8.0 中有效的转换bytesuint转换为十六进制字符串 (1->'1',f->'f') 的方法是什么?

bgu*_*uiz 4

以下编译,并使用 solc 0.8.7 进行测试 它与您的原始版本相同,有以下修改:

  • constant-->pure
  • returns (string)-->returns (string memory)
  • byte(...)--> bytes1(uint8(...))

上述更改克服了原始函数中的所有编译时差异。...但是仍然存在一个运行时错误导致该函数恢复:

调试时,该行在bstr[k--] = curr > 9 ?其所在循环的最后一次迭代中触发了恢复。这是因为 while 循环被设置为处于k0最终迭代中。

虽然识别很棘手,但修复很简单:将减量运算符从后缀更改为前缀 - bstr[--k] = curr > 9 ?

在旁边:

问:为什么在 solc 0.4.9 中编译时没有恢复,但在 solc 0.8.7 中编译相同的代码时却恢复?

答:solc 0.8.0 引入了一项重大更改,编译器插入了 uint 上溢和下溢检查。在此之前,需要使用SafeMath或类似的方法来完成相同的任务。 请参阅 solc 0.8 发行说明的“语义的无声变化”部分

pragma solidity >=0.8;

contract TypeConversion {
    function uint2hexstr(uint i) public pure returns (string memory) {
        if (i == 0) return "0";
        uint j = i;
        uint length;
        while (j != 0) {
            length++;
            j = j >> 4;
        }
        uint mask = 15;
        bytes memory bstr = new bytes(length);
        uint k = length;
        while (i != 0) {
            uint curr = (i & mask);
            bstr[--k] = curr > 9 ?
                bytes1(uint8(55 + curr)) :
                bytes1(uint8(48 + curr)); // 55 = 65 - 10
            i = i >> 4;
        }
        return string(bstr);
    }
}

Run Code Online (Sandbox Code Playgroud)