50

How can I convert a bytes32 to a string? Does anyone has a magic function or library which does it?

eth
  • 85,679
  • 53
  • 285
  • 406
arodriguezdonaire
  • 3,027
  • 3
  • 20
  • 37

12 Answers12

41

As of feb 2021 you can do

bytes32 foo = "hello";
string memory bar = string(abi.encodePacked(foo));
e18r
  • 728
  • 8
  • 17
31

Here's one:

function bytes32ToString(bytes32 x) constant returns (string) {
    bytes memory bytesString = new bytes(32);
    uint charCount = 0;
    for (uint j = 0; j < 32; j++) {
        byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
        if (char != 0) {
            bytesString[charCount] = char;
            charCount++;
        }
    }
    bytes memory bytesStringTrimmed = new bytes(charCount);
    for (j = 0; j < charCount; j++) {
        bytesStringTrimmed[j] = bytesString[j];
    }
    return string(bytesStringTrimmed);
}

To test, here it is combined with how to concatenate an array of bytes32. Paste the following in Remix.

contract C {
    function bytes32ToString(bytes32 x) constant returns (string) {
        bytes memory bytesString = new bytes(32);
        uint charCount = 0;
        for (uint j = 0; j < 32; j++) {
            byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
            if (char != 0) {
                bytesString[charCount] = char;
                charCount++;
            }
        }
        bytes memory bytesStringTrimmed = new bytes(charCount);
        for (j = 0; j < charCount; j++) {
            bytesStringTrimmed[j] = bytesString[j];
        }
        return string(bytesStringTrimmed);
    }

    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);
    }    
}

Click "Create". Then in bytes32ToString field enter "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" and click bytes32ToString.

In bytes32ArrayToString field enter ["0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"] and click bytes32ArrayToString.

Both will show same result (ABI encoding): Result: "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"


Here's another example. In bytes32ToString field enter "0xc3b6" and click bytes32ToString. You will get ö.

enter image description here

eth
  • 85,679
  • 53
  • 285
  • 406
  • I used the bytes32ToString function from above, but I obviously doesn't work with special characters such as ö ä ü etc. Is there a way to use this function with special characters? – Bumblebee Apr 20 '17 at 10:02
  • @Bumblebee I added an example for ö and it works. If still needed, probably ask a separate question. (The input or decoding the output might be your problem.) – eth Apr 21 '17 at 02:31
  • I am trying your bytes32ArrayToString with a fixed bytes32[10], but it seems I throw an invalid opcode if I use 8-10 full slots of the array. Meaning I have a test for abcdefghijklmnopqrstuvwxyzabcdef (32 characters) 10 times in an array and pass that in, but it throws. If I have 7 or less it works. Any idea why? – The Nomad Nov 12 '17 at 12:49
  • @TheNomad Not sure. Suggestions, try once instead of 10 times, and post a new question (a Remix or ethfiddle link might help). – eth Nov 19 '17 at 19:37
  • 1
    @Russo It's not clear what you're trying to do in Python; Stackoverflow is a better fit for questions about converting from different Python types. – eth Jun 03 '18 at 17:13
  • Had no idea a string was an array of bytes.. Learned something new today! thanks! – savageWays Jan 28 '19 at 16:45
25

Based on the latest compiler version 0.4.24, I use the following.

function convertingToString()public returns(string){
bytes32 memory hw = "Hello World";
string memory converted = string(hw);
return converted;
}

Using explicit conversion to carry it out. The reverse is also possible.

For versions 0.5.0+ please use (tested from 0.5 to 0.7.2 - it is likely that it will continue to work past 0.7.2):

function bytes32ToString(bytes32 _bytes32) public pure returns (string memory) {
        uint8 i = 0;
        while(i < 32 && _bytes32[i] != 0) {
            i++;
        }
        bytes memory bytesArray = new bytes(i);
        for (i = 0; i < 32 && _bytes32[i] != 0; i++) {
            bytesArray[i] = _bytes32[i];
        }
        return string(bytesArray);
    }
Patrick Collins
  • 11,186
  • 5
  • 44
  • 97
R.D
  • 505
  • 5
  • 15
  • 12
    This does not work in solidity version 0.5.0+ – Yogesh - EtherAuthority.io Jan 04 '19 at 14:38
  • 2
    and what does?? – Lukas Lukac Feb 06 '20 at 11:11
  • 2
    updated for solidity version past 0.5.0 – Patrick Collins Oct 08 '20 at 11:37
  • 3
    does not work getting this error Failed to decode output: null: invalid codepoint at offset 2; missing continuation byte (argument="bytes", value={"0":91,"1":218,"2":113,"3":98,"4":184,"5":77,"6":255,"7":114,"8":27,"9":203,"10":143,"11":119,"12":114,"13":120,"14":180,"15":136,"16":222,"17":216,"18":209,"19":71,"20":82,"21":100,"22":212,"23":54,"24":28,"25":107,"26":10,"27":191,"28":204,"29":42,"30":153,"31":168}, code=INVALID_ARGUMENT, version=strings/5.1.0) was trying to convert this string 0x5bda7162b84dff721bcb8f777278b488ded8d1475264d4361c6b0abfcc2a99a8 – Ramesh Pareek Jun 29 '21 at 16:33
12

How to convert a bytes32 to string:

pragma solidity ^0.4.15;

contract Bytes32ToString {

function bytes32ToStr(bytes32 _bytes32) public pure returns (string) {

    // string memory str = string(_bytes32);
    // TypeError: Explicit type conversion not allowed from "bytes32" to "string storage pointer"
    // thus we should fist convert bytes32 to bytes (to dynamically-sized byte array)

    bytes memory bytesArray = new bytes(32);
    for (uint256 i; i < 32; i++) {
        bytesArray[i] = _bytes32[i];
        }
    return string(bytesArray);
    }

}
itinance
  • 184
  • 9
