Convertir dirección a cadena después de solidez 0.5.x

Después del lanzamiento de solidity 0.5.x, ninguna de las conversiones de dirección a cadena parece estar funcionando. Los probé todos en remix y obtuve errores como convertir bytes a uint o algo así.

Este revierte el remix:

function toString(address x) 
    external pure 
    returns (string memory) 
{
    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);
}

Este me muestra que algo no está permitido desde bytes1 hasta uint256

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

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

¿Hay alguna forma adecuada de convertir la dirección en una cadena? Incluso si a través de bytes o bytes32.

La razón por la que necesito esto es que tengo un contrato de privilegios con una cadena => Mapeo de PrivilegeData y estoy llamando a los privilegios globales de esa cadena como "voting_time_limit". Para direcciones específicas, me gustaría usar la llamada por dirección analizada en una cadena como "0x252f...".

Cuidado con el truncamiento en (2**(8*(19 - i))).

Respuestas (1)

Probar esto.

pragma solidity > 0.5.1;

contract Test 
{
    
    function test() 
        public 
        view    
        returns (string memory) 
    {
        return addressToString(address(this));
    }

    function addressToString(address _addr) public pure returns(string memory) 
    {
        bytes32 value = bytes32(uint256(uint160(_addr)));
        bytes memory alphabet = "0123456789abcdef";
    
        bytes memory str = new bytes(51);
        str[0] = '0';
        str[1] = 'x';
        for (uint256 i = 0; i < 20; i++) {
            str[2+i*2] = alphabet[uint8(value[i + 12] >> 4)];
            str[3+i*2] = alphabet[uint8(value[i + 12] & 0x0f)];
        }
        return string(str);
    }
}
Entonces, ¿por qué 51 bytes y no 43?
51 solo porque ese es el código provisto, pero si analizamos eso, 42 se ajustará a los 40 caracteres + 2 al 0x.
43, ya que creo que también necesita asignar el carácter nulo.
¿Qué carácter nulo? ¿Estás hablando del byte nulo en "cadenas vacías"? o el byte nulo utilizado por c++? solidity no tiene eso, que yo sepa, solo almacena la longitud de la cadena en un uint256 en los primeros 32 bytes a los que apunta la variable, y apunta más 32 a donde almacena la matriz de cadenas real