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.
-
Related medium.com/@piyopiyo/…– Adrien BeJan 15, 2021 at 11:30
9 Answers
Using a Library
Libraries like web3.js and ethers have isAddress()
.
Examples:
ethers.utils.isAddress('0x8ba1f109551bd432803012645ac136ddd64dba72');
// trueweb3.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
}
-
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?– ZMittonFeb 15, 2016 at 11:07
-
1EIP 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, 2016 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 SJul 6, 2016 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, 2017 at 8:02 -
1
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.
-
2The isaddress() method also checks for checksum! why do we need go with checkSum method?– atulMar 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 Nov 1, 2020 at 16:56
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
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.– SimeonMar 21, 2018 at 11:23
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
-
The python Web3 library also has address checking methods. web3py.readthedocs.io/en/latest/… Mar 9, 2018 at 15:23
-
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.
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.
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'
-
It should be
from eth_keys import keys
. I would have edited, but edits must be at least six characters. Dec 7, 2021 at 18:52 -
@JoshDavis you are absolutley right! Thanks for the note I just corrected it. Dec 8, 2021 at 19:59
Or in Python (with Web3py)
from web3 import Web3
print(Web3.isAddress("0xBB9923E927F0bC33C901396F4C589B43DB991705"))