Viktor
  • 550
  • 4
  • 15
3

It's recommended you convert a bytes32 to a string using Web3.js to avoid gas costs. To do this, you would get the value of the bytes32 from Solidity to the front end then do:

web3.utils.hexToString(bytes32);

This will convert the bytes32 to a string that you can then see and use in your frontend dApp.

Adrian D.
  • 544
  • 6
  • 14
2

Like @e18r already mentioned, the simplest way to do it without having to write all these crazy functions like everyone else is answering with (and would cost more gas), just do:

string(abi.encodePacked(bytes32));

Adrian D.
  • 544
  • 6
  • 14
2

Just in case, if you want to convert bytes32 to ASCII string, you can use the OpenZeppelin Strings library.

https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2504

Strings.toHexString(uint256(tokenIdSeed), 32),

The output should be like

0xd8df8ecd5432b247d2fc2beb0619d637e9de0df7512bd36220582deda9a1df6e 

(this is just covert hexadecimal value of the bytes32 to string)

taijusanagi
  • 636
  • 6
  • 4
2

In version 0.5.0 and above i ended up with using Viktor answer How to convert a bytes32 to string but removing the zeros otherwise you will end up with

'ERC20\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000'

instead of

'ERC20'

This is the code:

/* bytes32 (fixed-size array) to string (dynamically-sized array) */
function bytes32ToString(bytes32 _bytes32) public pure returns (string memory) {
        uint8 i = 0;
        while(i < 32 && _bytes32[i] != 0) {
            i++;
        }
        bytes memory bytesArray = new bytes(i);
        for (i = 0; i < 32 && _bytes32[i] != 0; i++) {
            bytesArray[i] = _bytes32[i];
        }
        return string(bytesArray);
    }
Sr.PEDRO
  • 160
  • 6
1

A more gas-efficient method based on this answer (For versions 0.5.0+):

function toString(bytes32 source)
    internal
    pure
    returns (string memory result)
{
    uint8 length = 0;
    while (source[length] != 0 && length < 32) {
        length++;
    }
    assembly {
        result := mload(0x40)
        // new "memory end" including padding (the string isn't larger than 32 bytes)
        mstore(0x40, add(result, 0x40))
        // store length in memory
        mstore(result, length)
        // write actual data
        mstore(add(result, 0x20), source)
    }
}

This solution is using assembly to copy data to memory instead of for looping.

SSgumS
  • 13
  • 3
0
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.7;
    contract stringtobytes{
        function set(string memory  _a)public pure returns(bytes memory){
            return bytes(_a);
        } 
         function set1(bytes memory  _a)public pure returns(string  memory){
            return string(_a);
        } 

}

// you can convert strings to bytes(in decimal format) and vice versa with below code

//1- bytes1=8bit=2decimal

//2 bytes2=16bit=4decimal

//3 bytes3=24bit=6decimal

//4 bytes=dynamic array and reference value

  • 2
    The question is about conversion from bytes32 to string, and your example doesn't work for that. – Ismael Feb 03 '22 at 13:34
0

Here's the simplest way i tried

contract ModifyString{
bytes32 public VoterName;

mapping (address =&gt; VoterStruct) public voterCalls;

struct VoterStruct{
   address VoterAddress;
   string VoterID;
   bytes32 VoterName2;
}

function addVoter(string memory _VoterID, string memory _VoterName)public {
   // Load Voter struct trough mapping
   VoterStruct storage newVoter = voterCalls[msg.sender];

   // If want to write to global variable
   VoterName = bytes32(abi.encodePacked( _VoterName));

   // If want to write to struct
   newVoter.VoterAddress = msg.sender;
   newVoter.VoterID = _VoterID;
   newVoter.VoterName2 = bytes32(abi.encodePacked(_VoterName));
}

function getVoterName() public view returns (string memory) {

   // To load from Global Variables
   bytes memory bytesData = abi.encodePacked(VoterName);

   return string(abi.encodePacked(VoterName));
}

function getVoterName2() public view returns (string memory) {

   // To look Voter name in global variable
   bytes memory bytesData = abi.encodePacked(VoterName);

   return string(abi.encodePacked(bytesData));
}

function getVoterName3() public view returns (string memory) {

   // To look Voter name in struct
   VoterStruct storage voterCall = voterCalls[msg.sender];

   return string(abi.encodePacked(voterCall.VoterName2));
}

}

so to load the string, it need to be loaded in memory, as far as i know, string = bytes (without specific bytes number)

then return the output value using

string(abi.encodePacked(bytesData))

^^^^ ^^^^^ //The converted type to //Loaded Variable into memory or storage

ahh so there is to: 1.1 Write String to bytes32 to Global Variable, 1.2 Load string from bytes32 from Gobal Variable, 2.1 Write String to bytes32 to Struct, 2.2 Load String to bytes32 to struct.

0

Here's how I'm doing it:

function char(byte b) returns (byte c) {
    if (b < 10) return byte(uint8(b) + 0x30);
    else return byte(uint8(b) + 0x57);
}


function bytes32string(bytes32 b32) returns (string out) {
    bytes memory s = new bytes(64);

    for (var i = 0; i < 32; i++) {
        byte b = byte(b32[i]);
        byte hi = byte(uint8(b) / 16);
        byte lo = byte(uint8(b) - 16 * uint8(hi));
        s[i*2] = char(hi);
        s[i*2+1] = char(lo);            
    }

    out = string(s);
}
d9ngle
  • 436
  • 4
  • 10