Solidity Go-Ethereum Remix Addresses Data Types – How to Convert Address to String in Solidity?

addressesdata-typesgo-ethereumremixsolidity

I am using this code in converting address to string in solidity

function toAsciiString(address x) public returns (string memory) {

    bytes memory s = new bytes(40);
    for (uint i = 0; i < 20; i++) {
        bytes1 b = bytes1(uint8(uint(uint160(x)) / (2**(8*(19 - i)))));
        bytes1 hi = bytes1(uint8(b) / 16);
        bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));
        s[2*i] = char(hi);
        s[2*i+1] = char(lo);            
    }
    return string(abi.encodePacked("0x",s));
}

function char(bytes1 b) public returns (bytes1 c) {

    if (uint8(b) < 10) return bytes1(uint8(b) + 0x30);
    else return bytes1(uint8(b) + 0x57);
}

Input : 0x4a9C121080f6D9250Fc0143f41B595fD172E31bf

Output: 0x4a9c121080f6d9250fc0143f41b595fd172e31bf

As you can see, there is a capitalization issue. The output should be same as input but capital letters in input are coming out as small letters. I am running this code in remix. Please let me know if there is any fix.

Best Answer

The problem with the code above is that you're taking the address apart and converting it to a string of chars 1 hex digit at a time. In hexadecimal, there is not distinction between capital and small symbols (e.g., 0xA is equal to 0xa which in turn is equal to the decimal value of 10). All hex characters above the decimal value of 10 (non-decimal chars from a-f) are being converted into ASCII chars by incrementing their hex value with 0x57 to result in letters (a-z). And since input values like 0xa and 0xA are basically the same value, both would result in the same lowercase letter a.

The checksum details are lost in that conversion and the resulting string is all lowercase. If you wanted to keep the checksum info, you'll need to include the hex digit's index in the address into account, as the checksum algorithm is described as follows:

convert the address to hex, but if the ith digit is a letter (ie. it's one of abcdef) print it in uppercase if the 4*ith bit of the hash of the lowercase hexadecimal address is 1 () otherwise print it in lowercase.

Basically, you'll first need to convert the address to a lowercase string, then take the keccak256 hash of it and apply the algorithm above. More info about the checksum algorithm here.