#bit-manipulation #solidity #rsk
Вопрос:
Мне нужно сохранить значение такого рода 0xff0000
или 0x00ff08
(шестнадцатеричное цветовое представление) в смарт-контракте solidity и иметь возможность преобразовать его внутри контракта в строку с теми же текстовыми символами "ff0000"
. Я намерен развернуть этот смарт-контракт на RSK.
Моя идея состояла в том, чтобы сохранить эти значения в переменной bytes3
или просто uint
и иметь чистую функцию, преобразующую bytes3
или uint
в соответствующую строку. Я нашел функцию, которая выполняет эту работу и работает над солидностью 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 amp; 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 ?
Ответ №1:
Следующие компиляции и были протестированы с использованием 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 ?
.
В сторону:
Вопрос: Почему это не вернулось при компиляции в solc 0.4.9, но вернулось, когда тот же код был скомпилирован в solc 0.8.7?
A: в 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 amp; mask);
bstr[--k] = curr > 9 ?
bytes1(uint8(55 curr)) :
bytes1(uint8(48 curr)); // 55 = 65 - 10
i = i >> 4;
}
return string(bstr);
}
}