¿Cómo puedo comprobar si una dirección de Ethereum es válida?

He leído muchas veces que nunca debes ingresar una dirección a mano a menos que quieras enviar Ether accidentalmente a tierra de nadie. Me gustaría saber cuáles podrían ser esas sumas de verificación. ¿Hay alguna forma de saber que se ha producido un error tipográfico? ¿Cómo y cuáles son las reglas de formato? Estoy preguntando para poder crear una función contenedora que verifique estas cosas antes de enviarlas a la red.

Medio relacionado.com/@piyopiyo/…

Respuestas (9)

Usar una biblioteca

Bibliotecas como web3.js y ethers tienen isAddress().

Ejemplos:

  • ethers.utils.isAddress('0x8ba1f109551bd432803012645ac136ddd64dba72');// verdadero

  • web3.utils.isAddress('blah');// falso

La siguiente es una respuesta de 2016.

Dirección habitual

EIP 55 agregó una "suma de verificación basada en mayúsculas" que fue implementada por Geth en mayo de 2016. Aquí está el código Javascript de Geth:

/**
 * Checks if the given string is an address
 *
 * @method isAddress
 * @param {String} address the given HEX adress
 * @return {Boolean}
*/
var isAddress = function (address) {
    if (!/^(0x)?[0-9a-f]{40}$/i.test(address)) {
        // check if it has the basic requirements of an address
        return false;
    } else if (/^(0x)?[0-9a-f]{40}$/.test(address) || /^(0x)?[0-9A-F]{40}$/.test(address)) {
        // If it's all small caps or all all caps, return true
        return true;
    } else {
        // Otherwise check each case
        return isChecksumAddress(address);
    }
};

/**
 * Checks if the given string is a checksummed address
 *
 * @method isChecksumAddress
 * @param {String} address the given HEX adress
 * @return {Boolean}
*/
var isChecksumAddress = function (address) {
    // Check each case
    address = address.replace('0x','');
    var addressHash = sha3(address.toLowerCase());
    for (var i = 0; i < 40; i++ ) {
        // the nth letter should be uppercase if the nth digit of casemap is 1
        if ((parseInt(addressHash[i], 16) > 7 && address[i].toUpperCase() !== address[i]) || (parseInt(addressHash[i], 16) <= 7 && address[i].toLowerCase() !== address[i])) {
            return false;
        }
    }
    return true;
};

Dirección ICAP

ICAP tiene una suma de verificación que se puede verificar. Puede revisar icap.go de Geth y aquí hay un fragmento de él:

// https://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN
func validCheckSum(s string) error {
    s = join(s[4:], s[:4])
    expanded, err := iso13616Expand(s)
    if err != nil {
        return err
    }
    checkSumNum, _ := new(big.Int).SetString(expanded, 10)
    if checkSumNum.Mod(checkSumNum, Big97).Cmp(Big1) != 0 {
        return ICAPChecksumError
    }
    return nil
}
¡Gran respuesta! Por curiosidad, ¿alguna idea de lo buena que es la suma de comprobación? es decir, con algunos dígitos incorrectos, ¿cuáles son las posibilidades de que pase la suma de verificación coincidentemente de todos modos?
EIP 55 compara la suma de verificación de la dirección regular con ICAP: "En promedio, habrá 15 bits de verificación por dirección, y la probabilidad neta de que una dirección generada aleatoriamente si se escribe mal accidentalmente pase una verificación es 0.0247%. Esta es una mejora de ~50x sobre ICAP , pero no tan bueno como un código de verificación de 4 bytes".
Sería bueno poder verificar la validez en Solidity también. Una forma de hacer esto sería transferir una pequeña cantidad de éter a cualquier nueva dirección que cree y verificar si hay un saldo distinto de cero en Solidity. (¿Debería ser una pregunta aparte?)
@eth Mientras uso la función de dirección normal, recibo un ReferenceError: sha3 is not definederror, ¿alguna idea de por qué?
@PedroLobito Para sha3, puede usar keccak256desde una biblioteca como github.com/emn178/js-sha3 . No he podido encontrar el código reciente que usa Geth para mejorar esta respuesta.
¡Lo haré, gracias!
sha3la función no está definida. Se usa en la función checkSumAddress en la respuesta.var addressHash = sha3(address.toLowerCase());
@DenisMatafonov Estás preguntando lo mismo que Pablo... ethereum.stackexchange.com/questions/1374/…
@eth no era una pregunta, era un comentario de que el código proporcionado en la respuesta no es válido. Y lo peor de todo, que funciona la mayor parte del tiempo, excepto en los casos en que la dirección no cae en primero y segundo ify else if. El enlace a sha3 lib debe incluirse en la respuesta.
@eth Estoy tratando de usar esta lib github.com/Caligatio/jsSHA para sha3, pero parece que no funciona con su código. ¿Podrías ayudarme con esto?
¿Esto también funciona para la dirección del contrato inteligente? @eth
@Alper Sí, una dirección de contrato inteligente se puede capitalizar de acuerdo con EIP 55, ejemplo .
mala respuesta, ¡este código falla en la validación incluso de direcciones válidas! la siguiente respuesta con web3.utils.isAddress es mucho mejor y más fácil
@OleksandrGrin Gracias por tu comentario. También usaría una biblioteca; He modificado esta respuesta para mostrar 2 ejemplos.

