52

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

For example, this will works since as input I gave bytes32 . But it does not work with the characters greater than bytes32.

tx_hash = a.transact().set("QmVoGzRDscx61k3RHHkLYaMFtxYZi3ps") // 32-bit char

function get() returns (string value) {  
    return list.get_head_data();   
}

But if I need to give more character for example contains 48-bit string this won't work. How could I make this work?

alper
  • 8,395
  • 11
  • 63
  • 152

7 Answers7

62

This has worked for me so far. Not sure if it's the best way.

function stringToBytes32(string memory source) public pure returns (bytes32 result) {
    bytes memory tempEmptyStringTest = bytes(source);
    if (tempEmptyStringTest.length == 0) {
        return 0x0;
    }

    assembly {
        result := mload(add(source, 32))
    }
}

Also, remember that strings in solidity are UTF8 so after converting them to bytes each byte is not necessarily a character.

EDIT: shorter version, should work the same.

Thanwa Ch.
  • 15
  • 1
  • 7
  • xpected elementary inline assembly operation. bytes32 result := mload(add(source, 32)) ^ contracts/Link.sol:77:22: Error: Expected token Semicolon got 'Colon' bytes32 result := mload(add(source, 32)) – alper Oct 10 '16 at 11:30
  • @Avatar you have bytes32 result := while my code is declaring result type in returns (bytes32 result), just remove the bytes32 from before result := ... and it should compile. – Grzegorz Kapkowski Oct 10 '16 at 12:42
  • awesome works!! Thank you sir. One final question is, if my string is larger than 32 bits such as 48 bits the remaining 12 bits will be trimmed. Would there be additional assemble line that I can obtain bits from 32 to 48? thank you for your valuable time. when I did "result := mload(add(source, 64)) " it worked! – alper Oct 10 '16 at 15:26
  • I tried your code in remix.ethereum.org (using JavaScript VM) and entered "EOS8WE79SonHGHc5DquV4fxty9bHfnLSugCyTVXj2n9t4Uw5HL2vU" as my string, which is 56 characters long. It returned: "0x454f533857453739536f6e4847486335447175563466787479396248666e4c53" When I convert this into ASCII, I get "EOS8WE79SonHGHc5DquV4fxty9bHfnLS", which is 34 characters. Why? How do I get the original 56 characters back? – Curt Aug 16 '17 at 21:14
  • 1
    @Curt you can't, conversion from string to bytes32 is lossy. bytes32 can contain only 32 8-bit characters but strings can be longer than 32 characters and during this operation all characters above 32 are lost. The string you pasted has 32 characters, I didn't count the quotation characters. – Grzegorz Kapkowski Aug 18 '17 at 07:23
  • Also, this function should probably be marked "internal" to save some gas – EtherPaul Sep 28 '17 at 09:28
  • Took me a while to figure out so for the interested: AFAIK 'source' within assembly in this context refers to the memory address of source not the string it points to. Then we add 32 to this address as the first 32 bytes are seemingly reserved to hold the number of chars in the string (/length of the array). – willjgriff Nov 10 '17 at 16:47
  • Could you guys explain why this code works? What's the significance of adding 32 to the string's memory address pointer, and how does this convert it to bytes32? – Tarek Jan 13 '19 at 22:53
23

string is not equal to bytes32 but it is equal to bytes, because its length is dynamic.

so you could use a casting bytes B=bytes(S); //S string

E.g

contract string_test {

    function string_tobytes( string s) constant returns (bytes){
        bytes memory b3 = bytes(s);
        return b3;
    }
}

The conversion of string to bytes32 is possible only using assembly

Badr Bellaj
  • 18,780
  • 4
  • 58
  • 75
22

ethers.js has a built in utility function for this: https://docs.ethers.io/ethers.js/html/api-utils.html#bytes32-strings

const ethers = require('ethers')
const utils = ethers.utils

const inBytes = utils.formatBytes32String("test");
bornSwift
  • 329
  • 2
  • 4
8

Assembly is not needed in version 0.8.7

string text = "whatever"; 
bytes32 stringInBytes32 = bytes32(bytes(text));
Jose4Linux
  • 221
  • 2
  • 5
  • I tried this, what I want to do is send a bytes32 string to solidity and store it in a bytes32 variable. If I take the input string: '0x41b1a0649752af1b28b3dc29a1556eee781e4a4c3a1f7f53f90fa834de098c4d' and follow your code (bytes32(bytes(inputstring) I get '0x3078343162316130363439373532616631623238623364633239613135353665' from console.logBytes32 inside the solidity function. Seems to be all integers, altho the right length. Any ideas why that is: – GGizmos Feb 01 '22 at 02:03
  • @GGizmos, text is supposed to be a string of UTF-8 characters. You are using an hexadecimal value, I don't how to do it in that case. – Jose4Linux Feb 05 '22 at 19:31
  • When I try this I get Explicit type conversion not allowed from "bytes memory" to "bytes32". using a string from a parameter. – NickJ Jun 28 '22 at 23:04
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));
    } 
}

you can convert strings to bytes(in decimal format) 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 was about converting from string to bytes32, your example doesn't work for bytes32. – Ismael Feb 03 '22 at 13:24
0
function get(string memory key) 
    public 
    view 
    returns (bytes32) {
        return bytes32(abi.encodePacked(key));
}
alper
  • 8,395
  • 11
  • 63
  • 152
-1

Please reference this. You can convert string to bytes32 array.The length of string can be longer than 32 .

https://ethereum.stackexchange.com/a/13388/6353

黃智祥
  • 465
  • 6
  • 16