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

Enforce hex prefixing for address strings #241

Merged
merged 2 commits into from
Apr 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 } from './bytes'
import { toBuffer, zeros, bufferToHex } 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 @@ -446,6 +446,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 @@ -486,6 +494,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 @@ -494,10 +510,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')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. 👍

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