Solidity 将 HEX 数字转换为 HEX 字符串
Solidity convert HEX number to HEX string
我需要在 solidity 智能合约中存储这种 0xff0000
或 0x00ff08
(十六进制颜色表示)的值,并能够在合约中将其转换为具有相同文本的字符串字符 "ff0000"
。我打算在 RSK 上部署这个智能合约。
我的想法是将这些值存储在 bytes3
或简单的 uint
变量中,并使用一个纯函数将 bytes3
或 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);
}
}
但我需要更新的编译器版本(至少 0.8.0)。以上功能不适用于较新的版本。
如何将 bytes
或 uint
转换为十六进制字符串 (1->'1',f->'f') 在 Solidity >=0.8 中有效。 0 ?
以下编译,并使用solc 0.8.7测试
与您的原始版本相同,并进行了以下修改:
constant
--> pure
returns (string)
--> returns (string memory)
byte(...)
--> bytes1(uint8(...))
以上更改克服了原始函数中的所有编译时差异。
...但是仍然存在 运行 时间错误导致此函数恢复:
调试时,行 bstr[k--] = curr > 9 ?
在其所在循环的最后一次迭代中触发了还原。这是因为 while 循环的设置使得 k
为 0
在最后一次迭代中。
虽然识别很棘手,但修复很简单:将减量运算符从后缀更改为前缀 - bstr[--k] = curr > 9 ?
。
Aside:
Q: Why did this not revert when compiled in solc 0.4.9,
but revert when the same code was compiled in solc 0.8.7?
A: solc 0.8.0 introduced a breaking change where uint overflow and underflow checks were inserted by the compiler.
Prior to this one would have needed to use SafeMath
or similar to accomplish the same.
See the "Silent Changes of the Semantics" section of the solc 0.8 release notes
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);
}
}
我需要在 solidity 智能合约中存储这种 0xff0000
或 0x00ff08
(十六进制颜色表示)的值,并能够在合约中将其转换为具有相同文本的字符串字符 "ff0000"
。我打算在 RSK 上部署这个智能合约。
我的想法是将这些值存储在 bytes3
或简单的 uint
变量中,并使用一个纯函数将 bytes3
或 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);
}
}
但我需要更新的编译器版本(至少 0.8.0)。以上功能不适用于较新的版本。
如何将 bytes
或 uint
转换为十六进制字符串 (1->'1',f->'f') 在 Solidity >=0.8 中有效。 0 ?
以下编译,并使用solc 0.8.7测试 与您的原始版本相同,并进行了以下修改:
constant
-->pure
returns (string)
-->returns (string memory)
byte(...)
-->bytes1(uint8(...))
以上更改克服了原始函数中的所有编译时差异。 ...但是仍然存在 运行 时间错误导致此函数恢复:
调试时,行 bstr[k--] = curr > 9 ?
在其所在循环的最后一次迭代中触发了还原。这是因为 while 循环的设置使得 k
为 0
在最后一次迭代中。
虽然识别很棘手,但修复很简单:将减量运算符从后缀更改为前缀 - bstr[--k] = curr > 9 ?
。
Aside:
Q: Why did this not revert when compiled in solc 0.4.9, but revert when the same code was compiled in solc 0.8.7?
A: solc 0.8.0 introduced a breaking change where uint overflow and underflow checks were inserted by the compiler. Prior to this one would have needed to use
SafeMath
or similar to accomplish the same. See the "Silent Changes of the Semantics" section of the solc 0.8 release notes
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);
}
}