Skip to content

Commit

Permalink
Merge pull request #82 from tabookey/rebase_master_solidityPack-array…
Browse files Browse the repository at this point in the history
…s-27_tabookey_AUG2019

Rebase on master "solidity pack arrays" + fixes
  • Loading branch information
holgerd77 committed Aug 11, 2019
2 parents 8431eab + 7a0ac94 commit d700d09
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 45 deletions.
114 changes: 69 additions & 45 deletions lib/index.js
Expand Up @@ -447,61 +447,85 @@ ABI.stringify = function (types, values) {
return ret
}

ABI.solidityHexValue = function (type, value, bitsize) {
// pass in bitsize = null if use default bitsize
var size, num
if (isArray(type)) {
var subType = type.replace(/\[.*?\]/, '')
if (!isArray(subType)) {
var arraySize = parseTypeArray(type)
if (arraySize !== 'dynamic' && arraySize !== 0 && value.length > arraySize) {
throw new Error('Elements exceed array size: ' + arraySize)
}
}
var arrayValues = value.map(function (v) {
return ABI.solidityHexValue(subType, v, 256)
})
return Buffer.concat(arrayValues)
} else if (type === 'bytes') {
return value
} else if (type === 'string') {
return Buffer.from(value, 'utf8')
} else if (type === 'bool') {
bitsize = bitsize || 8
var padding = Array((bitsize) / 4).join('0')
return Buffer.from(value ? padding + '1' : padding + '0', 'hex')
} else if (type === 'address') {
var bytesize = 20
if (bitsize) {
bytesize = bitsize / 8
}
return utils.setLengthLeft(value, bytesize)
} else if (type.startsWith('bytes')) {
size = parseTypeN(type)
if (size < 1 || size > 32) {
throw new Error('Invalid bytes<N> width: ' + size)
}

return utils.setLengthRight(value, size)
} else if (type.startsWith('uint')) {
size = parseTypeN(type)
if ((size % 8) || (size < 8) || (size > 256)) {
throw new Error('Invalid uint<N> width: ' + size)
}

num = parseNumber(value)
if (num.bitLength() > size) {
throw new Error('Supplied uint exceeds width: ' + size + ' vs ' + num.bitLength())
}

bitsize = bitsize || size
return num.toArrayLike(Buffer, 'be', bitsize / 8)
} else if (type.startsWith('int')) {
size = parseTypeN(type)
if ((size % 8) || (size < 8) || (size > 256)) {
throw new Error('Invalid int<N> width: ' + size)
}

num = parseNumber(value)
if (num.bitLength() > size) {
throw new Error('Supplied int exceeds width: ' + size + ' vs ' + num.bitLength())
}

bitsize = bitsize || size
return num.toTwos(size).toArrayLike(Buffer, 'be', bitsize / 8)
} else {
// FIXME: support all other types
throw new Error('Unsupported or invalid type: ' + type)
}
}

ABI.solidityPack = function (types, values) {
if (types.length !== values.length) {
throw new Error('Number of types are not matching the values')
}

var size, num
var ret = []

for (var i = 0; i < types.length; i++) {
var type = elementaryName(types[i])
var value = values[i]

if (type === 'bytes') {
ret.push(value)
} else if (type === 'string') {
ret.push(Buffer.from(value, 'utf8'))
} else if (type === 'bool') {
ret.push(Buffer.from(value ? '01' : '00', 'hex'))
} else if (type === 'address') {
ret.push(utils.setLengthLeft(value, 20))
} else if (type.startsWith('bytes')) {
size = parseTypeN(type)
if (size < 1 || size > 32) {
throw new Error('Invalid bytes<N> width: ' + size)
}

ret.push(utils.setLengthRight(value, size))
} else if (type.startsWith('uint')) {
size = parseTypeN(type)
if ((size % 8) || (size < 8) || (size > 256)) {
throw new Error('Invalid uint<N> width: ' + size)
}

num = parseNumber(value)
if (num.bitLength() > size) {
throw new Error('Supplied uint exceeds width: ' + size + ' vs ' + num.bitLength())
}

ret.push(num.toArrayLike(Buffer, 'be', size / 8))
} else if (type.startsWith('int')) {
size = parseTypeN(type)
if ((size % 8) || (size < 8) || (size > 256)) {
throw new Error('Invalid int<N> width: ' + size)
}

num = parseNumber(value)
if (num.bitLength() > size) {
throw new Error('Supplied int exceeds width: ' + size + ' vs ' + num.bitLength())
}

ret.push(num.toTwos(size).toArrayLike(Buffer, 'be', size / 8))
} else {
// FIXME: support all other types
throw new Error('Unsupported or invalid type: ' + type)
}
ret.push(ABI.solidityHexValue(type, value, null))
}

return Buffer.concat(ret)
Expand Down
55 changes: 55 additions & 0 deletions test/index.js
Expand Up @@ -511,6 +511,61 @@ describe('solidity tight packing multiple arguments', function () {
})
})

describe('solidity tight packing uint32[]', function () {
it('should equal', function () {
var a = abi.solidityPack(
['uint32[]'],
[[8, 9]]
)
var b = '00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009'
assert.strict.equal(a.toString('hex'), b.toString('hex'))
})
})

describe('solidity tight packing bool[][]', function () {
it('should equal', function () {
let a = abi.solidityPack(
['bool[][]'],
[[[true, false], [false, true]]]
)
let b = '0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001'
assert.strict.equal(a.toString('hex'), b.toString('hex'))
})
})

describe('solidity tight packing address[]', function () {
it('should equal', function () {
let a = abi.solidityPack(
['address[]'],
[[new BN('43989fb883ba8111221e89123897538475893837', 16)]]
)
let b = '00000000000000000000000043989fb883ba8111221e89123897538475893837'
assert.strict.equal(a.toString('hex'), b.toString('hex'))
})
})

describe('solidity tight packing uint32[2]', function () {
it('should equal', function () {
let a = abi.solidityPack(
['uint32[2]'],
[[11, 12]]
)
let b = '000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c'
assert.strict.equal(a.toString('hex'), b.toString('hex'))
})
})

describe('solidity tight packing uint32[2] with wrong array length', function () {
it('should throw', function () {
assert.throws(function () {
abi.solidityPack(
['uint32[2]'],
[[11, 12, 13]]
)
})
})
})

describe('solidity tight packing sha3', function () {
it('should equal', function () {
var a = abi.soliditySHA3(
Expand Down

0 comments on commit d700d09

Please sign in to comment.