92

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.

  1. Is there a way to tell a typo is occurred?
  2. 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.

1

9 Answers 9

84

Updates (June 2023)

web3.utils.isAddress will soon be deprecated. Please use web3-validator package instead. Example:

import { isAddress } from 'web3-validator';

isAddress('blah');

Using a Library (June 2016)

Libraries like web3.js and ethers have isAddress().

Examples:

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

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

The following is an answer from 2016.

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
}
14
  • 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
    Commented Feb 15, 2016 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
    Commented May 8, 2016 at 6:29
  • 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
    Commented Oct 17, 2017 at 8:02
  • 1
    @Alper Yes a smart contract address can be capitalized according to EIP 55, example.
    – eth
    Commented Apr 15, 2018 at 7:01
  • 1
    @OleksandrGrin Thanks for your comment. I would also use a library; I've modified this answer to show 2 examples.
    – eth
    Commented Jun 9, 2022 at 9:59
52

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.

2
  • 2
    The isaddress() method also checks for checksum! why do we need go with checkSum method?
    – atul
    Commented Mar 31, 2020 at 2:44
  • 1
    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. As @atul stated Commented Nov 1, 2020 at 16:56
9

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

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

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

2
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.

2

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.

1

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'
2
  • It should be from eth_keys import keys. I would have edited, but edits must be at least six characters.
    – Josh Davis
    Commented Dec 7, 2021 at 18:52
  • @JoshDavis you are absolutley right! Thanks for the note I just corrected it. Commented Dec 8, 2021 at 19:59
0

Or in Python (with Web3py)

from web3 import Web3

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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