Skip to content
This repository has been archived by the owner on Jun 17, 2021. It is now read-only.

Commit

Permalink
Enforce hex prefixing for address strings
Browse files Browse the repository at this point in the history
  • Loading branch information
cgewecke committed Apr 24, 2020
1 parent 3bbc948 commit 11fc1c1
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 16 deletions.
8 changes: 4 additions & 4 deletions docs/modules/_account_.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ ___

*Defined in [account.ts:20](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L20)*

Checks if the address is a valid. Accepts checksummed addresses too.
Checks if the hex-prefixed address is a valid. Accepts checksummed addresses too.

**Parameters:**

Expand All @@ -134,7 +134,7 @@ ___

*Defined in [account.ts:66](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L66)*

Checks if the address is a valid checksummed address.
Checks if the hex-prefixed address is a valid checksummed address.

See toChecksumAddress' documentation for details about the eip1191ChainId parameter.

Expand Down Expand Up @@ -193,7 +193,7 @@ ___

*Defined in [account.ts:27](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L27)*

Checks if a given address is a zero address.
Checks if a given hex-prefixed address is a zero address.

**Parameters:**

Expand Down Expand Up @@ -267,7 +267,7 @@ ___

*Defined in [account.ts:42](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L42)*

Returns a checksummed address.
Returns a checksummed address. (Input address must be hex-prefixed.)

If a eip1191ChainId is provided, the chainId will be included in the checksum calculation. This
has the effect of checksummed addresses for one chain having invalid checksums for others.
Expand Down
25 changes: 16 additions & 9 deletions src/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ const ethjsUtil = require('ethjs-util')
import * as assert from 'assert'
import * as secp256k1 from 'secp256k1'
import * as BN from 'bn.js'
import { toBuffer, addHexPrefix, zeros, bufferToHex, unpad } from './bytes'
import { toBuffer, zeros, bufferToHex, unpad } from './bytes'
import { keccak, keccak256, rlphash } from './hash'
import { assertIsHexString } from './helpers'

/**
* Returns a zero address.
Expand All @@ -17,16 +18,18 @@ export const zeroAddress = function(): string {
/**
* Checks if the address is a valid. Accepts checksummed addresses too.
*/
export const isValidAddress = function(address: string): boolean {
return /^0x[0-9a-fA-F]{40}$/.test(address)
export const isValidAddress = function(hexAddress: string): boolean {
assertIsHexString(hexAddress)
return /^0x[0-9a-fA-F]{40}$/.test(hexAddress)
}

/**
* Checks if a given address is a zero address.
*/
export const isZeroAddress = function(address: string): boolean {
export const isZeroAddress = function(hexAddress: string): boolean {
assertIsHexString(hexAddress)
const zeroAddr = zeroAddress()
return zeroAddr === addHexPrefix(address)
return zeroAddr === hexAddress
}

/**
Expand All @@ -39,8 +42,9 @@ export const isZeroAddress = function(address: string): boolean {
* WARNING: Checksums with and without the chainId will differ. As of 2019-06-26, the most commonly
* used variation in Ethereum was without the chainId. This may change in the future.
*/
export const toChecksumAddress = function(address: string, eip1191ChainId?: number): string {
address = ethjsUtil.stripHexPrefix(address).toLowerCase()
export const toChecksumAddress = function(hexAddress: string, eip1191ChainId?: number): string {
assertIsHexString(hexAddress)
const address = ethjsUtil.stripHexPrefix(hexAddress).toLowerCase()

const prefix = eip1191ChainId !== undefined ? eip1191ChainId.toString() + '0x' : ''

Expand All @@ -63,8 +67,11 @@ export const toChecksumAddress = function(address: string, eip1191ChainId?: numb
*
* See toChecksumAddress' documentation for details about the eip1191ChainId parameter.
*/
export const isValidChecksumAddress = function(address: string, eip1191ChainId?: number): boolean {
return isValidAddress(address) && toChecksumAddress(address, eip1191ChainId) === address
export const isValidChecksumAddress = function(
hexAddress: string,
eip1191ChainId?: number,
): boolean {
return isValidAddress(hexAddress) && toChecksumAddress(hexAddress, eip1191ChainId) === hexAddress
}

/**
Expand Down
12 changes: 12 additions & 0 deletions src/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const ethjsUtil = require('ethjs-util')

/**
* Throws if a string is not hex prefixed
* @param {string} input string to check hex prefix of
*/
export const assertIsHexString = function(input: string): void {
const msg = `This method only supports 0x-prefixed hex strings but input was: ${input}`
if (!ethjsUtil.isHexString(input)) {
throw new Error(msg)
}
}
39 changes: 36 additions & 3 deletions test/account.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,14 @@ describe('.toChecksumAddress()', function() {
}
})
})

describe('input format', function() {
it('Should throw when the address is not hex-prefixed', function() {
assert.throws(function() {
toChecksumAddress('52908400098527886E0F7030069857D2E4169EE7'.toLowerCase())
})
})
})
})

describe('.isValidChecksumAddress()', function() {
Expand Down Expand Up @@ -513,6 +521,14 @@ describe('.isValidChecksumAddress()', function() {
}
})
})

describe('input format', function() {
it('Should throw when the address is not hex-prefixed', function() {
assert.throws(function() {
isValidChecksumAddress('2f015c60e0be116b1f0cd534704db9c92118fb6a')
})
})
})
})

describe('.isValidAddress()', function() {
Expand All @@ -521,10 +537,27 @@ describe('.isValidAddress()', function() {
assert.equal(isValidAddress('0x52908400098527886E0F7030069857D2E4169EE7'), true)
})
it('should return false', function() {
assert.equal(isValidAddress('2f015c60e0be116b1f0cd534704db9c92118fb6a'), false)
assert.equal(isValidAddress('0x2f015c60e0be116b1f0cd534704db9c92118fb6'), false)
assert.equal(isValidAddress('0x2f015c60e0be116b1f0cd534704db9c92118fb6aa'), false)
assert.equal(isValidAddress('0X52908400098527886E0F7030069857D2E4169EE7'), false)
assert.equal(isValidAddress('x2f015c60e0be116b1f0cd534704db9c92118fb6a'), false)
})
it('should throw when input is not hex prefixed', function() {
assert.throws(function() {
isValidAddress('2f015c60e0be116b1f0cd534704db9c92118fb6a')
})
assert.throws(function() {
isValidAddress('x2f015c60e0be116b1f0cd534704db9c92118fb6a')
})
assert.throws(function() {
isValidAddress('0X52908400098527886E0F7030069857D2E4169EE7')
})
})
it('error message should have correct format', function() {
const input = '2f015c60e0be116b1f0cd534704db9c92118fb6a'
try {
isValidAddress('2f015c60e0be116b1f0cd534704db9c92118fb6a')
} catch (err) {
assert(err.message.includes('only supports 0x-prefixed hex strings'))
assert(err.message.includes(input))
}
})
})
6 changes: 6 additions & 0 deletions test/bytes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ describe('is zero address', function() {
const nonZeroAddress = '0x2f015c60e0be116b1f0cd534704db9c92118fb6a'
assert.equal(isZeroAddress(nonZeroAddress), false)
})

it('should throw when address is not hex-prefixed', function() {
assert.throws(function() {
isZeroAddress('0000000000000000000000000000000000000000')
})
})
})

describe('unpad', function() {
Expand Down

0 comments on commit 11fc1c1

Please sign in to comment.