15

Is there a simple way to convert bytes32 to bytes in Solidity?

I'm trying to get the length of the string passed in the bytes32 variable but everything gets returned 32 size which makes sense.

But explicit conversion does not seem to work:

bytes memory _tmpUsername = bytes(_username);  // _username is of type bytes32 

This throws an error of:

Explicit type conversion not allowed from "bytes32" to "bytes storage pointer"
Ayrton Senna
  • 251
  • 1
  • 2
  • 5

4 Answers4

19

Since solidity@0.4.22, you can use abi.encodePacked() for this, which returns bytes. For example ;

contract C { 
  function toBytes(bytes32 _data) public pure returns (bytes) {
    return abi.encodePacked(_data);
  }
}
PhABC
  • 512
  • 5
  • 10
6

Here is a totally inefficient method of converting bytes32 to bytes (while removing extra zeros bytes to the right).

function bytes32ToBytes(bytes32 data) internal pure returns (bytes) {
    uint i = 0;
    while (i < 32 && uint(data[i]) != 0) {
        ++i;
    }
    bytes memory result = new bytes(i);
    i = 0;
    while (i < 32 && data[i] != 0) {
        result[i] = data[i];
        ++i;
    }
    return result;
}
Ismael
  • 30,570
  • 21
  • 53
  • 96
  • I actually was thinking on similar lines but wouldn't it be a problem if my data contains a 0 in its value? Say for example - data is "test2010"? – Ayrton Senna Feb 27 '18 at 05:29
  • 1
    The zero digit '0' has a value of 48 when considered as a byte, so it should not be a problem (this applies to more common string encoding, ASCII, UTF-8). – Ismael Feb 27 '18 at 06:27
4

Answer for Solidity v0.8.4 and above

You can use bytes.concat instead of abi.encodePacked.

function toBytes(bytes32 data) public pure returns (bytes memory) {
    return bytes.concat(data);
}

My understanding is that bytes.concat will ultimately replace abi.encodePacked.

Paul Razvan Berg
  • 17,902
  • 6
  • 73
  • 143
1

Using inline assembly you can copy a bytes32 to a bytes structure like this:

  function bytes32ToBytes(bytes32 input) public pure returns (bytes memory) {
    bytes memory b = new bytes(32);
    assembly {
      mstore(add(b, 32), input) // set the bytes data
    }
    return b;
  }