Skip to content

Commit

Permalink
chore: fix hex parsing in addresses using upper cased letters [A-F] (#38
Browse files Browse the repository at this point in the history
)

* run test

* fix tests, add typings, parse lower case hex
  • Loading branch information
menduz authored Feb 23, 2021
1 parent 18eab03 commit 536c280
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 26 deletions.
41 changes: 27 additions & 14 deletions src/solidity/coder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,18 +101,23 @@ export class SolidityCoder {
return result
}

encodeMultiWithOffset(types: string[], solidityTypes: SolidityType<any>[], encodeds: any[][], _dynamicOffset: number) {
encodeMultiWithOffset(
types: string[],
solidityTypes: SolidityType<any>[],
encodeds: (string | string[])[],
_dynamicOffset: number
): string {
let dynamicOffset = _dynamicOffset
let result = ''
let results: string[] = []

types.forEach((_, i) => {
if (isDynamic(solidityTypes[i], types[i])) {
result += formatter.formatInputInt(dynamicOffset).encode()
results.push(formatter.formatInputInt(dynamicOffset).encode())
let e = this.encodeWithOffset(types[i], solidityTypes[i], encodeds[i], dynamicOffset)
dynamicOffset += e.length / 2
} else {
// don't add length to dynamicOffset. it's already counted
result += this.encodeWithOffset(types[i], solidityTypes[i], encodeds[i], dynamicOffset)
results.push(this.encodeWithOffset(types[i], solidityTypes[i], encodeds[i], dynamicOffset))
}

// TODO: figure out nested arrays
Expand All @@ -122,14 +127,14 @@ export class SolidityCoder {
if (isDynamic(solidityTypes[i], types[i])) {
let e = this.encodeWithOffset(types[i], solidityTypes[i], encodeds[i], dynamicOffset)
dynamicOffset += e.length / 2
result += e
results.push(e)
}
})
return result
return results.join('')
}

// tslint:disable-next-line:prefer-function-over-method
encodeWithOffset(type: string, solidityType: SolidityType<any>, encoded: any[], offset: number) {
encodeWithOffset(type: string, solidityType: SolidityType<any>, encoded: string | string[], offset: number): string {
/* jshint maxcomplexity: 17 */
/* jshint maxdepth: 5 */

Expand All @@ -144,7 +149,11 @@ export class SolidityCoder {
if (mode !== encodingMode.other) {
let nestedName = solidityType.nestedName(type)
let nestedStaticPartLength = solidityType.staticPartLength(nestedName)
let result = mode === encodingMode.dynamic ? encoded[0] : ''
let results: string[] = []

if (mode === encodingMode.dynamic) {
results.push(encoded[0] as string)
}

if (solidityType.isDynamicArray(nestedName)) {
let previousLength = mode === encodingMode.dynamic ? 2 : 0
Expand All @@ -156,24 +165,28 @@ export class SolidityCoder {
} else if (mode === encodingMode.static) {
previousLength += +(encoded[i - 1] || [])[0] || 0
}
result += formatter.formatInputInt(offset + i * nestedStaticPartLength + previousLength * 32).encode()
results.push(formatter.formatInputInt(offset + i * nestedStaticPartLength + previousLength * 32).encode())
}
}

let len = mode === encodingMode.dynamic ? encoded.length - 1 : encoded.length
for (let c = 0; c < len; c++) {
let additionalOffset = result / 2
let additionalOffset = results.join('').length / 2
if (mode === encodingMode.dynamic) {
result += this.encodeWithOffset(nestedName, solidityType, encoded[c + 1], offset + additionalOffset)
results.push(this.encodeWithOffset(nestedName, solidityType, encoded[c + 1], offset + additionalOffset))
} else if (mode === encodingMode.static) {
result += this.encodeWithOffset(nestedName, solidityType, encoded[c], offset + additionalOffset)
results.push(this.encodeWithOffset(nestedName, solidityType, encoded[c], offset + additionalOffset))
}
}

return result
return results.join('')
}

if (typeof encoded != 'string') {
throw new Error('Encoded is not string')
}

return encoded
return encoded as any
}

/**
Expand Down
13 changes: 11 additions & 2 deletions src/solidity/formatters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,21 @@ import { inputAddressFormatter } from '../utils/formatters'
*/
export function formatInputInt(value: BigNumber.Value) {
BigNumber.config(config.ETH_BIGNUMBER_ROUNDING_MODE)

let result = utils.padLeft(utils.toTwosComplement(value).toString(16), 64)
return new SolidityParam(result)

const ret = new SolidityParam(result)

if (ret.value.indexOf('NaN') != -1) {
throw new Error(`The number ${JSON.stringify(value)} can't be parsed.`)
}

return ret
}

export function formatInputAddress(value: string) {
return formatInputInt(inputAddressFormatter(value))
if (typeof value != 'string') throw new Error('The input must be a valid address, got: ' + JSON.stringify(value))
return formatInputInt(inputAddressFormatter(value.trim()))
}

/**
Expand Down
6 changes: 3 additions & 3 deletions src/solidity/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ export abstract class SolidityType<ValueType> {
* @param {string} name
* @return {string} encoded value
*/
encode(value: any, name: string): any {
encode(value: any, name: string): string | string[] {
if (this.isDynamicArray(name)) {
let length = value.length // in int
let nestedName = this.nestedName(name)
Expand All @@ -177,9 +177,9 @@ export abstract class SolidityType<ValueType> {
let length = this.staticArrayLength(name) // in int
let nestedName = this.nestedName(name)

let result = []
let result: string[] = []
for (let i = 0; i < length; i++) {
result.push(this.encode(value[i], nestedName))
result.push(this.encode(value[i], nestedName) as string)
}

return result
Expand Down
8 changes: 6 additions & 2 deletions src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -403,11 +403,15 @@ export function toBigNumber(_num: BigNumber.Value): BigNumber {
return num as BigNumber
}

if (typeof num === 'string') {
num = num.trim()
}

if (typeof num === 'string' && (num.indexOf('0x') === 0 || num.indexOf('-0x') === 0)) {
return new BigNumber(num.replace('0x', ''), 16)
return new BigNumber(num.replace('0x', '').toLowerCase(), 16)
}

return new BigNumber(num.toString(10), 10)
return new BigNumber(num, 10)
}

/**
Expand Down
12 changes: 12 additions & 0 deletions test/coder.decodeParam.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ describe('lib/solidity/coder', function() {
expected: '0x407d73d8a49eeb85d32cf465507dd71d507100c1',
value: '000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1'
})
test({
type: 'address',
expected: '0xbf79ce2fbd819e5abc2327563d02a200255b7cb3',
value: '000000000000000000000000bf79ce2fbd819e5abc2327563d02a200255b7cb3'
})
test({
type: 'address[2]',
expected: ['0x407d73d8a49eeb85d32cf465507dd71d507100c1', '0x407d73d8a49eeb85d32cf465507dd71d507100c3'],
Expand Down Expand Up @@ -539,6 +544,13 @@ describe('lib/solidity/coder', function() {
'000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1' +
'000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c3'
})
test({
types: ['address', 'address'],
expected: ['0x6224fe0bea79701d338cf65ebc0da0caa566c544', '0xBF79cE2fbd819e5aBC2327563D02a200255B7Cb3'],
values:
'0000000000000000000000006224fe0bea79701d338cf65ebc0da0caa566c544' +
'000000000000000000000000BF79cE2fbd819e5aBC2327563D02a200255B7Cb3'
})
test({
types: ['bool[2]', 'bool[3]'],
expected: [[true, false], [false, false, true]],
Expand Down
12 changes: 12 additions & 0 deletions test/coder.encodeParam.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ describe('lib/solidity/coder', function () {
value: '0x407d73d8a49eeb85d32cf465507dd71d507100c1',
expected: '000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1'
})
test({
type: 'address',
value: '0xBF79cE2fbd819e5aBC2327563D02a200255B7Cb3',
expected: '000000000000000000000000BF79cE2fbd819e5aBC2327563D02a200255B7Cb3'.toLowerCase()
})
test({
type: 'address[2]',
value: ['0xBF79cE2fbd819e5aBC2327563D02a200255B7Cb3', '0x407d73d8a49eeb85d32cf465507dd71d507100c3'],
expected:
'000000000000000000000000bf79ce2fbd819e5abc2327563d02a200255b7cb3' +
'000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c3'
})
test({
type: 'address[2]',
value: ['0x407d73d8a49eeb85d32cf465507dd71d507100c1', '0x407d73d8a49eeb85d32cf465507dd71d507100c3'],
Expand Down
13 changes: 12 additions & 1 deletion test/formatters.inputAddressFormatter.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import * as expect from 'expect'
import { coder } from '../src/solidity/coder'
import { formatInputAddress } from '../src/solidity/formatters'
import * as formatters from '../src/utils/formatters'

let tests = [
// { input: 'XE7338O073KYGTWWZN0F2WZ0R8PX5ZPPZS', result: '0x00c5496aee77c1ba1f0854206a26dda82a81d6d8' },
{ input: '0x00c5496aee77c1ba1f0854206a26dda82a81d6d8', result: '0x00c5496aee77c1ba1f0854206a26dda82a81d6d8' },
{ input: '00c5496aee77c1ba1f0854206a26dda82a81d6d8', result: '0x00c5496aee77c1ba1f0854206a26dda82a81d6d8' },
{ input: '0x11f4d0a3c12e86b4b5f39b213f7e19d048276dae', result: '0x11f4d0a3c12e86b4b5f39b213f7e19d048276dae' }
{ input: '0x11f4d0a3c12e86b4b5f39b213f7e19d048276dae', result: '0x11f4d0a3c12e86b4b5f39b213f7e19d048276dae' },
{ input: '0xBF79cE2fbd819e5aBC2327563D02a200255B7Cb3', result: '0xBF79cE2fbd819e5aBC2327563D02a200255B7Cb3' }
]

let errorTests = [
Expand Down Expand Up @@ -37,4 +40,12 @@ describe('formatters', function () {
})
})
})
describe('formatInputAddress', () => {
tests.forEach(function (test) {
it('formatInputAddress: ' + test.input, () => {
const t = formatInputAddress(test.input)
expect(coder.decodeParam('address', t.encode())).toEqual(test.result.toLowerCase())
})
})
})
})
26 changes: 26 additions & 0 deletions test/integration.erc20.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ function doTest(requestManager: RequestManager) {
})

it('test allowance', async function () {
requestManager.provider.debug = true
this.timeout(30000)
const accounts = await requestManager.eth_accounts()
const allowanceAddress = '0x0f5d2fb29fb7d3cfee444a200298f468908cc942'
Expand All @@ -215,4 +216,29 @@ function doTest(requestManager: RequestManager) {
expect(allowedNumber).toBeInstanceOf(BigNumber)
}
})

it('test allowance with malformed addressess', async function () {
this.timeout(30000)
const accounts = await requestManager.eth_accounts()
const account = ` ${accounts[0]} `
const allowanceAddress = ' 0x0f5d2fb29fb7d3cfee444a200298f468908cc942 \n'
{
console.log(`> allowance(${account},${allowanceAddress})`)
const allowedNumber: BigNumber = await ERC20Contract.allowance(account, allowanceAddress)
expect(allowedNumber).toBeInstanceOf(BigNumber)
}
})


it('test for allowance using DG parameters', async function () {
this.timeout(30000)
const account = `0x6224fe0bea79701d338cf65ebc0da0caa566c544`
const allowanceAddress = '0xBF79cE2fbd819e5aBC2327563D02a200255B7Cb3'
{
console.log(`> allowance(${account},${allowanceAddress})`)
const allowedNumber: BigNumber = await ERC20Contract.allowance(account, allowanceAddress)
expect(allowedNumber).toBeInstanceOf(BigNumber)
}
requestManager.provider.debug = false
})
}
6 changes: 3 additions & 3 deletions test/soldity.formatters.formatInputInt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ let tests = [
]

describe('formatters', function () {
describe('inputAddressFormatter', function () {
tests.forEach(function (test) {
it('should return the correct value', function () {
describe('formatInputInt', function () {
tests.forEach(function (test, i) {
it('should return the correct value: ' + i, function () {
expect(formatters.formatInputInt(test.input)).toEqual(test.result)
})
})
Expand Down
3 changes: 2 additions & 1 deletion test/utils.isAddress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ let tests = [
{ value: '0xE247a45c287191d435A8a5D72A7C8dc030451E9F', is: false },
{ value: '0xe247a45c287191d435a8a5d72a7c8dc030451e9f', is: true },
{ value: '0XE247A45C287191D435A8A5D72A7C8DC030451E9F', is: false },
{ value: '0xE247A45C287191D435A8A5D72A7C8DC030451E9F', is: true }
{ value: '0xE247A45C287191D435A8A5D72A7C8DC030451E9F', is: true },
{ value: '0xBF79cE2fbd819e5aBC2327563D02a200255B7Cb3', is: true }
]

describe('lib/utils/utils', function () {
Expand Down

0 comments on commit 536c280

Please sign in to comment.