Hay una manera más fácil ahora con web3:

Ingenuo:
https://web3js.readthedocs.io/en/v1.2.0/web3-utils.html#isaddress

web3.utils.isAddress('0xc1912fee45d61c87cc5ea59dae31190fffff232d');
> true

O
Mejor versión
https://web3js.readthedocs.io/en/v1.2.0/web3-utils.html#tochecksumaddress

try {
  const address = web3.utils.toChecksumAddress(rawInput)
} catch(e) { 
  console.error('invalid ethereum address', e.message) 
}

usar el método checkSum es mejor porque siempre tratará con datos y nunca tendrá que usar minúsculas.

¡El método isaddress() también comprueba la suma de comprobación! ¿Por qué necesitamos ir con el método checkSum?
isAddress: Checks if a given string is a valid Ethereum address. It will also check the checksum, if the address has upper and lowercase letters.Como dijo @atul

Las direcciones hexadecimales estándar de 40 caracteres ahora tienen una suma de verificación en forma de mayúsculas. Si la dirección tiene al menos una letra mayúscula, se realiza una suma de verificación y, si se ingresa en un sitio que verifica la suma, devolverá falso si no es una dirección válida.

El esquema es el siguiente:

convierta la dirección a hexadecimal, pero si el iésimo dígito es una letra (es decir, es uno de abcdef) imprímalo en mayúsculas si el iésimo bit del hash de la dirección (en forma binaria) es 1 de lo contrario imprímalo en minúsculas

Puede leer el artículo completo de VB aquí: https://github.com/ethereum/EIPs/issues/55

function validateInputAddresses(address) {
        return (/^(0x){1}[0-9a-fA-F]{40}$/i.test(address));
}
Esto solo prueba la plausibilidad, no valida la suma de verificación. Todavía parece ser una mejor manera de escribir la expresión regular de prueba de plausibilidad.

El paquete de python 'ethereum' tiene una función llamada 'check_checksum' en el módulo utils:

from ethereum.utils import check_checksum
check_checksum('0xc1912fee45d61c87cc5ea59dae31190fffff232d')
> True

Construyo un pequeño proyecto para esto que uso programáticamente en mis aplicaciones. Tiene una API 'micro':

https://balidator.io/api/ethereum/0xea0258D0E745620e77B0A389e3A656EFdb7Cf821

También tiene validación de dirección para bitcoin, monero y ripple.

Puede encontrar la documentación aquí: balidator.io/api-documentation

La biblioteca python Web3 también tiene métodos de verificación de direcciones. web3py.readthedocs.io/en/latest/…
balidator.io no se encuentra

Hasta ahora, las direcciones ether no tienen suma de verificación y son simplemente la codificación HEX de los bytes de la dirección. Sin embargo, existe una propuesta para la codificación y la suma de comprobación, véase: ICAP: Inter Exchange Client Address Protocol .

ICAP tiene soporte preliminar fusionado en algún cliente de Ethereum.

Las sumas de verificación son mecanismos para evitar el envío de fondos a direcciones incorrectas (establecidas por error o por una parte malintencionada).

Programáticamente

Puedes usar web3las increíbles utilidades de:

web3.utils.toChecksumAddress(valor)

La función anterior solo funciona si tiene una versión 1.0.0o superior.

Web

Creé una herramienta en línea, échale un vistazo aquí: EthSum .

Otra forma de verificar es si también tiene la clave pública de la dirección de ethereum. Se puede usar la biblioteca Python oficial de la Fundación Ethereum eth-keys, y ahora es parte de su repositorio de Github y se puede ver aquí y contiene un conjunto de herramientas que incluyen formas de verificar la validez de la dirección, como usar el PublicKey().checksum_address()método (vea el ejemplo a continuación).

El siguiente método requiere la clave pública sin comprimir en formato de bytes, lo que significa que tendría que ser solo para las cuentas para las que tiene los datos de la clave pública:

 >>>from eth_keys import keys
 
 >>>keys.PublicKey(b'\x98\xbb\xfa\xdd\xbc\xc7\xab\x14\xa3\x9c\xb4\x84\xbf\x94MO\xf5\x91^G\xc1\xc2\x0b\xe77t\xc3\xd0\x05\x12|Z\xf5\x17PZ\x97\xe2\\`IR\xc1\xbd\x10\xa3\xa3\xdf\xbf0\xaf;7\xc0z\xbc\xc7\x0b\x9c\xbd<FY\x98').to_checksum_address()
        
        '0x28f4961F8b06F7361A1efD5E700DE717b1db5292'
debería from eth_keys import keysser Habría editado, pero las ediciones deben tener al menos seis caracteres.
@JoshDavis, ¡tienes toda la razón! Gracias por la nota, la acabo de corregir.

O en Python (con Web3py )

from web3 import Web3

print(Web3.isAddress("0xBB9923E927F0bC33C901396F4C589B43DB991705"))