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 to0xa
which in turn is equal to the decimal value of10
). All hex characters above the decimal value of10
(non-decimal chars from a-f) are being converted into ASCII chars by incrementing their hex value with0x57
to result in letters (a-z). And since input values like0xa
and0xA
are basically the same value, both would result in the same lowercase lettera
.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:
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.