9

I am passing an array of bytes32 to my function. This array can contain numbers or hashes etc. to identify an object. In a new use case I want to pass a URL to this function by splitting the URL into parts converted to bytes32. How can I concatenate the single bytes32 to restore the URL?

I know I can create a bytes array and set bytes at indexes. But I don't know how I can access a specific position in a bytes32.

function bytes2string(bytes32[] data) returns (string) {
    bytes memory r = new bytes(1);
    r[0] = bytes1(data[0]);
    return string(r);
}
9

Thanks to Piper and Chris I found a working solution for Solidity <= 0.2.1. The reason why the first two log statements return different results is, because uintN is right-aligned and bytesN is left-aligned. Conversion between uintN and bytesN first shortens and then changes alignment. That's why it has to be converted back to bytes32 before converted to byte:

LogBytes1(byte(data)); // prints "s"
LogBytes1(byte(uint(data))); prints "\x00"
LogBytes1(byte(bytes32(uint(data)))); prints "s"

A tested solution to my question is:

function bytes32ArrayToString (bytes32[] data) returns (string) {
    bytes memory bytesString = new bytes(data.length * 32);
    uint urlLength;
    for (uint i=0; i<data.length; i++) {
        for (uint j=0; j<32; j++) {
            byte char = byte(bytes32(uint(data[i]) * 2 ** (8 * j)));
            if (char != 0) {
                bytesString[urlLength] = char;
                urlLength += 1;
            }
        }
    }
    bytes memory bytesStringTrimmed = new bytes(urlLength);
    for (i=0; i<urlLength; i++) {
        bytesStringTrimmed[i] = bytesString[i];
    }
    return string(bytesStringTrimmed);
}
  • I meet some problem when call this function outside the contract, I specify the bytes32[] string like this [7bb8b6ec123302e43ad88384158e2347efcfef19600b821431e8e09504046595,1f57c6ad7358ac73b73730eabb54b1bea7b785df2e4502291ed99b08af625def] but the compiler tell me it's wrong, why? – Wang May 24 '16 at 17:16
7

Solidity <= 0.2.1

You can retrieve the nth byte of any bytesXX type with the following code.

bytes32 v = ...;
byte b = byte(bytes32(uint(v) * 2 ** (8 * n)));

Solidity > 0.2.1

Starting in the next release of solidity you will be able to access them using indices.

bytes32 v = ...;
byte b = v[n];
  • Thanks for your comment Piper. The Solidity <= 0.2.1 solution doesn't work for me, because of an odd Solidity behaviour. Assuming I have a bytes32 containing a bytes representation of string "string", after a uint and byte conversion, the data changed: ` event LogBytes1(bytes1); LogBytes1(byte(data)); // prints "s" LogBytes1(byte(uint(data))); // prints "\x00" ` – Stefan Feb 7 '16 at 10:42
  • I've updated my code to include the recasting to bytes32. Not sure if you want to keep this answer or the one from below. – Piper Merriam Feb 14 '16 at 20:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.