5

I try to convert hex string to bytes.

function MyContract() public {
    string memory str = "A76A95918C39eE40d4a43CFAF19C35050E32E271";
    array1 = bytes(str);


    bytes memory  str1 = hex"A76A95918C39eE40d4a43CFAF19C35050E32E271";
    array2 = str1; 
}

In array1 I have only unicode from str like array1[0] - 41. In array 2 I have what I want array2[0] - a7. But I can't use hex with variable.

I want to use function arguments for conversion to bytes like:

function (string str) {
  return bytes(hex(str))
}

Question: Is there any way to do the conversion in Solidity?

Thanks so much in advance.

Ismael
  • 30,570
  • 21
  • 53
  • 96
fragnatic
  • 51
  • 1
  • 1
  • 2

2 Answers2

5

This are very inefficient but should work

// Convert an hexadecimal character to their value
function fromHexChar(uint8 c) public pure returns (uint8) {
    if (bytes1(c) >= bytes1('0') && bytes1(c) <= bytes1('9')) {
        return c - uint8(bytes1('0'));
    }
    if (bytes1(c) >= bytes1('a') && bytes1(c) <= bytes1('f')) {
        return 10 + c - uint8(bytes1('a'));
    }
    if (bytes1(c) >= bytes1('A') && bytes1(c) <= bytes1('F')) {
        return 10 + c - uint8(bytes1('A'));
    }
    revert("fail");
}

// Convert an hexadecimal string to raw bytes function fromHex(string memory s) public pure returns (bytes memory) { bytes memory ss = bytes(s); require(ss.length%2 == 0); // length must be even bytes memory r = new bytes(ss.length/2); for (uint i=0; i<ss.length/2; ++i) { r[i] = bytes1(fromHexChar(uint8(ss[2*i])) * 16 + fromHexChar(uint8(ss[2*i+1]))); } return r; }

In any case I'd recommend to try to convert your hexadecimal data outside solidity.

Ismael
  • 30,570
  • 21
  • 53
  • 96
  • Thanks for the answer, the bottom is what I need, but it returns bytes. This may be a stupid question, but how do I get it as bytes32? – thefett Apr 27 '18 at 14:10
  • @thefett It should be possible, declare bytes32 r instead of bytes memory r = new bytes(..). The problem is that it is not easy to modify indivual bytes of bytes32, but casting to uint and using shifts you can achieve that. – Ismael Apr 29 '18 at 06:47
  • this doesn't work sadly... – Jim May 19 '22 at 00:59
  • @Jim I tried and the functions worked from solc 0.5. It had a warning with solc 0.8 but it was easy to fix, it should have worked anyway. – Ismael May 19 '22 at 04:18
  • when I call fromHex("FF") I want it to return the unit 255, not the raw bytes. Isn't this what OP is asking? – Jim May 19 '22 at 05:09
  • @Jim The question asks to return a byte array so it works as intended. It shouldn't be too hard to modify to return an uint256 instead. In any case it will be better to create a new question, or better search if there's an existing one. – Ismael May 19 '22 at 15:13
  • May you please do it for me, fran – Jim May 19 '22 at 15:28
  • @Jim Sorry, but I'm busy, so no. – Ismael May 19 '22 at 15:37
  • No rush, I'll wait for you. thanks! – Jim May 19 '22 at 15:56
2

abi.encodePacked can be used now.

bytes memory b = abi.encodePacked(hex"A76A95918C39eE40d4a43CFAF19C35050E32E271")
nikojpapa
  • 121
  • 2