57

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.

50

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? – ZMitton Feb 15 '16 at 11:07
  • 1
    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." – eth May 8 '16 at 6:29
  • 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?) – Paul S Jul 6 '16 at 3:40
  • 1
    @PedroLobito For sha3, you can use keccak256 from a library like github.com/emn178/js-sha3 I have not been able to find the recent code that Geth uses to improve this answer. – eth Oct 17 '17 at 8:02
  • 1
    @Alper Yes a smart contract address can be capitalized according to EIP 55, example. – eth Apr 15 '18 at 7:01
33

There is an easier way now with web3:

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

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

OR
Better version
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) 
}

using checkSum method is better because you will always deal with data and never have to lowerCase.

8

The standard 40 character hex addresses now have a checksum in the form of capitalization. If the address has at least one capital letter then it is checksummed and, if inputted on a site that checks the sum, it will return false if it's not a valid address.

The scheme is as follows:

convert the address to hex, but if the ith digit is a letter (ie. it's one of abcdef) print it in uppercase if the ith bit of the hash of the address (in binary form) is 1 otherwise print it in lowercase

You can read VBs full writeup here: https://github.com/ethereum/EIPs/issues/55

5

The python package 'ethereum' has a function called 'check_checksum' in the utils module:

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

I build a small project for this which i use programmatically in my apps. It has a 'micro' api:

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

It also has address validation for bitcoin, monero, and ripple.

You can find the documentation here: balidator.io/api-documentation

4
function validateInputAddresses(address) {
        return (/^(0x){1}[0-9a-fA-F]{40}$/i.test(address));
}
  • This just test plausibility, doesn't validate the checksum. It still seems to be a better way to write the plausibility test regex. – Simeon Mar 21 '18 at 11:23
2

So far ether addresses have no checksum and are simply the HEX encoding of the address bytes. There is however a proposal for encoding and checksum, see: ICAP: Inter exchange Client Address Protocol.

ICAP has preliminary support merged in some Ethereum client.

1

Checksums are mechanisms to prevent sending funds to wrong addresses (set by mistake or by a malicious party).

Programmatically

You can use web3's amazing utils:

web3.utils.toChecksumAddress(value)

The function above works only if you have version 1.0.0 or above.

Web

I created an online tool, check it out here: EthSum.

0

Another way to check is if you also have the public key of the ethereum address. The Ethereum Foundation's official eth-keys Python library can be used, and is now part of their Github repo and can be seen here and contains a suite of tools that include ways to check address validity, such as using the PublicKey().checksum_address() method (see below example).

The following method requires the uncompressed public key in bytes format, which means it would have to be only for accounts you have the public-key data for:

 >>>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'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.