How can I check if an Ethereum address is valid?

  • I've read many times that you should never input an address by hand unless you want to accidentally send Ether into no-mans-land. I'd like to know what those checksums might be. Is there a way to tell a typo is occurred? how, and what are the formatting rules to it? Im asking so I can potentially create a wrapper function that checks for these things before submitting to the network.

  • eth

    eth Correct answer

    5 years ago

    Regular Address

    EIP 55 added a "capitals-based checksum" which was implemented by Geth by May 2016. Here's Javascript code from 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;
    };
    

    ICAP Address

    ICAP has a checksum which can be verified. You can review Geth's icap.go and here's a snippet from it:

    // 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
    }
    

    Great answer! Out of curiosity, any idea how good the checksum is? meaning with a few wrong digits, what are the chances it passes the checksum coincidentally anyway?

    EIP 55 compares the regular address checksum with ICAP: "On average there will be 15 check bits per address, and the net probability that a randomly generated address if mistyped will accidentally pass a check is 0.0247%. This is a ~50x improvement over ICAP, but not as good as a 4-byte check code."

    It would be nice to be able to check for validity in Solidity as well. One way to do this would be to transfer a tiny amount of ether to any new address you create, and check for non-zero balance in Solidity. (Should that be a separate question?)

    @eth While using the regular address function I'm getting a `ReferenceError: sha3 is not defined` error, any idea why?

    @PedroLobito For sha3, you can use `keccak256` from a library like https://github.com/emn178/js-sha3 I have not been able to find the recent code that Geth uses to improve this answer.

    I'll do that, tks!

    `sha3` function is not defined. It is used in function checkSumAddress in the aswer. `var addressHash = sha3(address.toLowerCase());`

    @eth it wasnt a question, it was a remark that code, provided in the asnwer is not valid. And worst of all, that it _does_ work most of the time, except cases when address doesnt fall into fiorst and second `if` and `else if`. Link to sha3 lib should be included in the answer.

    @eth I am trying to use this lib https://github.com/Caligatio/jsSHA for `sha3`, but looks like it doesn't work with your code. Could you help me with this?

    Does this also works for smart-contract's address? @eth

    @Alper Yes a smart contract address can be capitalized according to EIP 55, example.

License under CC-BY-SA with attribution


Content dated before 7/24/2021 11:53 AM