13

In Solidity, how can I convert the sender address to a string?

The comments in How to convert an address to bytes in Solidity? did not provide a working solution

17
function toString(address x) returns (string) {
    bytes memory b = new bytes(20);
    for (uint i = 0; i < 20; i++)
        b[i] = byte(uint8(uint(x) / (2**(8*(19 - i)))));
    return string(b);
}

You can quickly test and see that the returned string is ABI encoded.

Here is an example of converting msg.sender to a string:

contract C {
    string public senderString;

    function toString(address x) returns (string) {
        bytes memory b = new bytes(20);
        for (uint i = 0; i < 20; i++)
            b[i] = byte(uint8(uint(x) / (2**(8*(19 - i)))));
        return string(b);
    }

    function test() {
        senderString = toString(msg.sender);
    }
}
  • 2
    Does not work tested in Remix with Solidity 0.4.15 – Viktor Nov 22 '17 at 3:21
  • 1
    Hi. I'm trying to convert this to C# and I'm struggling. Am I right in assuming that the argument x is of type "address" and address is an array of bytes? Also, is it correct to assume that uint(x) is a cast to uint? This is the part I don't understand. How do you cast an array of bytes to a single uint? What am I missing here? – Melbourne Developer Dec 28 '17 at 22:38
  • @MelbourneDeveloper One way to consider is that x is 20 bytes (not array) big-endian left-padded to 32 bytes. There is no need to cast if you read the bytes in big-endian: it's just to make Solidity's type checker happy. It looks like BigInteger may be helpful msdn.microsoft.com/en-us/library/dd268207.aspx, you'll need to be careful since it uses little-endian, but shouldn't need to cast and can divide like given in the answer. – eth Dec 30 '17 at 15:09
  • It works, but the result is not a human-readable string. For a human-readable string, see toAsciiString example in the other answer. – rustyx Apr 9 '18 at 13:22
  • None of these codes work. – Radeg90 Jul 8 at 9:10
8

I was not able to read the ABI-encoded string with web3.js. Therefore I added some conversion to the ascii-characters:

function toAsciiString(address x) returns (string) {
    bytes memory s = new bytes(40);
    for (uint i = 0; i < 20; i++) {
        byte b = byte(uint8(uint(x) / (2**(8*(19 - i)))));
        byte hi = byte(uint8(b) / 16);
        byte lo = byte(uint8(b) - 16 * uint8(hi));
        s[2*i] = char(hi);
        s[2*i+1] = char(lo);            
    }
    return string(s);
}

function char(byte b) returns (byte c) {
    if (b < 10) return byte(uint8(b) + 0x30);
    else return byte(uint8(b) + 0x57);
}
  • 1
    There was a problem with the function char(byte b). "TypeError: Operator < not compatible with types bytes1 and int_const 10" I suppose this comparison does work anyway since you probably meant if b is a number then add 0x30 to it. But how do you know if a byte is less than 10 or not anyways? – Billie Jan 16 at 12:25
1

This is method to convert address to hex string:

function addressToString(address _addr) public pure returns(string) {
    bytes32 value = bytes32(uint256(_addr));
    bytes memory alphabet = "0123456789abcdef";

    bytes memory str = new bytes(42);
    str[0] = '0';
    str[1] = 'x';
    for (uint i = 0; i < 20; i++) {
        str[2+i*2] = alphabet[uint(uint8(value[i + 12] >> 4))];
        str[3+i*2] = alphabet[uint(uint8(value[i + 12] & 0x0f))];
    }
    return string(str);
}
-1

function toString(address x) internal pure returns (string) { bytes memory b = new bytes(20); for (uint i = 0; i < 20; i++) b[i] = byte(uint8(uint(x) / (2**(8*(19 - i))))); return string(b); }

Use internal pure keyword, otherwise you will get a warning. For more information about pure function.

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.