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 23, 2020
1 parent 3bbc948 commit ed7eb36
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 16 deletions.
21 changes: 19 additions & 2 deletions src/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ 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'

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

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

/**
Expand All @@ -40,6 +42,7 @@ export const isZeroAddress = function(address: string): boolean {
* used variation in Ethereum was without the chainId. This may change in the future.
*/
export const toChecksumAddress = function(address: string, eip1191ChainId?: number): string {
enforceHexString(address)
address = ethjsUtil.stripHexPrefix(address).toLowerCase()

const prefix = eip1191ChainId !== undefined ? eip1191ChainId.toString() + '0x' : ''
Expand Down Expand Up @@ -115,6 +118,9 @@ export const generateAddress2 = function(
* Returns true if the supplied address belongs to a precompiled account (Byzantium).
*/
export const isPrecompiled = function(address: Buffer | string): boolean {
if (typeof address === 'string') {
enforceHexString(address)
}
const a = unpad(address)
return a.length === 1 && a[0] >= 1 && a[0] <= 8
}
Expand Down Expand Up @@ -190,3 +196,14 @@ export const importPublic = function(publicKey: Buffer): Buffer {
}
return publicKey
}

/**
* Helper method which throws if a string is not hex prefixed
* @param {string} input string to check hex prefix of
*/
const enforceHexString = 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)
}
}
66 changes: 52 additions & 14 deletions test/account.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -377,28 +377,33 @@ describe('generateAddress2: EIP-1014 testdata examples', function() {

describe('isPrecompiled', function() {
it('should return true', function() {
assert.equal(isPrecompiled('0000000000000000000000000000000000000001'), true)
assert.equal(isPrecompiled('0000000000000000000000000000000000000002'), true)
assert.equal(isPrecompiled('0000000000000000000000000000000000000003'), true)
assert.equal(isPrecompiled('0000000000000000000000000000000000000004'), true)
assert.equal(isPrecompiled('0000000000000000000000000000000000000005'), true)
assert.equal(isPrecompiled('0000000000000000000000000000000000000006'), true)
assert.equal(isPrecompiled('0000000000000000000000000000000000000007'), true)
assert.equal(isPrecompiled('0000000000000000000000000000000000000008'), true)
assert.equal(isPrecompiled('0x0000000000000000000000000000000000000001'), true)
assert.equal(isPrecompiled('0x0000000000000000000000000000000000000002'), true)
assert.equal(isPrecompiled('0x0000000000000000000000000000000000000003'), true)
assert.equal(isPrecompiled('0x0000000000000000000000000000000000000004'), true)
assert.equal(isPrecompiled('0x0000000000000000000000000000000000000005'), true)
assert.equal(isPrecompiled('0x0000000000000000000000000000000000000006'), true)
assert.equal(isPrecompiled('0x0000000000000000000000000000000000000007'), true)
assert.equal(isPrecompiled('0x0000000000000000000000000000000000000008'), true)
assert.equal(
isPrecompiled(Buffer.from('0000000000000000000000000000000000000001', 'hex')),
true,
)
})
it('should return false', function() {
assert.equal(isPrecompiled('0000000000000000000000000000000000000000'), false)
assert.equal(isPrecompiled('0000000000000000000000000000000000000009'), false)
assert.equal(isPrecompiled('1000000000000000000000000000000000000000'), false)
assert.equal(isPrecompiled('0x0000000000000000000000000000000000000000'), false)
assert.equal(isPrecompiled('0x0000000000000000000000000000000000000009'), false)
assert.equal(isPrecompiled('0x1000000000000000000000000000000000000000'), false)
assert.equal(
isPrecompiled(Buffer.from('0000000000000000000000000000000000000000', 'hex')),
false,
)
})
it('should throw when address is string and not hex-prefixed', function() {
assert.throws(function() {
isPrecompiled('0000000000000000000000000000000000000001')
})
})
})

const eip55ChecksumAddresses = [
Expand Down Expand Up @@ -473,6 +478,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 +526,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 +542,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 ed7eb36

Please sign in to comment.