Convertir dirección a cadena

En Solidity, ¿cómo puedo convertir la dirección del remitente en una cadena?

Los comentarios en ¿Cómo convertir una dirección a bytes en Solidity? no proporcionó una solución de trabajo

function toString(dirección x) retornos puros internos (cadena) { memoria de bytes b = bytes nuevos (20); for (uint i = 0; i < 20; i++) b[i] = byte(uint8(uint(x) / (2**(8*(19 - i))))); cadena de retorno (b); } Use internal purepalabra clave, de lo contrario recibirá una advertencia. Para obtener más información sobre la función pura .

Respuestas (5)

Usarabi.encodePacked(x)

donde xesta la direccion (Gracias @k06a )

Funciona, pero el resultado no es una cadena legible por humanos. Para una cadena legible por humanos, vea toAsciiStringel ejemplo en la otra respuesta.
no se puede usar junto con string.concat (0.8.x) (mensaje de error:) Invalid type for argument in the string.concat function call. string type is required, but t_bytes_memory_ptr provided, toAsciiStringfunciona para mí.
@Siwei Gracias, voté esa respuesta. Este tipo de pregunta me desconcierta porque puede ser un anti-patrón: generalmente debería tratar de evitar tales conversiones en un contrato y hacerlo en otro lugar como la interfaz...

No pude leer la cadena codificada con ABI con web3.js. Por lo tanto, agregué algo de conversión a los caracteres ASCII:

function toAsciiString(address x) internal pure 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(s);
}

function char(bytes1 b) internal pure returns (bytes1 c) {
    if (uint8(b) < 10) return bytes1(uint8(b) + 0x30);
    else return bytes1(uint8(b) + 0x57);
}
Hubo un problema con la función char(byte b). "Error de tipo: el operador <no es compatible con los tipos bytes1 e int_const 10" Supongo que esta comparación funciona de todos modos, ya que probablemente quiso decir que si b es un número, entonces agregue 0x30. Pero, ¿cómo saber si un byte es inferior a 10 o no?
if (b < 10)tiene que cambiarse a if (uint8(b) < 10), entonces el Operator < not compatible with types bytes1 ...error se corrige. Hice una edición a la respuesta. Espero que se apruebe.
Gracias por la respuesta, hasta ahora esto funciona en v0.5.10
Esta conversión pierde la suma de verificación de la dirección, que distingue entre mayúsculas y minúsculas. La suma de comprobación se puede restaurar usando Web3.utils.toChecksumAddress().
La dirección está formateada en minúsculas sin 0x inicial

Este es el método para convertir addressa hexadecimal string:

function toString(address account) public pure returns(string memory) {
    return toString(abi.encodePacked(account));
}

function toString(uint256 value) public pure returns(string memory) {
    return toString(abi.encodePacked(value));
}

function toString(bytes32 value) public pure returns(string memory) {
    return toString(abi.encodePacked(value));
}

function toString(bytes memory data) public pure returns(string memory) {
    bytes memory alphabet = "0123456789abcdef";

    bytes memory str = new bytes(2 + data.length * 2);
    str[0] = "0";
    str[1] = "x";
    for (uint i = 0; i < data.length; i++) {
        str[2+i*2] = alphabet[uint(uint8(data[i] >> 4))];
        str[3+i*2] = alphabet[uint(uint8(data[i] & 0x0f))];
    }
    return string(str);
}
¡¡Tener cuidado!! Aunque el código está bien diseñado, genera este error: github.com/ethers-io/ethers.js/issues/…
A partir de solidity 0.8.x, no se permite la conversión explícita de tipo de dirección a uint256. Así que usa uint256 i = uint256(uint160(address(msg.sender)));

Puede convertir la dirección a uint160, luego usar la biblioteca OpenZeppelin Strings.

Strings.toHexString(uint160(address), 20)

Referencia:

Enviar dirección a uint

Cadenas OpenZeppelin para bytes

Esto funciona con solidez 0.6.0

function addressToString(address _pool) public pure returns (string memory _uintAsString) {
      uint _i = uint256(_pool);
      if (_i == 0) {
          return "0";
      }
      uint j = _i;
      uint len;
      while (j != 0) {
          len++;
          j /= 10;
      }
      bytes memory bstr = new bytes(len);
      uint k = len - 1;
      while (_i != 0) {
          bstr[k--] = byte(uint8(48 + _i % 10));
          _i /= 10;
      }
      return string(bstr);
    }

Funciona pero atención: returns (string memory _uintAsString)!!! por lo que es un int, no la cadena de dirección como cabría esperar a primera vista. Esto también significa que si su dirección comienza con uno o más ceros (0x 0 A1bC4...), convertirlo a un int y luego volver a hexadecimal (dirección) nuevamente resultará en la falta de este 0 inicial. Necesitará algo como esto: '0x' + BigInt(ethAddressAsInt).toString(16).padStart(40, '0')(siendo 40 la longitud de una dirección ethereum, excluyendo el "0x")
¿Podría editar la respuesta para incluir esto en la función?
usando solidity 8.7, esto no se compila. Da "error del analizador - expresión primaria esperada" en bstr[k--] = byte(uint8(48 + _i % 10)); ]